aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch103042
1 files changed, 0 insertions, 103042 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch
deleted file mode 100644
index 0e08821f..00000000
--- a/common/recipes-kernel/linux/linux-yocto-4.14.71/0020-drm-amd-dc-Add-dc-display-driver-v2.patch
+++ /dev/null
@@ -1,103042 +0,0 @@
-From 6d79af6264d44cb07e405fcc504fda8578887db1 Mon Sep 17 00:00:00 2001
-From: Harry Wentland <harry.wentland@amd.com>
-Date: Wed, 23 Aug 2017 15:53:40 -0400
-Subject: [PATCH 0020/4131] drm/amd/dc: Add dc display driver (v2)
-
-Supported DCE versions: 8.0, 10.0, 11.0, 11.2
-
-v2: rebase against 4.11
-
-Signed-off-by: Harry Wentland <harry.wentland@amd.com>
-Acked-by: Alex Deucher <alexander.deucher@amd.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-Signed-off-by: Kalyan Alle <kalyan.alle@amd.com>
----
- drivers/gpu/drm/amd/amdgpu/Kconfig | 1 +
- drivers/gpu/drm/amd/amdgpu/Makefile | 17 +-
- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 18 +
- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 96 +-
- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 28 +
- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 2 +-
- 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 | 29 +-
- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 +
- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 89 +-
- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3 +-
- drivers/gpu/drm/amd/amdgpu/cik.c | 9 +
- drivers/gpu/drm/amd/amdgpu/vi.c | 21 +
- drivers/gpu/drm/amd/display/Kconfig | 20 +
- drivers/gpu/drm/amd/display/Makefile | 22 +
- drivers/gpu/drm/amd/display/amdgpu_dm/Makefile | 17 +
- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1584 ++++++++
- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 171 +
- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 483 +++
- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 829 ++++
- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 122 +
- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 445 +++
- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 36 +
- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 463 +++
- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3312 +++++++++++++++
- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 101 +
- drivers/gpu/drm/amd/display/dc/Makefile | 28 +
- drivers/gpu/drm/amd/display/dc/basics/Makefile | 11 +
- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 223 ++
- drivers/gpu/drm/amd/display/dc/basics/conversion.h | 51 +
- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 691 ++++
- drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c | 221 +
- .../gpu/drm/amd/display/dc/basics/grph_object_id.c | 134 +
- .../gpu/drm/amd/display/dc/basics/log_helpers.c | 100 +
- drivers/gpu/drm/amd/display/dc/basics/logger.c | 457 +++
- drivers/gpu/drm/amd/display/dc/basics/logger.h | 67 +
- .../drm/amd/display/dc/basics/register_logger.c | 197 +
- .../gpu/drm/amd/display/dc/basics/signal_types.c | 116 +
- drivers/gpu/drm/amd/display/dc/basics/vector.c | 307 ++
- drivers/gpu/drm/amd/display/dc/bios/Makefile | 24 +
- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 4220 ++++++++++++++++++++
- drivers/gpu/drm/amd/display/dc/bios/bios_parser.h | 33 +
- .../drm/amd/display/dc/bios/bios_parser_helper.c | 82 +
- .../drm/amd/display/dc/bios/bios_parser_helper.h | 40 +
- .../amd/display/dc/bios/bios_parser_interface.c | 50 +
- .../display/dc/bios/bios_parser_types_internal.h | 72 +
- .../gpu/drm/amd/display/dc/bios/command_table.c | 2609 ++++++++++++
- .../gpu/drm/amd/display/dc/bios/command_table.h | 112 +
- .../drm/amd/display/dc/bios/command_table_helper.c | 288 ++
- .../drm/amd/display/dc/bios/command_table_helper.h | 90 +
- .../dc/bios/dce110/command_table_helper_dce110.c | 364 ++
- .../dc/bios/dce110/command_table_helper_dce110.h | 34 +
- .../dc/bios/dce112/command_table_helper_dce112.c | 418 ++
- .../dc/bios/dce112/command_table_helper_dce112.h | 34 +
- .../dc/bios/dce80/command_table_helper_dce80.c | 354 ++
- .../dc/bios/dce80/command_table_helper_dce80.h | 33 +
- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 10 +
- .../gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 3108 ++++++++++++++
- drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c | 299 ++
- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 1382 +++++++
- drivers/gpu/drm/amd/display/dc/core/dc.c | 1846 +++++++++
- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 270 ++
- .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 93 +
- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1899 +++++++++
- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 1098 +++++
- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2462 ++++++++++++
- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 222 +
- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1934 +++++++++
- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 113 +
- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 141 +
- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 214 +
- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 334 ++
- drivers/gpu/drm/amd/display/dc/dc.h | 780 ++++
- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 224 ++
- drivers/gpu/drm/amd/display/dc/dc_ddc_types.h | 115 +
- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 105 +
- drivers/gpu/drm/amd/display/dc/dc_helper.c | 144 +
- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 588 +++
- drivers/gpu/drm/amd/display/dc/dc_types.h | 493 +++
- drivers/gpu/drm/amd/display/dc/dce/Makefile | 14 +
- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 920 +++++
- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 145 +
- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1264 ++++++
- .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 109 +
- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 195 +
- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 250 ++
- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2176 ++++++++++
- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 363 ++
- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 384 ++
- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 217 +
- .../gpu/drm/amd/display/dc/dce/dce_scl_filters.c | 501 +++
- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 1302 ++++++
- .../drm/amd/display/dc/dce/dce_stream_encoder.h | 564 +++
- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 1002 +++++
- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 313 ++
- drivers/gpu/drm/amd/display/dc/dce100/Makefile | 23 +
- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 140 +
- .../amd/display/dc/dce100/dce100_hw_sequencer.h | 36 +
- .../drm/amd/display/dc/dce100/dce100_resource.c | 1085 +++++
- .../drm/amd/display/dc/dce100/dce100_resource.h | 19 +
- drivers/gpu/drm/amd/display/dc/dce110/Makefile | 15 +
- .../drm/amd/display/dc/dce110/dce110_compressor.c | 859 ++++
- .../drm/amd/display/dc/dce110/dce110_compressor.h | 78 +
- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1978 +++++++++
- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 62 +
- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c | 62 +
- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 76 +
- .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 253 ++
- .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 303 ++
- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 535 +++
- .../drm/amd/display/dc/dce110/dce110_mem_input.h | 131 +
- .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 1081 +++++
- .../drm/amd/display/dc/dce110/dce110_mem_input_v.h | 94 +
- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c | 77 +
- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h | 149 +
- .../gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c | 363 ++
- .../drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 738 ++++
- .../amd/display/dc/dce110/dce110_opp_formatter.c | 627 +++
- .../drm/amd/display/dc/dce110/dce110_opp_regamma.c | 537 +++
- .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 551 +++
- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 63 +
- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 56 +
- .../drm/amd/display/dc/dce110/dce110_resource.c | 1413 +++++++
- .../drm/amd/display/dc/dce110/dce110_resource.h | 56 +
- .../display/dc/dce110/dce110_timing_generator.c | 1953 +++++++++
- .../display/dc/dce110/dce110_timing_generator.h | 273 ++
- .../display/dc/dce110/dce110_timing_generator_v.c | 743 ++++
- .../display/dc/dce110/dce110_timing_generator_v.h | 33 +
- .../drm/amd/display/dc/dce110/dce110_transform_v.c | 704 ++++
- .../drm/amd/display/dc/dce110/dce110_transform_v.h | 37 +
- .../gpu/drm/amd/display/dc/dce110/dce110_types.h | 30 +
- drivers/gpu/drm/amd/display/dc/dce112/Makefile | 11 +
- .../drm/amd/display/dc/dce112/dce112_compressor.c | 859 ++++
- .../drm/amd/display/dc/dce112/dce112_compressor.h | 78 +
- .../amd/display/dc/dce112/dce112_hw_sequencer.c | 166 +
- .../amd/display/dc/dce112/dce112_hw_sequencer.h | 36 +
- .../drm/amd/display/dc/dce112/dce112_mem_input.c | 54 +
- .../drm/amd/display/dc/dce112/dce112_mem_input.h | 38 +
- drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c | 72 +
- drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h | 48 +
- .../amd/display/dc/dce112/dce112_opp_formatter.c | 215 +
- .../drm/amd/display/dc/dce112/dce112_resource.c | 1418 +++++++
- .../drm/amd/display/dc/dce112/dce112_resource.h | 55 +
- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 16 +
- .../drm/amd/display/dc/dce80/dce80_compressor.c | 839 ++++
- .../drm/amd/display/dc/dce80/dce80_compressor.h | 78 +
- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 141 +
- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.h | 36 +
- drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 64 +
- drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 47 +
- .../gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c | 76 +
- .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 83 +
- .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.h | 36 +
- drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c | 136 +
- drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h | 130 +
- .../gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c | 363 ++
- .../drm/amd/display/dc/dce80/dce80_opp_formatter.c | 577 +++
- .../drm/amd/display/dc/dce80/dce80_opp_regamma.c | 543 +++
- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1063 +++++
- .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 39 +
- .../amd/display/dc/dce80/dce80_timing_generator.c | 241 ++
- .../amd/display/dc/dce80/dce80_timing_generator.h | 45 +
- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 101 +
- drivers/gpu/drm/amd/display/dc/dm_services.h | 424 ++
- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 242 ++
- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 38 +
- .../amd/display/dc/gpio/dce110/hw_factory_dce110.c | 178 +
- .../amd/display/dc/gpio/dce110/hw_factory_dce110.h | 32 +
- .../display/dc/gpio/dce110/hw_translate_dce110.c | 387 ++
- .../display/dc/gpio/dce110/hw_translate_dce110.h | 34 +
- .../amd/display/dc/gpio/dce80/hw_factory_dce80.c | 173 +
- .../amd/display/dc/gpio/dce80/hw_factory_dce80.h | 32 +
- .../amd/display/dc/gpio/dce80/hw_translate_dce80.c | 411 ++
- .../amd/display/dc/gpio/dce80/hw_translate_dce80.h | 32 +
- drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h | 150 +
- .../display/dc/gpio/diagnostics/hw_factory_diag.c | 63 +
- .../display/dc/gpio/diagnostics/hw_factory_diag.h | 32 +
- .../dc/gpio/diagnostics/hw_translate_diag.c | 40 +
- .../dc/gpio/diagnostics/hw_translate_diag.h | 34 +
- drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c | 272 ++
- drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h | 45 +
- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 592 +++
- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h | 56 +
- drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h | 79 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 243 ++
- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h | 46 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 93 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h | 74 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 205 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h | 144 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 175 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h | 46 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 75 +
- drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h | 50 +
- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 36 +
- .../display/dc/gpu/dce110/display_clock_dce110.c | 1035 +++++
- .../display/dc/gpu/dce110/display_clock_dce110.h | 53 +
- .../display/dc/gpu/dce112/display_clock_dce112.c | 964 +++++
- .../display/dc/gpu/dce112/display_clock_dce112.h | 114 +
- .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 934 +++++
- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 57 +
- drivers/gpu/drm/amd/display/dc/gpu/display_clock.c | 217 +
- drivers/gpu/drm/amd/display/dc/gpu/display_clock.h | 89 +
- drivers/gpu/drm/amd/display/dc/gpu/divider_range.c | 127 +
- drivers/gpu/drm/amd/display/dc/gpu/divider_range.h | 62 +
- drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 58 +
- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c | 567 +++
- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 117 +
- .../amd/display/dc/i2caux/dce100/i2caux_dce100.c | 112 +
- .../amd/display/dc/i2caux/dce100/i2caux_dce100.h | 32 +
- .../display/dc/i2caux/dce110/aux_engine_dce110.c | 456 +++
- .../display/dc/i2caux/dce110/aux_engine_dce110.h | 78 +
- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 577 +++
- .../dc/i2caux/dce110/i2c_hw_engine_dce110.h | 214 +
- .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 171 +
- .../dc/i2caux/dce110/i2c_sw_engine_dce110.h | 43 +
- .../amd/display/dc/i2caux/dce110/i2caux_dce110.c | 323 ++
- .../amd/display/dc/i2caux/dce110/i2caux_dce110.h | 53 +
- .../amd/display/dc/i2caux/dce112/i2caux_dce112.c | 140 +
- .../amd/display/dc/i2caux/dce112/i2caux_dce112.h | 32 +
- .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.c | 885 ++++
- .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.h | 54 +
- .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.c | 184 +
- .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.h | 43 +
- .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c | 295 ++
- .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h | 38 +
- .../display/dc/i2caux/diagnostics/i2caux_diag.c | 108 +
- .../display/dc/i2caux/diagnostics/i2caux_diag.h | 32 +
- drivers/gpu/drm/amd/display/dc/i2caux/engine.h | 120 +
- .../gpu/drm/amd/display/dc/i2caux/engine_base.c | 53 +
- drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c | 121 +
- drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h | 113 +
- .../amd/display/dc/i2caux/i2c_generic_hw_engine.c | 286 ++
- .../amd/display/dc/i2caux/i2c_generic_hw_engine.h | 77 +
- .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c | 246 ++
- .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h | 80 +
- .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c | 610 +++
- .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h | 81 +
- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 459 +++
- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h | 122 +
- .../gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 503 +++
- drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 63 +
- drivers/gpu/drm/amd/display/dc/inc/clock_source.h | 178 +
- drivers/gpu/drm/amd/display/dc/inc/compressor.h | 93 +
- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 50 +
- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 47 +
- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 319 ++
- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 145 +
- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 60 +
- drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h | 19 +
- drivers/gpu/drm/amd/display/dc/inc/gamma_types.h | 38 +
- drivers/gpu/drm/amd/display/dc/inc/hw/audio.h | 62 +
- drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h | 86 +
- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 74 +
- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 121 +
- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 263 ++
- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 106 +
- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 322 ++
- .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 121 +
- .../drm/amd/display/dc/inc/hw/timing_generator.h | 162 +
- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 179 +
- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 156 +
- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 73 +
- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 290 ++
- drivers/gpu/drm/amd/display/dc/inc/resource.h | 164 +
- drivers/gpu/drm/amd/display/dc/irq/Makefile | 28 +
- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 367 ++
- .../amd/display/dc/irq/dce110/irq_service_dce110.h | 48 +
- .../amd/display/dc/irq/dce80/irq_service_dce80.c | 283 ++
- .../amd/display/dc/irq/dce80/irq_service_dce80.h | 35 +
- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 163 +
- drivers/gpu/drm/amd/display/dc/irq/irq_service.h | 85 +
- drivers/gpu/drm/amd/display/dc/irq_types.h | 185 +
- drivers/gpu/drm/amd/display/dc/os_types.h | 61 +
- drivers/gpu/drm/amd/display/dc/virtual/Makefile | 9 +
- .../amd/display/dc/virtual/virtual_link_encoder.c | 150 +
- .../amd/display/dc/virtual/virtual_link_encoder.h | 34 +
- .../display/dc/virtual/virtual_stream_encoder.c | 132 +
- .../display/dc/virtual/virtual_stream_encoder.h | 39 +
- .../display/include/asic_capability_interface.h | 55 +
- .../amd/display/include/asic_capability_types.h | 116 +
- drivers/gpu/drm/amd/display/include/audio_types.h | 106 +
- .../amd/display/include/bios_parser_interface.h | 44 +
- .../drm/amd/display/include/bios_parser_types.h | 338 ++
- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 125 +
- .../drm/amd/display/include/dal_register_logger.h | 42 +
- drivers/gpu/drm/amd/display/include/dal_types.h | 44 +
- .../drm/amd/display/include/ddc_service_types.h | 189 +
- .../amd/display/include/display_clock_interface.h | 175 +
- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 742 ++++
- drivers/gpu/drm/amd/display/include/fixed31_32.h | 390 ++
- drivers/gpu/drm/amd/display/include/fixed32_32.h | 83 +
- .../gpu/drm/amd/display/include/gpio_interface.h | 92 +
- .../amd/display/include/gpio_service_interface.h | 105 +
- drivers/gpu/drm/amd/display/include/gpio_types.h | 332 ++
- .../amd/display/include/grph_object_ctrl_defs.h | 407 ++
- .../gpu/drm/amd/display/include/grph_object_defs.h | 140 +
- .../gpu/drm/amd/display/include/grph_object_id.h | 256 ++
- .../drm/amd/display/include/hw_sequencer_types.h | 105 +
- .../gpu/drm/amd/display/include/i2caux_interface.h | 89 +
- .../gpu/drm/amd/display/include/irq_interface.h | 31 +
- .../amd/display/include/irq_service_interface.h | 51 +
- .../drm/amd/display/include/link_service_types.h | 232 ++
- .../gpu/drm/amd/display/include/logger_interface.h | 140 +
- drivers/gpu/drm/amd/display/include/logger_types.h | 95 +
- .../gpu/drm/amd/display/include/set_mode_types.h | 127 +
- drivers/gpu/drm/amd/display/include/signal_types.h | 59 +
- drivers/gpu/drm/amd/display/include/vector.h | 150 +
- drivers/gpu/drm/amd/display/modules/color/color.c | 2094 ++++++++++
- .../gpu/drm/amd/display/modules/freesync/Makefile | 10 +
- .../drm/amd/display/modules/freesync/freesync.c | 1158 ++++++
- .../gpu/drm/amd/display/modules/inc/mod_color.h | 179 +
- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 149 +
- .../gpu/drm/amd/display/modules/inc/mod_power.h | 112 +
- drivers/gpu/drm/amd/display/modules/power/power.c | 784 ++++
- drivers/gpu/drm/drm_atomic.c | 35 +-
- drivers/gpu/drm/drm_atomic_helper.c | 189 +
- drivers/gpu/drm/drm_modeset_lock.c | 21 +
- include/drm/drm_atomic.h | 5 +
- include/drm/drm_atomic_helper.h | 8 +
- include/drm/drm_crtc.h | 13 +
- include/drm/drm_modeset_lock.h | 2 +
- include/uapi/drm/amdgpu_drm.h | 19 +
- 324 files changed, 99996 insertions(+), 38 deletions(-)
- create mode 100644 drivers/gpu/drm/amd/display/Kconfig
- create mode 100644 drivers/gpu/drm/amd/display/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
- create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/log_helpers.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/register_logger.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/signal_types.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/basics/vector.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_debug.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_resource.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_sink.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_stream.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_surface.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_target.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_bios_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_ddc_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dp_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_helper.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_hw_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dc_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dm_helpers.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/clock_source.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/compressor.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_dc.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_status.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/audio.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/inc/resource.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/irq_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/os_types.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c
- create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h
- create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/audio_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/dal_asic_id.h
- create mode 100644 drivers/gpu/drm/amd/display/include/dal_register_logger.h
- create mode 100644 drivers/gpu/drm/amd/display/include/dal_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/ddc_service_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/display_clock_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/dpcd_defs.h
- create mode 100644 drivers/gpu/drm/amd/display/include/fixed31_32.h
- create mode 100644 drivers/gpu/drm/amd/display/include/fixed32_32.h
- create mode 100644 drivers/gpu/drm/amd/display/include/gpio_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/gpio_service_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/gpio_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h
- create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_defs.h
- create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_id.h
- create mode 100644 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/i2caux_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/irq_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/irq_service_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/link_service_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/logger_interface.h
- create mode 100644 drivers/gpu/drm/amd/display/include/logger_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/set_mode_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/signal_types.h
- create mode 100644 drivers/gpu/drm/amd/display/include/vector.h
- create mode 100644 drivers/gpu/drm/amd/display/modules/color/color.c
- create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/Makefile
- create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/freesync.c
- create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_color.h
- create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
- create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_power.h
- create mode 100644 drivers/gpu/drm/amd/display/modules/power/power.c
-
-diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
-index 2668245..e8af1f5 100644
---- a/drivers/gpu/drm/amd/amdgpu/Kconfig
-+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
-@@ -41,3 +41,4 @@ config DRM_AMDGPU_GART_DEBUGFS
- pages. Uses more memory for housekeeping, enable only for debugging.
-
- source "drivers/gpu/drm/amd/acp/Kconfig"
-+source "drivers/gpu/drm/amd/display/Kconfig"
-diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
-index 567b037..93fc29d 100644
---- a/drivers/gpu/drm/amd/amdgpu/Makefile
-+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
-@@ -4,13 +4,19 @@
- # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-
- FULL_AMD_PATH=$(src)/..
-+DISPLAY_FOLDER_NAME=display
-+FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME)
-
- ccflags-y := -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_DISPLAY_PATH) \
-+ -I$(FULL_AMD_DISPLAY_PATH)/include \
-+ -I$(FULL_AMD_DISPLAY_PATH)/dc \
-+ -I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm
-
- amdgpu-y := amdgpu_drv.o
-
-@@ -133,6 +139,15 @@ include $(FULL_AMD_PATH)/powerplay/Makefile
-
- amdgpu-y += $(AMD_POWERPLAY_FILES)
-
-+ifneq ($(CONFIG_DRM_AMD_DC),)
-+
-+RELATIVE_AMD_DISPLAY_PATH = ../$(DISPLAY_FOLDER_NAME)
-+include $(FULL_AMD_DISPLAY_PATH)/Makefile
-+
-+amdgpu-y += $(AMD_DISPLAY_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 712ad8c..a8a27ac 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
-@@ -65,6 +65,7 @@
- #include "amdgpu_uvd.h"
- #include "amdgpu_vce.h"
- #include "amdgpu_vcn.h"
-+#include "amdgpu_dm.h"
-
- #include "gpu_scheduler.h"
- #include "amdgpu_virt.h"
-@@ -100,6 +101,7 @@ extern int amdgpu_vm_fragment_size;
- extern int amdgpu_vm_fault_stop;
- extern int amdgpu_vm_debug;
- extern int amdgpu_vm_update_mode;
-+extern int amdgpu_dc;
- extern int amdgpu_sched_jobs;
- extern int amdgpu_sched_hw_submission;
- extern int amdgpu_no_evict;
-@@ -1312,6 +1314,9 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
- int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
- struct drm_file *filp);
-
-+int amdgpu_freesync_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *filp);
-+
- /* VRAM scratch page for HDP bug, default vram page */
- struct amdgpu_vram_scratch {
- struct amdgpu_bo *robj;
-@@ -1502,6 +1507,7 @@ struct amdgpu_device {
- /* display */
- bool enable_virtual_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;
-@@ -1554,6 +1560,9 @@ struct amdgpu_device {
- /* GDS */
- struct amdgpu_gds gds;
-
-+ /* display related functionality */
-+ struct amdgpu_display_manager dm;
-+
- struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
- int num_ip_blocks;
- struct mutex mn_lock;
-@@ -1614,6 +1623,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
- u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index);
- void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v);
-
-+bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
-+bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
-+
- /*
- * Registers read & write functions.
- */
-@@ -1886,5 +1898,11 @@ amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
- uint64_t addr, struct amdgpu_bo **bo);
- int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser);
-
-+#if defined(CONFIG_DRM_AMD_DC)
-+int amdgpu_dm_display_resume(struct amdgpu_device *adev );
-+#else
-+static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; }
-+#endif
-+
- #include "amdgpu_object.h"
- #endif
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
-index 5c4d66f..12de22a 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
-@@ -31,6 +31,7 @@
- #include <linux/debugfs.h>
- #include <drm/drmP.h>
- #include <drm/drm_crtc_helper.h>
-+#include <drm/drm_atomic_helper.h>
- #include <drm/amdgpu_drm.h>
- #include <linux/vgaarb.h>
- #include <linux/vga_switcheroo.h>
-@@ -1966,6 +1967,43 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
- }
- }
-
-+bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
-+{
-+ switch (asic_type) {
-+#if defined(CONFIG_DRM_AMD_DC)
-+ case CHIP_BONAIRE:
-+ case CHIP_HAWAII:
-+ return amdgpu_dc != 0;
-+#endif
-+#if defined(CONFIG_DRM_AMD_DC)
-+ case CHIP_CARRIZO:
-+ case CHIP_STONEY:
-+ case CHIP_POLARIS11:
-+ case CHIP_POLARIS10:
-+ return amdgpu_dc != 0;
-+#endif
-+#if defined(CONFIG_DRM_AMD_DC)
-+ case CHIP_TONGA:
-+ case CHIP_FIJI:
-+ return amdgpu_dc != 0;
-+#endif
-+ default:
-+ return false;
-+ }
-+}
-+
-+/**
-+ * amdgpu_device_has_dc_support - check if dc is supported
-+ *
-+ * @adev: amdgpu_device_pointer
-+ *
-+ * Returns true for supported, false for not supported
-+ */
-+bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
-+{
-+ return amdgpu_device_asic_has_dc_support(adev->asic_type);
-+}
-+
- /**
- * amdgpu_device_init - initialize the driver
- *
-@@ -2160,7 +2198,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
- goto failed;
- }
- /* init i2c buses */
-- amdgpu_atombios_i2c_init(adev);
-+ if (!amdgpu_device_has_dc_support(adev))
-+ amdgpu_atombios_i2c_init(adev);
- }
-
- /* Fence driver */
-@@ -2288,7 +2327,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
- adev->accel_working = false;
- cancel_delayed_work_sync(&adev->late_init_work);
- /* free i2c buses */
-- amdgpu_i2c_fini(adev);
-+ if (!amdgpu_device_has_dc_support(adev))
-+ amdgpu_i2c_fini(adev);
- amdgpu_atombios_fini(adev);
- kfree(adev->bios);
- adev->bios = NULL;
-@@ -2339,12 +2379,14 @@ int amdgpu_device_suspend(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_dc_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);
-
- amdgpu_amdkfd_suspend(adev);
-
-@@ -2452,6 +2494,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
- DRM_ERROR("amdgpu_resume failed (%d).\n", r);
- goto unlock;
- }
-+
- amdgpu_fence_driver_resume(adev);
-
- if (resume) {
-@@ -2487,13 +2530,25 @@ int amdgpu_device_resume(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_dc_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);
-+ } else {
-+ /*
-+ * There is no equivalent atomic helper to turn on
-+ * display, so we defined our own function for this,
-+ * once suspend resume is supported by the atomic
-+ * framework this will be reworked
-+ */
-+ amdgpu_dm_display_resume(adev);
- }
-- drm_modeset_unlock_all(dev);
- }
-
- drm_kms_helper_poll_enable(dev);
-@@ -2510,7 +2565,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
- #ifdef CONFIG_PM
- dev->dev->power.disable_depth++;
- #endif
-- drm_helper_hpd_irq_event(dev);
-+ if (!amdgpu_device_has_dc_support(adev))
-+ drm_helper_hpd_irq_event(dev);
-+ else
-+ drm_kms_helper_hotplug_event(dev);
- #ifdef CONFIG_PM
- dev->dev->power.disable_depth--;
- #endif
-@@ -2806,6 +2864,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job)
- */
- int amdgpu_gpu_reset(struct amdgpu_device *adev)
- {
-+ struct drm_atomic_state *state = NULL;
- int i, r;
- int resched;
- bool need_full_reset, vram_lost = false;
-@@ -2819,6 +2878,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
-
- /* block TTM */
- resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
-+ /* store modesetting */
-+ if (amdgpu_device_has_dc_support(adev))
-+ state = drm_atomic_helper_suspend(adev->ddev);
-
- /* block scheduler */
- for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-@@ -2936,7 +2998,11 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
- }
- }
-
-- drm_helper_resume_force_mode(adev->ddev);
-+ if (amdgpu_device_has_dc_support(adev)) {
-+ r = drm_atomic_helper_resume(adev->ddev, state);
-+ amdgpu_dm_display_resume(adev);
-+ } else
-+ drm_helper_resume_force_mode(adev->ddev);
-
- ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
- if (r) {
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
-index 6ad2432..3cd8ab1 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
-@@ -631,6 +631,19 @@ int amdgpu_modeset_create_props(struct amdgpu_device *adev)
- "dither",
- amdgpu_dither_enum_list, sz);
-
-+ if (amdgpu_device_has_dc_support(adev)) {
-+ adev->mode_info.freesync_property =
-+ drm_property_create_bool(adev->ddev, 0, "freesync");
-+ if (!adev->mode_info.freesync_property)
-+ return -ENOMEM;
-+ adev->mode_info.freesync_capable_property =
-+ drm_property_create_bool(adev->ddev,
-+ DRM_MODE_PROP_IMMUTABLE,
-+ "freesync_capable");
-+ if (!adev->mode_info.freesync_capable_property)
-+ return -ENOMEM;
-+ }
-+
- return 0;
- }
-
-@@ -886,3 +899,18 @@ int amdgpu_crtc_idx_to_irq_type(struct amdgpu_device *adev, int crtc)
- return AMDGPU_CRTC_IRQ_NONE;
- }
- }
-+
-+int amdgpu_freesync_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *filp)
-+{
-+ int ret = -EPERM;
-+ struct amdgpu_device *adev = dev->dev_private;
-+
-+ if (adev->mode_info.funcs->notify_freesync)
-+ ret = adev->mode_info.funcs->notify_freesync(dev,data,filp);
-+ else
-+ DRM_DEBUG("amdgpu no notify_freesync ioctl\n");
-+
-+ return ret;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
-index 8c96a4c..f187680 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
-@@ -488,7 +488,7 @@ struct amdgpu_pm {
- const struct amdgpu_dpm_funcs *funcs;
- uint32_t pcie_gen_mask;
- uint32_t pcie_mlw_mask;
-- struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
-+ struct amd_pp_display_configuration pm_display_cfg;/* set by dc */
- };
-
- #define R600_SSTU_DFLT 0
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
-index 0f16986..b96fa64 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
-@@ -102,6 +102,7 @@ int amdgpu_vm_debug = 0;
- int amdgpu_vram_page_split = 512;
- int amdgpu_vm_update_mode = -1;
- int amdgpu_exp_hw_support = 0;
-+int amdgpu_dc = -1;
- int amdgpu_sched_jobs = 32;
- int amdgpu_sched_hw_submission = 2;
- int amdgpu_no_evict = 0;
-@@ -206,6 +207,9 @@ module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444);
- MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))");
- module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444);
-
-+MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))");
-+module_param_named(dc, amdgpu_dc, int, 0444);
-+
- MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)");
- module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444);
-
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
-index 9afa9c0..84d227b 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 int
- amdgpufb_open(struct fb_info *info, int user)
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
-index 538e5f2..47c5ce9 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
-@@ -37,6 +37,10 @@
-
- #include <linux/pm_runtime.h>
-
-+#ifdef CONFIG_DRM_AMD_DC
-+#include "amdgpu_dm_irq.h"
-+#endif
-+
- #define AMDGPU_WAIT_IDLE_TIMEOUT 200
-
- /*
-@@ -221,15 +225,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
-
- spin_lock_init(&adev->irq.lock);
-
-- if (!adev->enable_virtual_display)
-- /* Disable vblank irqs aggressively for power-saving */
-- adev->ddev->vblank_disable_immediate = true;
--
-- r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
-- if (r) {
-- return r;
-- }
--
- /* enable msi */
- adev->irq.msi_enabled = false;
-
-@@ -241,7 +236,21 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
- }
- }
-
-- INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
-+ if (!amdgpu_device_has_dc_support(adev)) {
-+ if (!adev->enable_virtual_display)
-+ /* Disable vblank irqs aggressively for power-saving */
-+ /* XXX: can this be enabled for DC? */
-+ adev->ddev->vblank_disable_immediate = true;
-+
-+ 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_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
-index e162290..d31777b 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
-@@ -1032,6 +1032,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
-+ DRM_IOCTL_DEF_DRV(AMDGPU_FREESYNC, amdgpu_freesync_ioctl, DRM_MASTER)
- };
- const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
-
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
-index 2af2678..3339ecf 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
-@@ -38,11 +38,15 @@
- #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 <linux/hrtimer.h>
- #include "amdgpu_irq.h"
-
-+#include <drm/drm_dp_mst_helper.h>
-+#include "modules/inc/mod_freesync.h"
-+
- struct amdgpu_bo;
- struct amdgpu_device;
- struct amdgpu_encoder;
-@@ -292,6 +296,27 @@ struct amdgpu_display_funcs {
- uint16_t connector_object_id,
- struct amdgpu_hpd *hpd,
- struct amdgpu_router *router);
-+ /* it is used to enter or exit into free sync mode */
-+ int (*notify_freesync)(struct drm_device *dev, void *data,
-+ struct drm_file *filp);
-+ /* it is used to allow enablement of freesync mode */
-+ int (*set_freesync_property)(struct drm_connector *connector,
-+ struct drm_property *property,
-+ uint64_t val);
-+
-+
-+};
-+
-+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 {
-@@ -312,6 +337,10 @@ struct amdgpu_mode_info {
- struct drm_property *audio_property;
- /* FMT dithering */
- struct drm_property *dither_property;
-+ /* it is used to allow enablement of freesync mode */
-+ struct drm_property *freesync_property;
-+ /* it is used to know about display capability of freesync mode */
-+ struct drm_property *freesync_capable_property;
- /* hardcoded DFP edid from BIOS */
- struct edid *bios_hardcoded_edid;
- int bios_hardcoded_edid_size;
-@@ -400,6 +429,11 @@ struct amdgpu_crtc {
- /* for virtual dce */
- struct hrtimer vblank_timer;
- enum amdgpu_interrupt_state vsync_timer_enabled;
-+
-+ int otg_inst;
-+ uint32_t flip_flags;
-+ /* After Set Mode target will be non-NULL */
-+ struct dc_target *target;
- };
-
- struct amdgpu_encoder_atom_dig {
-@@ -489,6 +523,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;
-@@ -500,6 +547,14 @@ 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_sink *dc_em_sink;
-+ const struct dc_target *target;
- void *con_priv;
- bool dac_load_detect;
- bool detected_by_load; /* if the connection status was determined by load */
-@@ -510,11 +565,39 @@ 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;
-+ 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;
-+
-+ /* Monitor range limits */
-+ int min_vfreq ;
-+ int max_vfreq ;
-+ int pixel_clock_mhz;
-+
-+ /*freesync caps*/
-+ struct mod_freesync_caps caps;
-+
-+ struct mutex hpd_lock;
-+
- };
-
--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/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-index 7df503a..f435275 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-@@ -1242,7 +1242,6 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
- printk("switching to power state:\n");
- amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps);
- }
--
- /* update whether vce is active */
- ps->vce_active = adev->pm.dpm.vce_active;
-
-@@ -1505,7 +1504,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
- list_for_each_entry(crtc,
- &ddev->mode_config.crtc_list, head) {
- amdgpu_crtc = to_amdgpu_crtc(crtc);
-- if (crtc->enabled) {
-+ if (amdgpu_crtc->enabled) {
- adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
- adev->pm.dpm.new_active_crtc_count++;
- }
-diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
-index 567c4a5..af3b66f 100644
---- a/drivers/gpu/drm/amd/amdgpu/cik.c
-+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
-@@ -65,6 +65,7 @@
- #include "oss/oss_2_0_d.h"
- #include "oss/oss_2_0_sh_mask.h"
-
-+#include "amdgpu_dm.h"
- #include "amdgpu_amdkfd.h"
- #include "amdgpu_powerplay.h"
- #include "dce_virtual.h"
-@@ -1900,6 +1901,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display)
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v8_2_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
-@@ -1914,6 +1919,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display)
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v8_5_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block);
-diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
-index 0327e0a..e131eb3 100644
---- a/drivers/gpu/drm/amd/amdgpu/vi.c
-+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
-@@ -77,6 +77,7 @@
- #endif
- #include "dce_virtual.h"
- #include "mxgpu_vi.h"
-+#include "amdgpu_dm.h"
-
- /*
- * Indirect registers accessor
-@@ -1544,6 +1545,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v10_1_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
-@@ -1560,6 +1565,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v10_0_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
-@@ -1578,6 +1587,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display)
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v11_2_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
-@@ -1592,6 +1605,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display)
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
-@@ -1609,6 +1626,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
- amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
- if (adev->enable_virtual_display)
- amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
-+#if defined(CONFIG_DRM_AMD_DC)
-+ else if (amdgpu_device_has_dc_support(adev))
-+ amdgpu_ip_block_add(adev, &dm_ip_block);
-+#endif
- else
- amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
- amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block);
-diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
-new file mode 100644
-index 0000000..f652cc3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/Kconfig
-@@ -0,0 +1,20 @@
-+menu "Display Engine Configuration"
-+ depends on DRM && DRM_AMDGPU
-+
-+config DRM_AMD_DC
-+ bool "AMD DC - Enable new display engine (will be deprecated when the development is done)"
-+ help
-+ Choose this option if you want to use the new display engine
-+ support for AMDGPU.
-+
-+ Will be deprecated when the DC component is upstream.
-+
-+config DEBUG_KERNEL_DC
-+ bool "Enable kgdb break in DC"
-+ depends on DRM_AMD_DC
-+ help
-+ Choose this option
-+ if you want to hit
-+ kdgb_break in assert.
-+
-+endmenu
-diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile
-new file mode 100644
-index 0000000..8ba37dd
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/Makefile
-@@ -0,0 +1,22 @@
-+#
-+# 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_DISPLAY_PATH)
-+
-+subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
-+
-+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/
-+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw
-+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
-+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
-+
-+#TODO: remove when Timing Sync feature is complete
-+subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
-+
-+DAL_LIBS = amdgpu_dm dc modules/freesync
-+
-+AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
-+
-+include $(AMD_DAL)
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
-new file mode 100644
-index 0000000..698b1d4
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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_DC),)
-+AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o
-+endif
-+
-+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc
-+
-+AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
-+
-+AMD_DISPLAY_FILES += $(AMDGPU_DM)
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-new file mode 100644
-index 0000000..333c835
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-@@ -0,0 +1,1584 @@
-+/*
-+ * 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"
-+
-+#ifdef CONFIG_DRM_AMDGPU_CIK
-+#include "dce_v8_0.h"
-+#endif
-+#include "dce_v10_0.h"
-+#include "dce_v11_0.h"
-+
-+#include "ivsrcid/ivsrcid_vislands30.h"
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/version.h>
-+
-+#include <drm/drm_atomic.h>
-+#include <drm/drm_atomic_helper.h>
-+#include <drm/drm_dp_mst_helper.h>
-+
-+#include "modules/inc/mod_freesync.h"
-+
-+/* 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;
-+ 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_scanoutpos(acrtc->target, 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 bool dm_check_soft_reset(void *handle)
-+{
-+ return false;
-+}
-+
-+static int dm_soft_reset(void *handle)
-+{
-+ /* XXX todo */
-+ return 0;
-+}
-+
-+static struct amdgpu_crtc *get_crtc_by_otg_inst(
-+ struct amdgpu_device *adev,
-+ int otg_inst)
-+{
-+ 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 (otg_inst == -1) {
-+ WARN_ON(1);
-+ 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->otg_inst == otg_inst)
-+ 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;
-+
-+ amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
-+
-+ /* IRQ could occur when in initial stage */
-+ /*TODO work and BO cleanup */
-+ if (amdgpu_crtc == NULL) {
-+ DRM_DEBUG_DRIVER("CRTC is null, returning.\n");
-+ 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) on crtc:%d[%p] \n",
-+ amdgpu_crtc->pflip_status,
-+ AMDGPU_FLIP_SUBMITTED,
-+ amdgpu_crtc->crtc_id,
-+ amdgpu_crtc);
-+ 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_crtc_send_vblank_event(&amdgpu_crtc->base,
-+ works->event);
-+
-+ spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
-+
-+ DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n",
-+ __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works);
-+
-+ 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;
-+ uint8_t crtc_index = 0;
-+ struct amdgpu_crtc *acrtc;
-+
-+ acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
-+
-+ 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 dc_init_data init_data;
-+ adev->dm.ddev = adev->ddev;
-+ adev->dm.adev = adev;
-+
-+ DRM_INFO("DAL is enabled\n");
-+ /* 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;
-+ }
-+
-+ 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.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;
-+
-+ init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
-+
-+ /* Display Core create. */
-+ adev->dm.dc = dc_create(&init_data);
-+
-+ if (!adev->dm.dc)
-+ DRM_INFO("Display Core failed to initialize!\n");
-+
-+ INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func);
-+
-+ adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);
-+ if (!adev->dm.freesync_module) {
-+ DRM_ERROR(
-+ "amdgpu: failed to initialize freesync_module.\n");
-+ } else
-+ DRM_INFO("amdgpu: freesync_module init done %p.\n",
-+ adev->dm.freesync_module);
-+
-+ 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;
-+ }
-+ if (adev->dm.freesync_module) {
-+ mod_freesync_destroy(adev->dm.freesync_module);
-+ adev->dm.freesync_module = 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 void s3_handle_mst(struct drm_device *dev, bool suspend)
-+{
-+ 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 &&
-+ !aconnector->mst_port) {
-+
-+ if (suspend)
-+ drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
-+ else
-+ drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr);
-+ }
-+ }
-+
-+ 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_suspend(void *handle)
-+{
-+ struct amdgpu_device *adev = handle;
-+ struct amdgpu_display_manager *dm = &adev->dm;
-+ int ret = 0;
-+ struct drm_crtc *crtc;
-+
-+ s3_handle_mst(adev->ddev, true);
-+
-+ /* flash all pending vblank events and turn interrupt off
-+ * before disabling CRTCs. They will be enabled back in
-+ * dm_display_resume
-+ */
-+ drm_modeset_lock_all(adev->ddev);
-+ list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) {
-+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-+ if (acrtc->target)
-+ drm_crtc_vblank_off(crtc);
-+ }
-+ drm_modeset_unlock_all(adev->ddev);
-+
-+ amdgpu_dm_irq_suspend(adev);
-+
-+ dc_set_power_state(
-+ dm->dc,
-+ DC_ACPI_CM_POWER_STATE_D3,
-+ DC_VIDEO_POWER_SUSPEND);
-+
-+ return ret;
-+}
-+
-+struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector(
-+ struct drm_atomic_state *state,
-+ struct drm_crtc *crtc,
-+ bool from_state_var)
-+{
-+ uint32_t i;
-+ struct drm_connector_state *conn_state;
-+ struct drm_connector *connector;
-+ struct drm_crtc *crtc_from_state;
-+
-+ for_each_connector_in_state(
-+ state,
-+ connector,
-+ conn_state,
-+ i) {
-+ crtc_from_state =
-+ from_state_var ?
-+ conn_state->crtc :
-+ connector->state->crtc;
-+
-+ if (crtc_from_state == crtc)
-+ return to_amdgpu_connector(connector);
-+ }
-+
-+ return NULL;
-+}
-+
-+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;
-+ struct amdgpu_connector *aconnector;
-+ struct drm_connector_state *conn_state;
-+
-+ if (!state)
-+ return ENOMEM;
-+
-+ state->acquire_ctx = ddev->mode_config.acquire_ctx;
-+
-+ /* Construct an atomic state to restore previous display setting */
-+
-+ /*
-+ * Attach connectors to drm_atomic_state
-+ * Should be done in the first place in order to make connectors
-+ * available in state during crtc state processing. It is used for
-+ * making decision if crtc should be disabled in case sink got
-+ * disconnected.
-+ *
-+ * Connectors state crtc with NULL dc_sink should be cleared, because it
-+ * will fail validation during commit
-+ */
-+ list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
-+ aconnector = to_amdgpu_connector(connector);
-+ conn_state = drm_atomic_get_connector_state(state, connector);
-+
-+ ret = PTR_ERR_OR_ZERO(conn_state);
-+ if (ret)
-+ goto err;
-+ }
-+
-+ /* 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) {
-+
-+ struct drm_crtc *crtc;
-+ struct drm_gem_object *obj;
-+ struct drm_framebuffer *fb;
-+ struct amdgpu_framebuffer *afb;
-+ struct amdgpu_bo *rbo;
-+ int r;
-+ struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane);
-+
-+ ret = PTR_ERR_OR_ZERO(plane_state);
-+ if (ret)
-+ goto err;
-+
-+ crtc = plane_state->crtc;
-+ fb = plane_state->fb;
-+
-+ if (!crtc || !crtc->state || !crtc->state->active)
-+ continue;
-+
-+ if (!fb) {
-+ DRM_DEBUG_KMS("No FB bound\n");
-+ return 0;
-+ }
-+
-+ /*
-+ * Pin back the front buffers, cursor buffer was already pinned
-+ * back in amdgpu_resume_kms
-+ */
-+
-+ 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;
-+ }
-+
-+ }
-+
-+
-+ /* 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_put(state);
-+
-+ return ret;
-+}
-+
-+static int dm_resume(void *handle)
-+{
-+ struct amdgpu_device *adev = handle;
-+ struct amdgpu_display_manager *dm = &adev->dm;
-+
-+ /* power on hardware */
-+ dc_set_power_state(
-+ dm->dc,
-+ DC_ACPI_CM_POWER_STATE_D0,
-+ DC_VIDEO_POWER_ON);
-+
-+ return 0;
-+}
-+
-+int amdgpu_dm_display_resume(struct amdgpu_device *adev )
-+{
-+ struct drm_device *ddev = adev->ddev;
-+ struct amdgpu_display_manager *dm = &adev->dm;
-+ struct amdgpu_connector *aconnector;
-+ struct drm_connector *connector;
-+ int ret = 0;
-+ struct drm_crtc *crtc;
-+
-+ /* program HPD filter */
-+ dc_resume(dm->dc);
-+
-+ /* On resume we need to rewrite the MSTM control bits to enamble MST*/
-+ s3_handle_mst(ddev, false);
-+
-+ /*
-+ * early enable HPD Rx IRQ, should be done before set mode as short
-+ * pulse interrupts are used for MST
-+ */
-+ amdgpu_dm_irq_resume_early(adev);
-+
-+ drm_modeset_lock_all(ddev);
-+ list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
-+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-+ if (acrtc->target)
-+ drm_crtc_vblank_on(crtc);
-+ }
-+ drm_modeset_unlock_all(ddev);
-+
-+ /* Do detection*/
-+ list_for_each_entry(connector,
-+ &ddev->mode_config.connector_list, head) {
-+ aconnector = to_amdgpu_connector(connector);
-+
-+ /*
-+ * this is the case when traversing through already created
-+ * MST connectors, should be skipped
-+ */
-+ if (aconnector->mst_port)
-+ continue;
-+
-+ 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);
-+
-+ amdgpu_dm_irq_resume(adev);
-+
-+ return ret;
-+}
-+
-+static const struct amd_ip_funcs amdgpu_dm_funcs = {
-+ .name = "dm",
-+ .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,
-+ .check_soft_reset = dm_check_soft_reset,
-+ .soft_reset = dm_soft_reset,
-+ .set_clockgating_state = dm_set_clockgating_state,
-+ .set_powergating_state = dm_set_powergating_state,
-+};
-+
-+const struct amdgpu_ip_block_version dm_ip_block =
-+{
-+ .type = AMD_IP_BLOCK_TYPE_DCE,
-+ .major = 1,
-+ .minor = 0,
-+ .rev = 0,
-+ .funcs = &amdgpu_dm_funcs,
-+};
-+
-+/* 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;
-+
-+ /* Edid mgmt connector gets first update only in mode_valid hook and then
-+ * the connector sink is set to either fake or physical sink depends on link status.
-+ * don't do it here if u are during boot
-+ */
-+ if (aconnector->base.force != DRM_FORCE_UNSPECIFIED
-+ && aconnector->dc_em_sink) {
-+
-+ /* For S3 resume with headless use eml_sink to fake target
-+ * because on resume connecotr->sink is set ti NULL
-+ */
-+ mutex_lock(&dev->mode_config.mutex);
-+
-+ if (sink) {
-+ if (aconnector->dc_sink)
-+ amdgpu_dm_remove_sink_from_freesync_module(
-+ connector);
-+ aconnector->dc_sink = sink;
-+ amdgpu_dm_add_sink_to_freesync_module(
-+ connector, aconnector->edid);
-+ } else {
-+ amdgpu_dm_remove_sink_from_freesync_module(connector);
-+ if (!aconnector->dc_sink)
-+ aconnector->dc_sink = aconnector->dc_em_sink;
-+ }
-+
-+ mutex_unlock(&dev->mode_config.mutex);
-+ return;
-+ }
-+
-+ /*
-+ * 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. */
-+ if (aconnector->dc_sink)
-+ amdgpu_dm_remove_sink_from_freesync_module(
-+ connector);
-+
-+ 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);
-+ }
-+ amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid);
-+
-+ } else {
-+ amdgpu_dm_remove_sink_from_freesync_module(connector);
-+ 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.
-+ */
-+ mutex_lock(&aconnector->hpd_lock);
-+ if (dc_link_detect(aconnector->dc_link, false)) {
-+ amdgpu_dm_update_connector_after_detect(aconnector);
-+
-+
-+ drm_modeset_lock_all(dev);
-+ dm_restore_drm_connector_state(dev, connector);
-+ drm_modeset_unlock_all(dev);
-+
-+ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
-+ drm_kms_helper_hotplug_event(dev);
-+ }
-+ mutex_unlock(&aconnector->hpd_lock);
-+
-+}
-+
-+static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector)
-+{
-+ uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
-+ uint8_t dret;
-+ bool new_irq_handled = false;
-+ int dpcd_addr;
-+ int dpcd_bytes_to_read;
-+
-+ const int max_process_count = 30;
-+ int process_count = 0;
-+
-+ const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
-+
-+ if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
-+ dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
-+ /* DPCD 0x200 - 0x201 for downstream IRQ */
-+ dpcd_addr = DP_SINK_COUNT;
-+ } else {
-+ dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
-+ /* DPCD 0x2002 - 0x2005 for downstream IRQ */
-+ dpcd_addr = DP_SINK_COUNT_ESI;
-+ }
-+
-+ dret = drm_dp_dpcd_read(
-+ &aconnector->dm_dp_aux.aux,
-+ dpcd_addr,
-+ esi,
-+ dpcd_bytes_to_read);
-+
-+ while (dret == dpcd_bytes_to_read &&
-+ process_count < max_process_count) {
-+ uint8_t retry;
-+ dret = 0;
-+
-+ process_count++;
-+
-+ DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
-+ /* handle HPD short pulse irq */
-+ if (aconnector->mst_mgr.mst_state)
-+ drm_dp_mst_hpd_irq(
-+ &aconnector->mst_mgr,
-+ esi,
-+ &new_irq_handled);
-+#endif
-+
-+ if (new_irq_handled) {
-+ /* ACK at DPCD to notify down stream */
-+ const int ack_dpcd_bytes_to_write =
-+ dpcd_bytes_to_read - 1;
-+
-+ for (retry = 0; retry < 3; retry++) {
-+ uint8_t wret;
-+
-+ wret = drm_dp_dpcd_write(
-+ &aconnector->dm_dp_aux.aux,
-+ dpcd_addr + 1,
-+ &esi[1],
-+ ack_dpcd_bytes_to_write);
-+ if (wret == ack_dpcd_bytes_to_write)
-+ break;
-+ }
-+
-+ /* check if there is new irq to be handle */
-+ dret = drm_dp_dpcd_read(
-+ &aconnector->dm_dp_aux.aux,
-+ dpcd_addr,
-+ esi,
-+ dpcd_bytes_to_read);
-+
-+ new_irq_handled = false;
-+ } else
-+ break;
-+ }
-+
-+ if (process_count == max_process_count)
-+ DRM_DEBUG_KMS("Loop exceeded max iterations\n");
-+}
-+
-+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;
-+ const struct dc_link *dc_link = aconnector->dc_link;
-+ bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
-+
-+ /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio
-+ * conflict, after implement i2c helper, this mutex should be
-+ * retired.
-+ */
-+ if (aconnector->dc_link->type != dc_connection_mst_branch)
-+ mutex_lock(&aconnector->hpd_lock);
-+
-+ 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_modeset_lock_all(dev);
-+ dm_restore_drm_connector_state(dev, connector);
-+ drm_modeset_unlock_all(dev);
-+
-+ drm_kms_helper_hotplug_event(dev);
-+ }
-+ }
-+ if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
-+ (dc_link->type == dc_connection_mst_branch))
-+ dm_handle_hpd_rx_irq(aconnector);
-+
-+ if (aconnector->dc_link->type != dc_connection_mst_branch)
-+ mutex_unlock(&aconnector->hpd_lock);
-+}
-+
-+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;
-+
-+ if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
-+ 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;
-+
-+ 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, AMDGPU_IH_CLIENTID_LEGACY, 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, AMDGPU_IH_CLIENTID_LEGACY, 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, AMDGPU_IH_CLIENTID_LEGACY, 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;
-+ /* indicate support of immediate flip */
-+ adev->ddev->mode_config.async_page_flip = true;
-+
-+ 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, 0, 0))
-+ 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;
-+ uint32_t link_cnt;
-+
-+ link_cnt = dm->dc->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 < dm->dc->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 = dm->dc->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_BONAIRE:
-+ case CHIP_HAWAII:
-+ case CHIP_TONGA:
-+ case CHIP_FIJI:
-+ case CHIP_CARRIZO:
-+ case CHIP_STONEY:
-+ case CHIP_POLARIS11:
-+ case CHIP_POLARIS10:
-+ 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
-+ ******************************************************************************/
-+
-+/**
-+ * 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, bool async)
-+{
-+ 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) {
-+ WARN_ON(1);
-+ return;
-+ }
-+
-+ addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
-+ addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
-+ addr.flip_immediate = async;
-+
-+ DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
-+ __func__,
-+ addr.address.grph.addr.high_part,
-+ addr.address.grph.addr.low_part);
-+
-+ dc_flip_surface_addrs(
-+ adev->dm.dc,
-+ dc_target_get_status(target)->surfaces,
-+ &addr, 1);
-+}
-+
-+static int amdgpu_notify_freesync(struct drm_device *dev, void *data,
-+ struct drm_file *filp)
-+{
-+ struct mod_freesync_params freesync_params;
-+ uint8_t num_targets;
-+ uint8_t i;
-+ struct dc_target *target;
-+
-+ struct amdgpu_device *adev = dev->dev_private;
-+ struct drm_amdgpu_freesync *args = data;
-+ int r = 0;
-+
-+ freesync_params.state = FREESYNC_STATE_FULLSCREEN;
-+ if (args->op == AMDGPU_FREESYNC_FULLSCREEN_ENTER)
-+ freesync_params.enable = true;
-+ else
-+ freesync_params.enable = false;
-+
-+ num_targets = dc_get_current_target_count(adev->dm.dc);
-+
-+ for (i = 0; i < num_targets; i++) {
-+
-+ target = dc_get_target_at_index(adev->dm.dc, i);
-+
-+ mod_freesync_update_state(adev->dm.freesync_module,
-+ target->streams,
-+ target->stream_count,
-+ &freesync_params);
-+ }
-+
-+ return r;
-+}
-+
-+#ifdef CONFIG_DRM_AMDGPU_CIK
-+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,
-+ .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 */
-+ .notify_freesync = amdgpu_notify_freesync,
-+};
-+#endif
-+
-+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,
-+ .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 */
-+ .notify_freesync = amdgpu_notify_freesync,
-+
-+};
-+
-+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,
-+ .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 */
-+ .notify_freesync = amdgpu_notify_freesync,
-+
-+};
-+
-+#if defined(CONFIG_DEBUG_KERNEL_DC)
-+
-+static ssize_t s3_debug_store(
-+ struct device *device,
-+ struct device_attribute *attr,
-+ const char *buf,
-+ size_t count)
-+{
-+ int ret;
-+ int s3_state;
-+ struct pci_dev *pdev = to_pci_dev(device);
-+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
-+ struct amdgpu_device *adev = drm_dev->dev_private;
-+
-+ ret = kstrtoint(buf, 0, &s3_state);
-+
-+ if (ret == 0) {
-+ if (s3_state) {
-+ dm_resume(adev);
-+ amdgpu_dm_display_resume(adev);
-+ drm_kms_helper_hotplug_event(adev->ddev);
-+ } else
-+ dm_suspend(adev);
-+ }
-+
-+ return ret == 0 ? count : 0;
-+}
-+
-+DEVICE_ATTR_WO(s3_debug);
-+
-+#endif
-+
-+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_BONAIRE:
-+ case CHIP_HAWAII:
-+ adev->mode_info.num_crtc = 6;
-+ adev->mode_info.num_hpd = 6;
-+ adev->mode_info.num_dig = 6;
-+#ifdef CONFIG_DRM_AMDGPU_CIK
-+ if (adev->mode_info.funcs == NULL)
-+ adev->mode_info.funcs = &dm_dce_v8_0_display_funcs;
-+#endif
-+ break;
-+ 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:
-+ 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;
-+ case CHIP_STONEY:
-+ adev->mode_info.num_crtc = 2;
-+ 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;
-+ case CHIP_POLARIS11:
-+ adev->mode_info.num_crtc = 5;
-+ adev->mode_info.num_hpd = 5;
-+ adev->mode_info.num_dig = 5;
-+ if (adev->mode_info.funcs == NULL)
-+ adev->mode_info.funcs = &dm_dce_v11_0_display_funcs;
-+ break;
-+ case CHIP_POLARIS10:
-+ adev->mode_info.num_crtc = 6;
-+ adev->mode_info.num_hpd = 6;
-+ adev->mode_info.num_dig = 6;
-+ 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() */
-+#if defined(CONFIG_DEBUG_KERNEL_DC)
-+ device_create_file(
-+ adev->ddev->dev,
-+ &dev_attr_s3_debug);
-+#endif
-+
-+ 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/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
-new file mode 100644
-index 0000000..1b54566
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
-@@ -0,0 +1,171 @@
-+/*
-+ * 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"
-+#include "signal_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;
-+ struct cgs_device *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;
-+
-+ struct mod_freesync *freesync_module;
-+};
-+
-+/* 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);
-+
-+extern const struct amdgpu_ip_block_version dm_ip_block;
-+
-+void amdgpu_dm_update_connector_after_detect(
-+ struct amdgpu_connector *aconnector);
-+
-+struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector(
-+ struct drm_atomic_state *state,
-+ struct drm_crtc *crtc,
-+ bool from_state_var);
-+
-+#endif /* __AMDGPU_DM_H__ */
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
-new file mode 100644
-index 0000000..e503677
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
-@@ -0,0 +1,483 @@
-+/*
-+ * 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 (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) {
-+ 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++;
-+ }
-+ }
-+ }
-+
-+ edid_caps->edid_hdmi = drm_detect_hdmi_monitor(
-+ (struct edid *) edid->raw_edid);
-+
-+ 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;
-+
-+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
-+ if (aconnector->dc_sink == sink)
-+ return aconnector;
-+ }
-+
-+ return NULL;
-+}
-+
-+static struct amdgpu_connector *get_connector_for_link(
-+ struct drm_device *dev,
-+ const struct dc_link *link)
-+{
-+ struct drm_connector *connector;
-+
-+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
-+ if (aconnector->dc_link == link)
-+ return aconnector;
-+ }
-+
-+ return NULL;
-+}
-+
-+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 || !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 || !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);
-+
-+ if (!aconnector || !aconnector->mst_port)
-+ return false;
-+
-+ mst_port = aconnector->port;
-+
-+ 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;
-+}
-+
-+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 (!aconnector) {
-+ DRM_ERROR("Failed to found connector for link!");
-+ return false;
-+ }
-+
-+ 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);
-+
-+ if (!aconnector) {
-+ DRM_ERROR("Failed to found connector for link!");
-+ return;
-+ }
-+
-+ 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/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
-new file mode 100644
-index 0000000..20e0749
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
-@@ -0,0 +1,829 @@
-+/*
-+ * 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_early(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: early resume\n");
-+
-+ /* re-enable short pulse interrupts HW interrupt */
-+ for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; 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;
-+}
-+
-+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[0]);
-+
-+ 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) {
-+ DRM_ERROR(
-+ "%s: crtc is NULL at id :%d\n",
-+ func,
-+ crtc_id);
-+ return 0;
-+ }
-+
-+ irq_source = dal_irq_type + acrtc->otg_inst;
-+
-+ 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 (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
-+ 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/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h
-new file mode 100644
-index 0000000..9339861
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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_early - enable HPDRX ASIC interrupts during resume.
-+ * amdgpu_dm_irq_resume - enable ASIC interrupt during resume.
-+ *
-+ */
-+int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev);
-+int amdgpu_dm_irq_resume(struct amdgpu_device *adev);
-+
-+#endif /* __AMDGPU_DM_IRQ_H__ */
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
-new file mode 100644
-index 0000000..3430d97
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
-@@ -0,0 +1,445 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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);
-+
-+ /*
-+ * 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,
-+ .set_property = drm_atomic_helper_connector_set_property,
-+ .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
-+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-+ .atomic_set_property = amdgpu_dm_connector_atomic_set_property
-+};
-+
-+static int dm_dp_mst_get_modes(struct drm_connector *connector)
-+{
-+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
-+ int ret = 0;
-+
-+ 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) {
-+ amdgpu_dm_remove_sink_from_freesync_module(connector);
-+ dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
-+ dc_sink_release(aconnector->dc_sink);
-+ aconnector->dc_sink = NULL;
-+ }
-+ if (aconnector->edid) {
-+ kfree(aconnector->edid);
-+ aconnector->edid = NULL;
-+ }
-+
-+ drm_mode_connector_update_edid_property(
-+ &aconnector->base,
-+ 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;
-+ struct drm_connector *connector;
-+ struct amdgpu_connector *aconnector;
-+ struct edid *edid;
-+
-+ drm_modeset_lock_all(dev);
-+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-+ aconnector = to_amdgpu_connector(connector);
-+ if (aconnector->port &&
-+ aconnector->port->pdt != DP_PEER_DEVICE_NONE &&
-+ aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING &&
-+ !aconnector->dc_sink) {
-+ /*
-+ * This is plug in case, where port has been created but
-+ * sink hasn't been created yet
-+ */
-+ if (!aconnector->edid) {
-+ struct dc_sink_init_data init_params = {
-+ .link = aconnector->dc_link,
-+ .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
-+ edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
-+
-+ if (!edid) {
-+ drm_mode_connector_update_edid_property(
-+ &aconnector->base,
-+ NULL);
-+ continue;
-+ }
-+
-+ aconnector->edid = edid;
-+
-+ aconnector->dc_sink = dc_link_add_remote_sink(
-+ aconnector->dc_link,
-+ (uint8_t *)edid,
-+ (edid->extensions + 1) * EDID_LENGTH,
-+ &init_params);
-+ if (aconnector->dc_sink)
-+ amdgpu_dm_add_sink_to_freesync_module(
-+ connector,
-+ edid);
-+
-+ dm_restore_drm_connector_state(connector->dev, connector);
-+ } else
-+ edid = aconnector->edid;
-+
-+ DRM_DEBUG_KMS("edid retrieved %p\n", edid);
-+
-+ drm_mode_connector_update_edid_property(
-+ &aconnector->base,
-+ aconnector->edid);
-+ }
-+ }
-+ drm_modeset_unlock_all(dev);
-+
-+ 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);
-+
-+}
-+
-+static const 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->ddev,
-+ &aconnector->dm_dp_aux.aux,
-+ 16,
-+ 4,
-+ aconnector->connector_id);
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
-new file mode 100644
-index 0000000..6130d62
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
-new file mode 100644
-index 0000000..9d51259
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
-@@ -0,0 +1,463 @@
-+/*
-+ * 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"
-+
-+#define dm_alloc(size) kzalloc(size, GFP_KERNEL)
-+#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL)
-+#define dm_free(ptr) kfree(ptr)
-+
-+/******************************************************************************
-+ * 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;
-+}
-+
-+bool dm_write_persistent_data(struct dc_context *ctx,
-+ const struct dc_sink *sink,
-+ const char *module_name,
-+ const char *key_name,
-+ void *params,
-+ unsigned int size,
-+ struct persistent_data_flag *flag)
-+{
-+ /*TODO implement*/
-+ return false;
-+}
-+
-+bool dm_read_persistent_data(struct dc_context *ctx,
-+ const struct dc_sink *sink,
-+ const char *module_name,
-+ const char *key_name,
-+ void *params,
-+ unsigned int size,
-+ struct persistent_data_flag *flag)
-+{
-+ /*TODO implement*/
-+ return false;
-+}
-+
-+void dm_delay_in_microseconds(struct dc_context *ctx,
-+ unsigned int microSeconds)
-+{
-+ /*TODO implement*/
-+ return;
-+}
-+
-+/**** power component interfaces ****/
-+
-+bool dm_pp_pre_dce_clock_change(
-+ struct dc_context *ctx,
-+ struct dm_pp_gpu_clock_range *requested_state,
-+ struct dm_pp_gpu_clock_range *actual_state)
-+{
-+ /*TODO*/
-+ return false;
-+}
-+
-+bool dm_pp_apply_safe_state(
-+ const struct dc_context *ctx)
-+{
-+ struct amdgpu_device *adev = ctx->driver_context;
-+
-+ if (adev->pm.dpm_enabled) {
-+ /* TODO: Does this require PreModeChange event to PPLIB? */
-+ }
-+
-+ return true;
-+}
-+
-+bool dm_pp_apply_display_requirements(
-+ const struct dc_context *ctx,
-+ const struct dm_pp_display_configuration *pp_display_cfg)
-+{
-+ 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.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
-+ 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;
-+}
-+
-+bool dc_service_get_system_clocks_range(
-+ const struct dc_context *ctx,
-+ struct dm_pp_gpu_clock_range *sys_clks)
-+{
-+ struct amdgpu_device *adev = ctx->driver_context;
-+
-+ /* Default values, in case PPLib is not compiled-in. */
-+ sys_clks->mclk.max_khz = 800000;
-+ sys_clks->mclk.min_khz = 800000;
-+
-+ sys_clks->sclk.max_khz = 600000;
-+ sys_clks->sclk.min_khz = 300000;
-+
-+ if (adev->pm.dpm_enabled) {
-+ sys_clks->mclk.max_khz = amdgpu_dpm_get_mclk(adev, false);
-+ sys_clks->mclk.min_khz = amdgpu_dpm_get_mclk(adev, true);
-+
-+ sys_clks->sclk.max_khz = amdgpu_dpm_get_sclk(adev, false);
-+ sys_clks->sclk.min_khz = amdgpu_dpm_get_sclk(adev, true);
-+ }
-+
-+ return true;
-+}
-+
-+static void get_default_clock_levels(
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_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 DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-+ clks->num_levels = 6;
-+ memmove(clks->clocks_in_khz, disp_clks_in_khz,
-+ sizeof(disp_clks_in_khz));
-+ break;
-+ case DM_PP_CLOCK_TYPE_ENGINE_CLK:
-+ clks->num_levels = 6;
-+ memmove(clks->clocks_in_khz, sclks_in_khz,
-+ sizeof(sclks_in_khz));
-+ break;
-+ case DM_PP_CLOCK_TYPE_MEMORY_CLK:
-+ clks->num_levels = 2;
-+ memmove(clks->clocks_in_khz, mclks_in_khz,
-+ sizeof(mclks_in_khz));
-+ break;
-+ default:
-+ clks->num_levels = 0;
-+ break;
-+ }
-+}
-+
-+static enum amd_pp_clock_type dc_to_pp_clock_type(
-+ enum dm_pp_clock_type dm_pp_clk_type)
-+{
-+ enum amd_pp_clock_type amd_pp_clk_type = 0;
-+
-+ switch (dm_pp_clk_type) {
-+ case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-+ amd_pp_clk_type = amd_pp_disp_clock;
-+ break;
-+ case DM_PP_CLOCK_TYPE_ENGINE_CLK:
-+ amd_pp_clk_type = amd_pp_sys_clock;
-+ break;
-+ case DM_PP_CLOCK_TYPE_MEMORY_CLK:
-+ amd_pp_clk_type = amd_pp_mem_clock;
-+ break;
-+ default:
-+ DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
-+ dm_pp_clk_type);
-+ break;
-+ }
-+
-+ return amd_pp_clk_type;
-+}
-+
-+static void pp_to_dc_clock_levels(
-+ const struct amd_pp_clocks *pp_clks,
-+ struct dm_pp_clock_levels *dc_clks,
-+ enum dm_pp_clock_type dc_clk_type)
-+{
-+ uint32_t i;
-+
-+ if (pp_clks->count > DM_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,
-+ DM_PP_MAX_CLOCK_LEVELS);
-+
-+ dc_clks->num_levels = DM_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;
-+ }
-+}
-+
-+bool dm_pp_get_clock_levels_by_type(
-+ const struct dc_context *ctx,
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels *dc_clks)
-+{
-+ 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 == DM_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 == DM_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;
-+ }
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+bool dm_pp_get_clock_levels_by_type_with_latency(
-+ const struct dc_context *ctx,
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels_with_latency *clk_level_info)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+bool dm_pp_get_clock_levels_by_type_with_voltage(
-+ const struct dc_context *ctx,
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels_with_voltage *clk_level_info)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+bool dm_pp_notify_wm_clock_changes(
-+ const struct dc_context *ctx,
-+ struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+bool dm_pp_apply_power_level_change_request(
-+ const struct dc_context *ctx,
-+ struct dm_pp_power_level_change_request *level_change_req)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+bool dm_pp_apply_clock_for_voltage_request(
-+ const struct dc_context *ctx,
-+ struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+bool dm_pp_get_static_clocks(
-+ const struct dc_context *ctx,
-+ struct dm_pp_static_clock_info *static_clk_info)
-+{
-+ /* TODO: to be implemented */
-+ return false;
-+}
-+
-+/**** 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/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
-new file mode 100644
-index 0000000..0311090
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
-@@ -0,0 +1,3312 @@
-+/*
-+ * 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 <drm/drm_edid.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"
-+
-+#include "modules/inc/mod_freesync.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
-+
-+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;
-+ attributes.height = height;
-+ 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(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_hotspot = xorigin;
-+ position.y_hotspot = yorigin;
-+
-+ if (amdgpu_crtc->target) {
-+ 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, bool addReq)
-+{
-+ uint64_t tiling_flags;
-+ uint64_t fb_location = 0;
-+ const struct drm_framebuffer *fb = &amdgpu_fb->base;
-+ struct drm_format_name_buf format_name;
-+
-+ get_fb_info(
-+ amdgpu_fb,
-+ &tiling_flags,
-+ addReq == true ? &fb_location:NULL);
-+
-+ 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->format->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;
-+ case DRM_FORMAT_XRGB2101010:
-+ case DRM_FORMAT_ARGB2101010:
-+ surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010;
-+ break;
-+ case DRM_FORMAT_XBGR2101010:
-+ case DRM_FORMAT_ABGR2101010:
-+ surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010;
-+ break;
-+ default:
-+ DRM_ERROR("Unsupported screen format %s\n",
-+ drm_get_format_name(fb->format->format, &format_name));
-+ 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.gfx8.num_banks = num_banks;
-+ surface->tiling_info.gfx8.array_mode =
-+ DC_ARRAY_2D_TILED_THIN1;
-+ surface->tiling_info.gfx8.tile_split = tile_split;
-+ surface->tiling_info.gfx8.bank_width = bankw;
-+ surface->tiling_info.gfx8.bank_height = bankh;
-+ surface->tiling_info.gfx8.tile_aspect = mtaspect;
-+ surface->tiling_info.gfx8.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.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
-+ }
-+
-+ surface->tiling_info.gfx8.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->format->cpp[0];
-+
-+ surface->visible = true;
-+ surface->scaling_quality.h_taps_c = 0;
-+ surface->scaling_quality.v_taps_c = 0;
-+
-+ /* TODO: unhardcode */
-+ surface->color_space = COLOR_SPACE_SRGB;
-+ /* is this needed? is surface zeroed at allocation? */
-+ surface->scaling_quality.h_taps = 0;
-+ surface->scaling_quality.v_taps = 0;
-+ 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 dc_gamma *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;
-+ struct amdgpu_device *adev = crtc->dev->dev_private;
-+
-+ red = crtc->gamma_store;
-+ green = red + crtc->gamma_size;
-+ blue = green + crtc->gamma_size;
-+
-+ gamma = dc_create_gamma(adev->dm.dc);
-+
-+ if (gamma == NULL)
-+ return;
-+
-+ 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);
-+
-+ dc_surface->gamma_correction = gamma;
-+}
-+
-+static void fill_plane_attributes(
-+ struct dc_surface *surface,
-+ struct drm_plane_state *state, bool addrReq)
-+{
-+ 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,
-+ addrReq);
-+
-+ /* 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 update_stream_scaling_settings(
-+ const struct drm_display_mode *mode,
-+ const struct dm_connector_state *dm_state,
-+ const struct dc_stream *stream)
-+{
-+ struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private;
-+ 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;
-+ }
-+
-+ adev->dm.dc->stream_funcs.stream_update_scaling(adev->dm.dc, 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 dc_surface *dc_surface;
-+ const struct dc_surface *dc_surfaces[1];
-+ 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;
-+ }
-+
-+ /* Surface programming */
-+ fill_plane_attributes(dc_surface, crtc->primary->state, true);
-+ 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;
-+ }
-+
-+ dc_surfaces[0] = dc_surface;
-+
-+ if (false == dc_commit_surfaces_to_target(
-+ dc,
-+ dc_surfaces,
-+ 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 enum dc_color_space get_output_color_space(
-+ const struct dc_crtc_timing *dc_crtc_timing)
-+{
-+ enum dc_color_space color_space = COLOR_SPACE_SRGB;
-+
-+ switch (dc_crtc_timing->pixel_encoding) {
-+ case PIXEL_ENCODING_YCBCR422:
-+ case PIXEL_ENCODING_YCBCR444:
-+ case PIXEL_ENCODING_YCBCR420:
-+ {
-+ /*
-+ * 27030khz is the separation point between HDTV and SDTV
-+ * according to HDMI spec, we use YCbCr709 and YCbCr601
-+ * respectively
-+ */
-+ if (dc_crtc_timing->pix_clk_khz > 27030) {
-+ if (dc_crtc_timing->flags.Y_ONLY)
-+ color_space =
-+ COLOR_SPACE_YCBCR709_LIMITED;
-+ else
-+ color_space = COLOR_SPACE_YCBCR709;
-+ } else {
-+ if (dc_crtc_timing->flags.Y_ONLY)
-+ color_space =
-+ COLOR_SPACE_YCBCR601_LIMITED;
-+ else
-+ color_space = COLOR_SPACE_YCBCR601;
-+ }
-+
-+ }
-+ break;
-+ case PIXEL_ENCODING_RGB:
-+ color_space = COLOR_SPACE_SRGB;
-+ break;
-+
-+ default:
-+ WARN_ON(1);
-+ break;
-+ }
-+
-+ return color_space;
-+}
-+
-+/*****************************************************************************/
-+
-+static void fill_stream_properties_from_drm_display_mode(
-+ struct dc_stream *stream,
-+ const struct drm_display_mode *mode_in,
-+ const struct drm_connector *connector)
-+{
-+ struct dc_crtc_timing *timing_out = &stream->timing;
-+ 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 */
-+
-+ if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
-+ && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
-+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
-+ else
-+ timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
-+
-+ 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);
-+ if (mode_in->flags & DRM_MODE_FLAG_PHSYNC)
-+ timing_out->flags.HSYNC_POSITIVE_POLARITY = 1;
-+ if (mode_in->flags & DRM_MODE_FLAG_PVSYNC)
-+ timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
-+
-+ stream->output_color_space = get_output_color_space(timing_out);
-+
-+}
-+
-+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 */
-+
-+}
-+
-+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,
-+ const struct drm_display_mode *drm_mode,
-+ const struct dm_connector_state *dm_state)
-+{
-+ struct drm_display_mode *preferred_mode = NULL;
-+ const struct drm_connector *drm_connector;
-+ 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;
-+ }
-+
-+ if (NULL == dm_state) {
-+ DRM_ERROR("dm_state is NULL!\n");
-+ goto dm_state_null;
-+ }
-+
-+ drm_connector = &aconnector->base;
-+ 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) {
-+ /* This may not be an error, the use case is when we we have no
-+ * usermode calls to reset and set mode upon hotplug. In this
-+ * case, we call set mode ourselves to restore the previous mode
-+ * and the modelist may not be filled in in time.
-+ */
-+ DRM_INFO("No preferred mode found\n");
-+ } else {
-+ decide_crtc_timing_for_drm_display_mode(
-+ &mode, preferred_mode,
-+ dm_state->scaling != RMX_OFF);
-+ }
-+
-+ fill_stream_properties_from_drm_display_mode(stream,
-+ &mode, &aconnector->base);
-+ update_stream_scaling_settings(&mode, dm_state, stream);
-+
-+ 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;
-+ }
-+
-+dm_state_null:
-+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 int amdgpu_dm_atomic_crtc_gamma_set(
-+ struct drm_crtc *crtc,
-+ u16 *red,
-+ u16 *green,
-+ u16 *blue,
-+ 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;
-+
-+ return 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;
-+}
-+
-+
-+static int amdgpu_atomic_helper_page_flip(struct drm_crtc *crtc,
-+ struct drm_framebuffer *fb,
-+ struct drm_pending_vblank_event *event,
-+ uint32_t flags)
-+{
-+ struct drm_plane *plane = crtc->primary;
-+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-+ struct drm_atomic_state *state;
-+ struct drm_plane_state *plane_state;
-+ struct drm_crtc_state *crtc_state;
-+ int ret = 0;
-+
-+ state = drm_atomic_state_alloc(plane->dev);
-+ if (!state)
-+ return -ENOMEM;
-+
-+ state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
-+retry:
-+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
-+ if (IS_ERR(crtc_state)) {
-+ ret = PTR_ERR(crtc_state);
-+ goto fail;
-+ }
-+ crtc_state->event = event;
-+
-+ plane_state = drm_atomic_get_plane_state(state, plane);
-+ if (IS_ERR(plane_state)) {
-+ ret = PTR_ERR(plane_state);
-+ goto fail;
-+ }
-+
-+ ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
-+ if (ret != 0)
-+ goto fail;
-+ drm_atomic_set_fb_for_plane(plane_state, fb);
-+
-+ /* Make sure we don't accidentally do a full modeset. */
-+ state->allow_modeset = false;
-+ if (!crtc_state->active) {
-+ DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
-+ crtc->base.id);
-+ ret = -EINVAL;
-+ goto fail;
-+ }
-+ acrtc->flip_flags = flags;
-+ ret = drm_atomic_nonblocking_commit(state);
-+ if (ret != 0)
-+ goto fail;
-+
-+ /* Driver takes ownership of state on successful async commit. */
-+ return 0;
-+fail:
-+ if (ret == -EDEADLK)
-+ goto backoff;
-+
-+ drm_atomic_state_put(state);
-+
-+ return ret;
-+backoff:
-+ drm_atomic_state_clear(state);
-+ drm_atomic_legacy_backoff(state);
-+
-+ /*
-+ * Someone might have exchanged the framebuffer while we dropped locks
-+ * in the backoff code. We need to fix up the fb refcount tracking the
-+ * core does for us.
-+ */
-+ plane->old_fb = plane->fb;
-+
-+ goto retry;
-+}
-+
-+/* 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 = amdgpu_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. */
-+
-+ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
-+ connected = (aconnector->dc_sink != NULL);
-+ else
-+ connected = (aconnector->base.force == DRM_FORCE_ON);
-+
-+ return (connected ? connector_status_connected :
-+ connector_status_disconnected);
-+}
-+
-+/* Compare user free sync property with immunable property free sync capable
-+ * and if display is not free sync capable sets free sync property to 0
-+ */
-+static int amdgpu_freesync_update_property_atomic(
-+ struct drm_connector *connector,
-+ uint64_t val_capable)
-+{
-+ struct drm_device *dev;
-+ struct amdgpu_device *adev;
-+ int ret;
-+ uint64_t val;
-+
-+ dev = connector->dev;
-+ adev = dev->dev_private;
-+
-+ ret = drm_object_property_get_value(
-+ &connector->base,
-+ adev->mode_info.freesync_property,
-+ &val);
-+ if (ret == 0 && val != 0 && val_capable == 0)
-+ ret = drm_object_property_set_value(
-+ &connector->base,
-+ adev->mode_info.freesync_property,
-+ val_capable);
-+ return ret;
-+
-+}
-+
-+static int amdgpu_freesync_set_property_atomic(
-+ struct drm_connector *connector,
-+ struct drm_connector_state *connector_state,
-+ struct drm_property *property, uint64_t val)
-+{
-+ struct mod_freesync_user_enable user_enable;
-+ struct drm_device *dev;
-+ struct amdgpu_device *adev;
-+ struct amdgpu_crtc *acrtc;
-+ int ret;
-+ uint64_t val_capable;
-+
-+ dev = connector->dev;
-+ adev = dev->dev_private;
-+ ret = -EINVAL;
-+
-+ if (adev->dm.freesync_module && connector_state->crtc) {
-+ ret = drm_object_property_get_value(
-+ &connector->base,
-+ adev->mode_info.freesync_capable_property,
-+ &val_capable);
-+ /* if user free sync val property is enable, but the capable
-+ * prop is not, then fail the call
-+ */
-+ if (ret != 0 || (val_capable == 0 && val != 0)) {
-+ ret = -EINVAL;
-+ goto release;
-+ }
-+
-+ user_enable.enable_for_gaming = val ? true : false;
-+ user_enable.enable_for_static = user_enable.enable_for_gaming;
-+ user_enable.enable_for_video = user_enable.enable_for_gaming;
-+ ret = -EINVAL;
-+ acrtc = to_amdgpu_crtc(connector_state->crtc);
-+ if (connector_state->connector == connector && acrtc->target) {
-+ mod_freesync_set_user_enable(adev->dm.freesync_module,
-+ acrtc->target->streams,
-+ acrtc->target->stream_count
-+ , &user_enable);
-+ ret = 0;
-+ }
-+ }
-+release:
-+ return ret;
-+}
-+
-+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);
-+
-+ struct drm_crtc_state *new_crtc_state;
-+ struct drm_crtc *crtc;
-+ int i;
-+ int ret = -EINVAL;
-+
-+ if (property == dev->mode_config.scaling_mode_property) {
-+ 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;
-+ ret = 0;
-+ } else if (property == adev->mode_info.underscan_hborder_property) {
-+ dm_new_state->underscan_hborder = val;
-+ ret = 0;
-+ } else if (property == adev->mode_info.underscan_vborder_property) {
-+ dm_new_state->underscan_vborder = val;
-+ ret = 0;
-+ } else if (property == adev->mode_info.underscan_property) {
-+ dm_new_state->underscan_enable = val;
-+ ret = 0;
-+ } else if (property == adev->mode_info.freesync_property) {
-+ ret = amdgpu_freesync_set_property_atomic(connector,
-+ connector_state,
-+ property, val);
-+ return ret;
-+ } else if (property == adev->mode_info.freesync_capable_property) {
-+ ret = -EINVAL;
-+ return ret;
-+ }
-+
-+
-+
-+ 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 ret;
-+}
-+
-+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 =
-+ kmemdup(state, sizeof(*state), GFP_KERNEL);
-+
-+ if (new_state) {
-+ __drm_atomic_helper_connector_duplicate_state(connector,
-+ &new_state->base);
-+ return &new_state->base;
-+ }
-+
-+ return NULL;
-+}
-+
-+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 = drm_atomic_helper_connector_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);
-+}
-+
-+static void create_eml_sink(struct amdgpu_connector *aconnector)
-+{
-+ struct dc_sink_init_data init_params = {
-+ .link = aconnector->dc_link,
-+ .sink_signal = SIGNAL_TYPE_VIRTUAL
-+ };
-+ struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
-+
-+ if (!aconnector->base.edid_blob_ptr ||
-+ !aconnector->base.edid_blob_ptr->data) {
-+ DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
-+ aconnector->base.name);
-+
-+ aconnector->base.force = DRM_FORCE_OFF;
-+ aconnector->base.override_edid = false;
-+ return;
-+ }
-+
-+ aconnector->edid = edid;
-+
-+ aconnector->dc_em_sink = dc_link_add_remote_sink(
-+ aconnector->dc_link,
-+ (uint8_t *)edid,
-+ (edid->extensions + 1) * EDID_LENGTH,
-+ &init_params);
-+
-+ if (aconnector->base.force
-+ == DRM_FORCE_ON)
-+ aconnector->dc_sink = aconnector->dc_link->local_sink ?
-+ aconnector->dc_link->local_sink :
-+ aconnector->dc_em_sink;
-+}
-+
-+static void handle_edid_mgmt(struct amdgpu_connector *aconnector)
-+{
-+ struct dc_link *link = (struct dc_link *)aconnector->dc_link;
-+
-+ /* In case of headless boot with force on for DP managed connector
-+ * Those settings have to be != 0 to get initial modeset
-+ */
-+ if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) {
-+ link->verified_link_cap.lane_count = LANE_COUNT_FOUR;
-+ link->verified_link_cap.link_rate = LINK_RATE_HIGH2;
-+ }
-+
-+
-+ aconnector->base.override_edid = true;
-+ create_eml_sink(aconnector);
-+}
-+
-+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;
-+ 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;
-+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
-+
-+ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
-+ (mode->flags & DRM_MODE_FLAG_DBLSCAN))
-+ return result;
-+
-+ /* Only run this the first time mode_valid is called to initilialize
-+ * EDID mgmt
-+ */
-+ if (aconnector->base.force != DRM_FORCE_UNSPECIFIED &&
-+ !aconnector->dc_em_sink)
-+ handle_edid_mgmt(aconnector);
-+
-+ dc_sink = to_amdgpu_connector(connector)->dc_sink;
-+
-+ 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);
-+ fill_stream_properties_from_drm_display_mode(streams[0], 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,
-+ bool commit_surface_required)
-+{
-+ 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;
-+ struct amdgpu_crtc *acrtc_new;
-+
-+ uint64_t old_tiling_flags;
-+ uint64_t new_tiling_flags;
-+
-+ bool page_flip_required;
-+
-+ 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 (commit_surface_required == true &&
-+ old_tiling_flags != new_tiling_flags)
-+ return false;
-+
-+ clear_unrelated_fields(&old_state_tmp);
-+ clear_unrelated_fields(&new_state_tmp);
-+
-+ page_flip_required = memcmp(&old_state_tmp,
-+ &new_state_tmp,
-+ sizeof(old_state_tmp)) == 0 ? true:false;
-+ if (new_state->crtc && page_flip_required == false) {
-+ acrtc_new = to_amdgpu_crtc(new_state->crtc);
-+ if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
-+ page_flip_required = true;
-+ }
-+ return page_flip_required;
-+}
-+
-+static int dm_plane_helper_prepare_fb(
-+ struct drm_plane *plane,
-+ struct drm_plane_state *new_state)
-+{
-+ struct amdgpu_framebuffer *afb;
-+ struct drm_gem_object *obj;
-+ struct amdgpu_bo *rbo;
-+ int r;
-+
-+ if (!new_state->fb) {
-+ DRM_DEBUG_KMS("No FB bound\n");
-+ return 0;
-+ }
-+
-+ afb = to_amdgpu_framebuffer(new_state->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,
-+ struct drm_plane_state *old_state)
-+{
-+ struct amdgpu_bo *rbo;
-+ struct amdgpu_framebuffer *afb;
-+ int r;
-+
-+ if (!old_state->fb)
-+ return;
-+
-+ afb = to_amdgpu_framebuffer(old_state->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);
-+
-+ fill_stream_properties_from_drm_display_mode(streams[0], 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,
-+ DRM_FORMAT_XRGB2101010,
-+ DRM_FORMAT_XBGR2101010,
-+ DRM_FORMAT_ARGB2101010,
-+ DRM_FORMAT_ABGR2101010,
-+};
-+
-+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), NULL,
-+ 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 */
-+
-+ mutex_init(&aconnector->hpd_lock);
-+
-+ /*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);
-+
-+ if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-+ connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
-+ drm_object_attach_property(&aconnector->base.base,
-+ adev->mode_info.freesync_property, 0);
-+ drm_object_attach_property(&aconnector->base.base,
-+ adev->mode_info.freesync_capable_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 */
-+
-+ DRM_DEBUG_KMS("crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
-+ state->enable,
-+ state->active,
-+ state->planes_changed,
-+ state->mode_changed,
-+ state->active_changed,
-+ state->connectors_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 && state->connectors_changed)
-+ return DM_COMMIT_ACTION_SET;
-+
-+ 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;
-+ }
-+ }
-+}
-+
-+
-+typedef bool (*predicate)(struct amdgpu_crtc *acrtc);
-+
-+static void wait_while_pflip_status(struct amdgpu_device *adev,
-+ struct amdgpu_crtc *acrtc, predicate f) {
-+ int count = 0;
-+ while (f(acrtc)) {
-+ /* Spin Wait*/
-+ msleep(1);
-+ count++;
-+ if (count == 1000) {
-+ DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n",
-+ __func__, acrtc->crtc_id,
-+ acrtc,
-+ acrtc->pflip_status);
-+
-+ /* we do not expect to hit this case except on Polaris with PHY PLL
-+ * 1. DP to HDMI passive dongle connected
-+ * 2. unplug (headless)
-+ * 3. plug in DP
-+ * 3a. on plug in, DP will try verify link by training, and training
-+ * would disable PHY PLL which HDMI rely on to drive TG
-+ * 3b. this will cause flip interrupt cannot be generated, and we
-+ * exit when timeout expired. however we do not have code to clean
-+ * up flip, flip clean up will happen when the address is written
-+ * with the restore mode change
-+ */
-+ WARN_ON(1);
-+ break;
-+ }
-+ }
-+
-+ DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n",
-+ __func__,
-+ count,
-+ acrtc->crtc_id,
-+ acrtc,
-+ acrtc->pflip_status);
-+}
-+
-+static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc)
-+{
-+ return acrtc->pflip_status != AMDGPU_FLIP_NONE;
-+}
-+
-+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 {
-+ wait_while_pflip_status(adev, acrtc,
-+ pflip_in_progress_predicate);
-+
-+ amdgpu_irq_put(
-+ adev,
-+ &adev->pageflip_irq,
-+ irq_type);
-+ drm_crtc_vblank_off(&acrtc->base);
-+ }
-+}
-+
-+
-+static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc)
-+{
-+ return acrtc->pflip_status == AMDGPU_FLIP_PENDING;
-+}
-+
-+static bool is_scaling_state_different(
-+ const struct dm_connector_state *dm_state,
-+ const struct dm_connector_state *old_dm_state)
-+{
-+ if (dm_state->scaling != old_dm_state->scaling)
-+ return true;
-+ if (!dm_state->underscan_enable && old_dm_state->underscan_enable) {
-+ if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0)
-+ return true;
-+ } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) {
-+ if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0)
-+ return true;
-+ } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder
-+ || dm_state->underscan_vborder != old_dm_state->underscan_vborder)
-+ return true;
-+ return false;
-+}
-+
-+static void remove_target(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc)
-+{
-+ int i;
-+
-+ /*
-+ * we evade vblanks and pflips on crtc that
-+ * should be changed
-+ */
-+ manage_dm_interrupts(adev, acrtc, false);
-+ /* this is the update mode case */
-+ if (adev->dm.freesync_module)
-+ for (i = 0; i < acrtc->target->stream_count; i++)
-+ mod_freesync_remove_stream(
-+ adev->dm.freesync_module,
-+ acrtc->target->streams[i]);
-+ dc_target_release(acrtc->target);
-+ acrtc->target = NULL;
-+ acrtc->otg_inst = -1;
-+ acrtc->enabled = false;
-+}
-+
-+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 = 0;
-+ 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[MAX_TARGETS];
-+ struct amdgpu_crtc *new_crtcs[MAX_TARGETS];
-+ struct dc_target *new_target;
-+
-+ /* In this step all new fb would be pinned */
-+
-+ /*
-+ * TODO: Revisit when we support true asynchronous commit.
-+ * Right now we receive async commit only from pageflip, in which case
-+ * we should not pin/unpin the fb here, it should be done in
-+ * amdgpu_crtc_flip and from the vblank irq handler.
-+ */
-+ if (!async) {
-+ 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(state, true);
-+
-+ /*
-+ * 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;
-+
-+ acrtc = to_amdgpu_crtc(crtc);
-+
-+ aconnector =
-+ amdgpu_dm_find_first_crct_matching_connector(
-+ state,
-+ crtc,
-+ false);
-+
-+ /* handles headless hotplug case, updating new_state and
-+ * aconnector as needed
-+ */
-+
-+ action = get_dm_commit_action(new_state);
-+
-+ switch (action) {
-+ case DM_COMMIT_ACTION_DPMS_ON:
-+ case DM_COMMIT_ACTION_SET: {
-+ struct dm_connector_state *dm_state = NULL;
-+ new_target = NULL;
-+
-+ if (aconnector)
-+ dm_state = to_dm_connector_state(aconnector->base.state);
-+
-+ new_target = create_target_for_sink(
-+ aconnector,
-+ &crtc->state->mode,
-+ dm_state);
-+
-+ DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc);
-+
-+ 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
-+ *
-+ * In this case, we want to pretend we still
-+ * have a sink to keep the pipe running so that
-+ * hw state is consistent with the sw state
-+ */
-+ DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
-+ __func__, acrtc->base.base.id);
-+ break;
-+ }
-+
-+ if (acrtc->target)
-+ remove_target(adev, acrtc);
-+
-+ /*
-+ * 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;
-+ acrtc->hw_mode = crtc->state->mode;
-+ crtc->hwmode = crtc->state->mode;
-+
-+ break;
-+ }
-+
-+ case DM_COMMIT_ACTION_NOTHING: {
-+ struct dm_connector_state *dm_state = NULL;
-+
-+ if (!aconnector)
-+ break;
-+
-+ dm_state = to_dm_connector_state(aconnector->base.state);
-+
-+ /* Scaling update */
-+ update_stream_scaling_settings(
-+ &crtc->state->mode,
-+ dm_state,
-+ acrtc->target->streams[0]);
-+
-+ break;
-+ }
-+ case DM_COMMIT_ACTION_DPMS_OFF:
-+ case DM_COMMIT_ACTION_RESET:
-+ DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc);
-+ /* i.e. reset mode */
-+ if (acrtc->target)
-+ remove_target(adev, acrtc);
-+ break;
-+ } /* switch() */
-+ } /* for_each_crtc_in_state() */
-+
-+ 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;
-+ }
-+ }
-+
-+ /*
-+ * Add streams after required streams from new and replaced targets
-+ * are removed from freesync module
-+ */
-+ if (adev->dm.freesync_module) {
-+ for (i = 0; i < new_crtcs_count; i++) {
-+ struct amdgpu_connector *aconnector = NULL;
-+ new_target = new_crtcs[i]->target;
-+ aconnector =
-+ amdgpu_dm_find_first_crct_matching_connector(
-+ state,
-+ &new_crtcs[i]->base,
-+ false);
-+ if (!aconnector) {
-+ DRM_INFO(
-+ "Atomic commit: Failed to find connector for acrtc id:%d "
-+ "skipping freesync init\n",
-+ new_crtcs[i]->crtc_id);
-+ continue;
-+ }
-+
-+ for (j = 0; j < new_target->stream_count; j++)
-+ mod_freesync_add_stream(
-+ adev->dm.freesync_module,
-+ new_target->streams[j], &aconnector->caps);
-+ }
-+ }
-+
-+ /* DC is optimized not to do anything if 'targets' didn't change. */
-+ dc_commit_targets(dm->dc, commit_targets, commit_targets_count);
-+
-+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-+
-+ if (acrtc->target != NULL)
-+ acrtc->otg_inst =
-+ dc_target_get_status(acrtc->target)->primary_otg_inst;
-+ }
-+
-+ /* 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 amdgpu_crtc *acrtc = to_amdgpu_crtc(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, true) ||
-+ 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;
-+
-+ /*
-+ * if flip is pending (ie, still waiting for fence to return
-+ * before address is submitted) here, we cannot commit_surface
-+ * as commit_surface will pre-maturely write out the future
-+ * address. wait until flip is submitted before proceeding.
-+ */
-+ wait_while_pflip_status(adev, acrtc, pflip_pending_predicate);
-+
-+ dm_dc_surface_commit(dm->dc, crtc);
-+ }
-+ }
-+
-+ for (i = 0; i < new_crtcs_count; i++) {
-+ /*
-+ * loop to enable interrupts on newly arrived crtc
-+ */
-+ struct amdgpu_crtc *acrtc = new_crtcs[i];
-+
-+ if (adev->dm.freesync_module) {
-+ for (j = 0; j < acrtc->target->stream_count; j++)
-+ mod_freesync_notify_mode_change(
-+ adev->dm.freesync_module,
-+ acrtc->target->streams,
-+ acrtc->target->stream_count);
-+ }
-+
-+ 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 amdgpu_crtc *acrtc = to_amdgpu_crtc(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, false)) {
-+ ret = amdgpu_crtc_page_flip_target(crtc,
-+ fb,
-+ crtc->state->event,
-+ acrtc->flip_flags,
-+ drm_crtc_vblank_count(crtc));
-+ /*clean up the flags for next usage*/
-+ acrtc->flip_flags = 0;
-+ if (ret)
-+ return ret;
-+ }
-+ }
-+
-+ /* In this state all old framebuffers would be unpinned */
-+
-+ /* TODO: Revisit when we support true asynchronous commit.*/
-+ if (!async)
-+ drm_atomic_helper_cleanup_planes(dev, state);
-+
-+ drm_atomic_state_put(state);
-+
-+ return ret;
-+}
-+/*
-+ * This functions handle all cases when set mode does not come upon hotplug.
-+ * This include when the same display is unplugged then plugged back into the
-+ * same port and when we are running without usermode desktop manager supprot
-+ */
-+void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector)
-+{
-+ struct drm_crtc *crtc;
-+ struct amdgpu_device *adev = dev->dev_private;
-+ struct dc *dc = adev->dm.dc;
-+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
-+ struct amdgpu_crtc *disconnected_acrtc;
-+ const struct dc_sink *sink;
-+ struct dc_target *commit_targets[6];
-+ struct dc_target *current_target;
-+ uint32_t commit_targets_count = 0;
-+ int i;
-+
-+ if (!aconnector->dc_sink || !connector->state || !connector->encoder)
-+ return;
-+
-+ disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
-+
-+ if (!disconnected_acrtc || !disconnected_acrtc->target)
-+ return;
-+
-+ sink = disconnected_acrtc->target->streams[0]->sink;
-+
-+ /*
-+ * If the previous sink is not released and different from the current,
-+ * we deduce we are in a state where we can not rely on usermode call
-+ * to turn on the display, so we do it here
-+ */
-+ if (sink != aconnector->dc_sink) {
-+ struct dm_connector_state *dm_state =
-+ to_dm_connector_state(aconnector->base.state);
-+
-+ struct dc_target *new_target =
-+ create_target_for_sink(
-+ aconnector,
-+ &disconnected_acrtc->base.state->mode,
-+ dm_state);
-+
-+ DRM_INFO("Headless hotplug, restoring connector state\n");
-+ /*
-+ * we evade vblanks and pflips on crtc that
-+ * should be changed
-+ */
-+ manage_dm_interrupts(adev, disconnected_acrtc, false);
-+ /* this is the update mode case */
-+
-+ current_target = disconnected_acrtc->target;
-+
-+ disconnected_acrtc->target = new_target;
-+ disconnected_acrtc->enabled = true;
-+ disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode;
-+
-+ 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. */
-+ if (!dc_commit_targets(dc, commit_targets,
-+ commit_targets_count)) {
-+ DRM_INFO("Failed to restore connector state!\n");
-+ dc_target_release(disconnected_acrtc->target);
-+ disconnected_acrtc->target = current_target;
-+ manage_dm_interrupts(adev, disconnected_acrtc, true);
-+ return;
-+ }
-+
-+ if (adev->dm.freesync_module) {
-+
-+ for (i = 0; i < current_target->stream_count; i++)
-+ mod_freesync_remove_stream(
-+ adev->dm.freesync_module,
-+ current_target->streams[i]);
-+
-+ for (i = 0; i < new_target->stream_count; i++)
-+ mod_freesync_add_stream(
-+ adev->dm.freesync_module,
-+ new_target->streams[i],
-+ &aconnector->caps);
-+ }
-+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-+
-+ if (acrtc->target != NULL) {
-+ acrtc->otg_inst =
-+ dc_target_get_status(acrtc->target)->primary_otg_inst;
-+ }
-+ }
-+
-+ dc_target_release(current_target);
-+
-+ dm_dc_surface_commit(dc, &disconnected_acrtc->base);
-+
-+ manage_dm_interrupts(adev, disconnected_acrtc, true);
-+ dm_crtc_cursor_reset(&disconnected_acrtc->base);
-+
-+ }
-+}
-+
-+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,
-+ struct drm_crtc **crtcs,
-+ uint32_t set_count,
-+ const struct dc_target *old_target,
-+ const struct dc_target *new_target,
-+ struct drm_crtc *crtc)
-+{
-+ uint32_t i = 0;
-+
-+ while (i < set_count) {
-+ if (val_sets[i].target == old_target)
-+ break;
-+ ++i;
-+ }
-+
-+ val_sets[i].target = new_target;
-+ crtcs[i] = crtc;
-+
-+ 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)
-+{
-+ int i;
-+
-+ for (i = 0; i < set_count; i++)
-+ if (val_sets[i].target == target)
-+ break;
-+
-+ if (i == set_count) {
-+ /* nothing found */
-+ return set_count;
-+ }
-+
-+ set_count--;
-+
-+ for (; i < set_count; i++) {
-+ val_sets[i] = val_sets[i + 1];
-+ }
-+
-+ return set_count;
-+}
-+
-+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, j;
-+ int ret;
-+ int set_count;
-+ int new_target_count;
-+ struct dc_validation_set set[MAX_TARGETS] = {{ 0 }};
-+ struct dc_target *new_targets[MAX_TARGETS] = { 0 };
-+ struct drm_crtc *crtc_set[MAX_TARGETS] = { 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;
-+ crtc_set[set_count] = crtc;
-+ ++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;
-+
-+ acrtc = to_amdgpu_crtc(crtc);
-+
-+ aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
-+
-+ action = get_dm_commit_action(crtc_state);
-+
-+ switch (action) {
-+ case DM_COMMIT_ACTION_DPMS_ON:
-+ case DM_COMMIT_ACTION_SET: {
-+ struct dc_target *new_target = NULL;
-+ struct drm_connector_state *conn_state = NULL;
-+ struct dm_connector_state *dm_state = NULL;
-+
-+ if (aconnector) {
-+ conn_state = drm_atomic_get_connector_state(state, &aconnector->base);
-+ if (IS_ERR(conn_state))
-+ return ret;
-+ dm_state = to_dm_connector_state(conn_state);
-+ }
-+
-+ new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state);
-+
-+ /*
-+ * 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,
-+ crtc_set,
-+ set_count,
-+ acrtc->target,
-+ new_target,
-+ crtc);
-+
-+ new_target_count++;
-+ need_to_validate = true;
-+ break;
-+ }
-+
-+ case DM_COMMIT_ACTION_NOTHING: {
-+ const struct drm_connector *drm_connector = NULL;
-+ struct drm_connector_state *conn_state = NULL;
-+ struct dm_connector_state *dm_state = NULL;
-+ struct dm_connector_state *old_dm_state = NULL;
-+ struct dc_target *new_target;
-+
-+ if (!aconnector)
-+ break;
-+
-+ for_each_connector_in_state(
-+ state, drm_connector, conn_state, j) {
-+ if (&aconnector->base == drm_connector)
-+ break;
-+ }
-+
-+ old_dm_state = to_dm_connector_state(drm_connector->state);
-+ dm_state = to_dm_connector_state(conn_state);
-+
-+ /* Support underscan adjustment*/
-+ if (!is_scaling_state_different(dm_state, old_dm_state))
-+ break;
-+
-+ new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state);
-+
-+ if (!new_target) {
-+ DRM_ERROR("%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,
-+ crtc_set,
-+ set_count,
-+ acrtc->target,
-+ new_target,
-+ crtc);
-+
-+ new_target_count++;
-+ need_to_validate = true;
-+
-+ 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_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_set[i] != 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,
-+ true) ||
-+ action == DM_COMMIT_ACTION_DPMS_ON ||
-+ action == DM_COMMIT_ACTION_SET) {
-+ struct dc_surface *surface;
-+
-+ 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;
-+
-+ surface = dc_create_surface(dc);
-+ fill_plane_attributes(
-+ surface,
-+ plane_state,
-+ false);
-+
-+ add_val_sets_surface(
-+ set,
-+ set_count,
-+ set[i].target,
-+ surface);
-+
-+ need_to_validate = true;
-+ }
-+ }
-+ }
-+
-+ if (need_to_validate == false || set_count == 0 ||
-+ dc_validate_resources(dc, set, set_count))
-+ ret = 0;
-+
-+ 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;
-+}
-+
-+static bool is_dp_capable_without_timing_msa(
-+ struct dc *dc,
-+ struct amdgpu_connector *amdgpu_connector)
-+{
-+ uint8_t dpcd_data;
-+ bool capable = false;
-+ if (amdgpu_connector->dc_link &&
-+ dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index,
-+ DP_DOWN_STREAM_PORT_COUNT,
-+ &dpcd_data, sizeof(dpcd_data)) )
-+ capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false;
-+
-+ return capable;
-+}
-+void amdgpu_dm_add_sink_to_freesync_module(
-+ struct drm_connector *connector,
-+ struct edid *edid)
-+{
-+ int i;
-+ uint64_t val_capable;
-+ bool edid_check_required;
-+ struct detailed_timing *timing;
-+ struct detailed_non_pixel *data;
-+ struct detailed_data_monitor_range *range;
-+ struct amdgpu_connector *amdgpu_connector =
-+ to_amdgpu_connector(connector);
-+
-+ struct drm_device *dev = connector->dev;
-+ struct amdgpu_device *adev = dev->dev_private;
-+ edid_check_required = false;
-+ if (!amdgpu_connector->dc_sink) {
-+ DRM_ERROR("dc_sink NULL, could not add free_sync module.\n");
-+ return;
-+ }
-+ if (!adev->dm.freesync_module)
-+ return;
-+ /*
-+ * if edid non zero restrict freesync only for dp and edp
-+ */
-+ if (edid) {
-+ if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT
-+ || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) {
-+ edid_check_required = is_dp_capable_without_timing_msa(
-+ adev->dm.dc,
-+ amdgpu_connector);
-+ }
-+ }
-+ val_capable = 0;
-+ if (edid_check_required == true && (edid->version > 1 ||
-+ (edid->version == 1 && edid->revision > 1))) {
-+ for (i = 0; i < 4; i++) {
-+
-+ timing = &edid->detailed_timings[i];
-+ data = &timing->data.other_data;
-+ range = &data->data.range;
-+ /*
-+ * Check if monitor has continuous frequency mode
-+ */
-+ if (data->type != EDID_DETAIL_MONITOR_RANGE)
-+ continue;
-+ /*
-+ * Check for flag range limits only. If flag == 1 then
-+ * no additional timing information provided.
-+ * Default GTF, GTF Secondary curve and CVT are not
-+ * supported
-+ */
-+ if (range->flags != 1)
-+ continue;
-+
-+ amdgpu_connector->min_vfreq = range->min_vfreq;
-+ amdgpu_connector->max_vfreq = range->max_vfreq;
-+ amdgpu_connector->pixel_clock_mhz =
-+ range->pixel_clock_mhz * 10;
-+ break;
-+ }
-+
-+ if (amdgpu_connector->max_vfreq -
-+ amdgpu_connector->min_vfreq > 10) {
-+ amdgpu_connector->caps.supported = true;
-+ amdgpu_connector->caps.min_refresh_in_micro_hz =
-+ amdgpu_connector->min_vfreq * 1000000;
-+ amdgpu_connector->caps.max_refresh_in_micro_hz =
-+ amdgpu_connector->max_vfreq * 1000000;
-+ val_capable = 1;
-+ }
-+ }
-+ drm_object_property_set_value(&connector->base,
-+ adev->mode_info.freesync_capable_property,
-+ val_capable);
-+ amdgpu_freesync_update_property_atomic(connector, val_capable);
-+
-+}
-+
-+void amdgpu_dm_remove_sink_from_freesync_module(
-+ struct drm_connector *connector)
-+{
-+ struct amdgpu_connector *amdgpu_connector =
-+ to_amdgpu_connector(connector);
-+
-+ struct drm_device *dev = connector->dev;
-+ struct amdgpu_device *adev = dev->dev_private;
-+
-+ if (!amdgpu_connector->dc_sink || !adev->dm.freesync_module) {
-+ DRM_ERROR("dc_sink NULL or no free_sync module.\n");
-+ return;
-+ }
-+
-+ amdgpu_connector->min_vfreq = 0;
-+ amdgpu_connector->max_vfreq = 0;
-+ amdgpu_connector->pixel_clock_mhz = 0;
-+
-+ memset(&amdgpu_connector->caps, 0, sizeof(amdgpu_connector->caps));
-+
-+ drm_object_property_set_value(&connector->base,
-+ adev->mode_info.freesync_capable_property,
-+ 0);
-+ amdgpu_freesync_update_property_atomic(connector, 0);
-+
-+}
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
-new file mode 100644
-index 0000000..4f7bd3ba
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
-@@ -0,0 +1,101 @@
-+/*
-+ * 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);
-+
-+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);
-+
-+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);
-+
-+void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector);
-+
-+void amdgpu_dm_add_sink_to_freesync_module(
-+ struct drm_connector *connector,
-+ struct edid *edid);
-+
-+void amdgpu_dm_remove_sink_from_freesync_module(
-+ struct drm_connector *connector);
-+
-+extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
-+
-+#endif /* __AMDGPU_DM_TYPES_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
-new file mode 100644
-index 0000000..5fac034
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/Makefile
-@@ -0,0 +1,28 @@
-+#
-+# Makefile for Display Core (dc) component.
-+#
-+
-+DC_LIBS = basics bios calcs dce \
-+gpio gpu i2caux irq virtual
-+
-+DC_LIBS += dce112
-+DC_LIBS += dce110
-+DC_LIBS += dce100
-+DC_LIBS += dce80
-+
-+AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS)))
-+
-+include $(AMD_DC)
-+
-+DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \
-+dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o
-+
-+AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
-+
-+AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o)
-+
-+AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE)
-+AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE)
-+
-+
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile
-new file mode 100644
-index 0000000..a263cad
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile
-@@ -0,0 +1,11 @@
-+#
-+# Makefile for the 'utils' sub-component of DAL.
-+# It provides the general basic services required by other DAL
-+# subcomponents.
-+
-+BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \
-+ logger.o log_helpers.o register_logger.o signal_types.o vector.o
-+
-+AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_BASICS)
-diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c
-new file mode 100644
-index 0000000..ebe14e1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.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"
-+
-+#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/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h
-new file mode 100644
-index 0000000..18cbe41
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.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 __DAL_CONVERSION_H__
-+#define __DAL_CONVERSION_H__
-+
-+#include "include/fixed31_32.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/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
-new file mode 100644
-index 0000000..5a6e4684
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
-@@ -0,0 +1,691 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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/display/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c
-new file mode 100644
-index 0000000..911e90b
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c
-@@ -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
-+ *
-+ */
-+
-+#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;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c
-new file mode 100644
-index 0000000..9c80847
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c
-new file mode 100644
-index 0000000..61f36a7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c
-@@ -0,0 +1,100 @@
-+/*
-+ * 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 "core_types.h"
-+#include "logger.h"
-+#include "include/logger_interface.h"
-+
-+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-+
-+struct dc_signal_type_info {
-+ enum signal_type type;
-+ char name[MAX_NAME_LEN];
-+};
-+
-+static const struct dc_signal_type_info signal_type_info_tbl[] = {
-+ {SIGNAL_TYPE_NONE, "NC"},
-+ {SIGNAL_TYPE_DVI_SINGLE_LINK, "DVI"},
-+ {SIGNAL_TYPE_DVI_DUAL_LINK, "DDVI"},
-+ {SIGNAL_TYPE_HDMI_TYPE_A, "HDMIA"},
-+ {SIGNAL_TYPE_LVDS, "LVDS"},
-+ {SIGNAL_TYPE_RGB, "VGA"},
-+ {SIGNAL_TYPE_DISPLAY_PORT, "DP"},
-+ {SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"},
-+ {SIGNAL_TYPE_EDP, "eDP"},
-+ {SIGNAL_TYPE_WIRELESS, "Wireless"},
-+ {SIGNAL_TYPE_VIRTUAL, "Virtual"}
-+};
-+
-+void dc_conn_log(struct dc_context *ctx,
-+ const struct dc_link *link,
-+ uint8_t *hex_data,
-+ int hex_data_count,
-+ enum dc_log_type event,
-+ const char *msg,
-+ ...)
-+{
-+ int i;
-+ va_list args;
-+ struct log_entry entry = { 0 };
-+ enum signal_type signal;
-+
-+ if (link->local_sink)
-+ signal = link->local_sink->sink_signal;
-+ else
-+ signal = link->connector_signal;
-+
-+ if (link->type == dc_connection_mst_branch)
-+ signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
-+
-+ dm_logger_open(ctx->logger, &entry, event);
-+
-+ for (i = 0; i < NUM_ELEMENTS(signal_type_info_tbl); i++)
-+ if (signal == signal_type_info_tbl[i].type)
-+ break;
-+
-+ dm_logger_append(&entry, "[%s][ConnIdx:%d] ",
-+ signal_type_info_tbl[i].name,
-+ link->link_index);
-+
-+ va_start(args, msg);
-+ entry.buf_offset += dm_log_to_buffer(
-+ &entry.buf[entry.buf_offset],
-+ LOG_MAX_LINE_SIZE - entry.buf_offset,
-+ msg, args);
-+
-+ if (entry.buf[strlen(entry.buf) - 1] == '\n') {
-+ entry.buf[strlen(entry.buf) - 1] = '\0';
-+ entry.buf_offset--;
-+ }
-+
-+ if (hex_data)
-+ for (i = 0; i < hex_data_count; i++)
-+ dm_logger_append(&entry, "%2.2X ", hex_data[i]);
-+
-+ dm_logger_append(&entry, "^\n");
-+ dm_logger_close(&entry);
-+ va_end(args);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c
-new file mode 100644
-index 0000000..a5625a3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c
-@@ -0,0 +1,457 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "logger.h"
-+
-+
-+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-+
-+static const struct dc_log_type_info log_type_info_tbl[] = {
-+ {LOG_ERROR, "Error"},
-+ {LOG_WARNING, "Warning"},
-+ {LOG_DC, "DC_Interface"},
-+ {LOG_SURFACE, "Surface"},
-+ {LOG_HW_HOTPLUG, "HW_Hotplug"},
-+ {LOG_HW_LINK_TRAINING, "HW_LKTN"},
-+ {LOG_HW_SET_MODE, "HW_Mode"},
-+ {LOG_HW_RESUME_S3, "HW_Resume"},
-+ {LOG_HW_AUDIO, "HW_Audio"},
-+ {LOG_HW_HPD_IRQ, "HW_HPDIRQ"},
-+ {LOG_MST, "MST"},
-+ {LOG_SCALER, "Scaler"},
-+ {LOG_BIOS, "BIOS"},
-+ {LOG_BANDWIDTH_CALCS, "BWCalcs"},
-+ {LOG_BANDWIDTH_VALIDATION, "BWValidation"},
-+ {LOG_I2C_AUX, "I2C_AUX"},
-+ {LOG_SYNC, "Sync"},
-+ {LOG_BACKLIGHT, "Backlight"},
-+ {LOG_FEATURE_OVERRIDE, "Override"},
-+ {LOG_DETECTION_EDID_PARSER, "Edid"},
-+ {LOG_DETECTION_DP_CAPS, "DP_Caps"},
-+ {LOG_RESOURCE, "Resource"},
-+ {LOG_DML, "DML"},
-+ {LOG_EVENT_MODE_SET, "Mode"},
-+ {LOG_EVENT_DETECTION, "Detect"},
-+ {LOG_EVENT_LINK_TRAINING, "LKTN"},
-+ {LOG_EVENT_LINK_LOSS, "LinkLoss"},
-+ {LOG_EVENT_UNDERFLOW, "Underflow"},
-+ {LOG_IF_TRACE, "InterfaceTrace"}
-+};
-+
-+
-+#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \
-+ (1 << LOG_WARNING) | \
-+ (1 << LOG_EVENT_MODE_SET) | \
-+ (1 << LOG_EVENT_DETECTION) | \
-+ (1 << LOG_EVENT_LINK_TRAINING) | \
-+ (1 << LOG_EVENT_LINK_LOSS) | \
-+ (1 << LOG_EVENT_UNDERFLOW) | \
-+ (1 << LOG_RESOURCE) | \
-+ (1 << LOG_FEATURE_OVERRIDE) | \
-+ (1 << LOG_DETECTION_EDID_PARSER) | \
-+ (1 << LOG_DC) | \
-+ (1 << LOG_HW_HOTPLUG) | \
-+ (1 << LOG_HW_SET_MODE) | \
-+ (1 << LOG_HW_RESUME_S3) | \
-+ (1 << LOG_HW_HPD_IRQ) | \
-+ (1 << LOG_SYNC) | \
-+ (1 << LOG_BANDWIDTH_VALIDATION) | \
-+ (1 << LOG_MST) | \
-+ (1 << LOG_BIOS) | \
-+ (1 << LOG_DETECTION_EDID_PARSER) | \
-+ (1 << LOG_DETECTION_DP_CAPS) | \
-+ (1 << LOG_BACKLIGHT)) | \
-+ (1 << LOG_I2C_AUX) | \
-+ (1 << LOG_IF_TRACE) /* | \
-+ (1 << LOG_SURFACE) | \
-+ (1 << LOG_SCALER) | \
-+ (1 << LOG_DML) | \
-+ (1 << LOG_HW_LINK_TRAINING) | \
-+ (1 << LOG_HW_AUDIO)| \
-+ (1 << LOG_BANDWIDTH_CALCS)*/
-+
-+/* ----------- Object init and destruction ----------- */
-+static bool construct(struct dc_context *ctx, struct dal_logger *logger)
-+{
-+ /* malloc buffer and init offsets */
-+ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
-+ logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size *
-+ sizeof(char));
-+
-+ if (!logger->log_buffer)
-+ return false;
-+
-+ /* 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;
-+
-+ logger->mask = DC_DEFAULT_LOG_MASK;
-+
-+ return true;
-+}
-+
-+static void destruct(struct dal_logger *logger)
-+{
-+ if (logger->log_buffer) {
-+ dm_free(logger->log_buffer);
-+ logger->log_buffer = NULL;
-+ }
-+}
-+
-+struct dal_logger *dal_logger_create(struct dc_context *ctx)
-+{
-+ /* malloc struct */
-+ struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger));
-+
-+ if (!logger)
-+ return NULL;
-+ if (!construct(ctx, logger)) {
-+ dm_free(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);
-+ *logger = NULL;
-+
-+ return 0;
-+}
-+
-+/* ------------------------------------------------------------------------ */
-+
-+
-+static bool dal_logger_should_log(
-+ struct dal_logger *logger,
-+ enum dc_log_type log_type)
-+{
-+ if (logger->mask & (1 << log_type))
-+ 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->type) {
-+ case LOG_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'
-+ */
-+ 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;
-+
-+ memmove(logger->log_buffer +
-+ logger->buffer_write_offset,
-+ entry->buf, space_before_wrap);
-+ 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 */
-+ memmove(logger->log_buffer, entry->buf, size);
-+ logger->buffer_write_offset = size;
-+ logger->buffer_read_offset = 0;
-+ }
-+
-+ }
-+}
-+
-+static void log_heading(struct log_entry *entry)
-+{
-+ int j;
-+
-+ for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) {
-+
-+ const struct dc_log_type_info *info = &log_type_info_tbl[j];
-+
-+ if (info->type == entry->type)
-+ dm_logger_append(entry, "[%s]\t", info->name);
-+ }
-+}
-+
-+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 */
-+ 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 dm_logger_write(
-+ struct dal_logger *logger,
-+ enum dc_log_type log_type,
-+ const char *msg,
-+ ...)
-+{
-+ if (logger && dal_logger_should_log(logger, log_type)) {
-+ uint32_t size;
-+ va_list args;
-+ char buffer[LOG_MAX_LINE_SIZE];
-+ struct log_entry entry;
-+
-+ va_start(args, msg);
-+
-+ entry.logger = logger;
-+
-+ entry.buf = buffer;
-+
-+ entry.buf_offset = 0;
-+ entry.max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
-+
-+ entry.type = log_type;
-+
-+ log_heading(&entry);
-+
-+ size = dm_log_to_buffer(
-+ buffer, LOG_MAX_LINE_SIZE, msg, args);
-+
-+ entry.buf_offset += size;
-+
-+ /* --Flush log_entry buffer-- */
-+ /* print to kernel console */
-+ log_to_debug_console(&entry);
-+ /* log internally for dsat */
-+ log_to_internal_buffer(&entry);
-+
-+ va_end(args);
-+ }
-+}
-+
-+/* Same as dm_logger_write, except without open() and close(), which must
-+ * be done separately.
-+ */
-+void dm_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->type)) {
-+
-+ uint32_t size;
-+ va_list args;
-+ char buffer[LOG_MAX_LINE_SIZE];
-+
-+ va_start(args, msg);
-+
-+ size = dm_log_to_buffer(
-+ buffer, LOG_MAX_LINE_SIZE, msg, args);
-+
-+ if (size < LOG_MAX_LINE_SIZE - 1) {
-+ append_entry(entry, buffer, size);
-+ } else {
-+ append_entry(entry, "LOG_ERROR, line too long\n", 27);
-+ }
-+
-+ va_end(args);
-+ }
-+}
-+
-+void dm_logger_open(
-+ struct dal_logger *logger,
-+ struct log_entry *entry, /* out */
-+ enum dc_log_type log_type)
-+{
-+ if (!entry) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ entry->type = log_type;
-+ entry->logger = logger;
-+
-+ entry->buf = dm_alloc(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++;
-+
-+ log_heading(entry);
-+}
-+
-+void dm_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->buf);
-+ entry->buf = NULL;
-+ entry->buf_offset = 0;
-+ entry->max_buf_bytes = 0;
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h
-new file mode 100644
-index 0000000..2f7a5df
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h
-@@ -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
-+ *
-+ */
-+
-+#ifndef __DAL_LOGGER_H__
-+#define __DAL_LOGGER_H__
-+
-+/* Structure for keeping track of offsets, buffer, etc */
-+
-+#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
-+
-+/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes,
-+ * change log line size to 896 to meet the request.
-+ */
-+#define LOG_MAX_LINE_SIZE 896
-+
-+#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 mask; /*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/display/dc/basics/register_logger.c b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c
-new file mode 100644
-index 0000000..b8d57d9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+
-+ 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());
-+
-+ 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/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c
-new file mode 100644
-index 0000000..44447e0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c
-new file mode 100644
-index 0000000..bb72a18
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c
-@@ -0,0 +1,307 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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(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(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)
-+ 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(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(vector);
-+ return NULL;
-+}
-+
-+struct vector *dal_vector_create(
-+ struct dc_context *ctx,
-+ uint32_t capacity,
-+ uint32_t struct_size)
-+{
-+ struct vector *vector = dm_alloc(sizeof(struct vector));
-+
-+ if (vector == NULL)
-+ return NULL;
-+
-+ if (dal_vector_construct(vector, ctx, capacity, struct_size))
-+ return vector;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(vector);
-+ return NULL;
-+}
-+
-+void dal_vector_destruct(
-+ struct vector *vector)
-+{
-+ if (vector->container != NULL)
-+ dm_free(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);
-+ *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)
-+ 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;
-+ }
-+ 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)
-+ memmove(
-+ insert_address + vector->struct_size,
-+ insert_address,
-+ vector->struct_size * (vector->count - position));
-+
-+ 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 */
-+ 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->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;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile
-new file mode 100644
-index 0000000..9ba677f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile
-@@ -0,0 +1,24 @@
-+#
-+# 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_interface.o bios_parser_helper.o command_table.o command_table_helper.o
-+
-+AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_BIOS)
-+
-+###############################################################################
-+# DCE 8x
-+###############################################################################
-+# All DCE8.x are derived from DCE8.0, so 8.0 MUST be defined if ANY of
-+# DCE8.x is compiled.
-+AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o
-+
-+###############################################################################
-+# DCE 11x
-+###############################################################################
-+AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o
-+
-+ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT
-+AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
-new file mode 100644
-index 0000000..ebd2e41
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
-@@ -0,0 +1,4220 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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/gpio_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"
-+#include "bios_parser_helper.h"
-+#include "command_table_helper.h"
-+#include "bios_parser.h"
-+#include "bios_parser_types_internal.h"
-+#include "bios_parser_interface.h"
-+
-+/* TODO remove - only needed for default i2c speed */
-+#include "dc.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 DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
-+
-+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);
-+
-+#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,
-+ enum dce_version dce_version);
-+
-+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 *bios_parser_create(
-+ struct bp_init_data *init,
-+ enum dce_version dce_version)
-+{
-+ struct bios_parser *bp = NULL;
-+
-+ bp = dm_alloc(sizeof(struct bios_parser));
-+ if (!bp)
-+ return NULL;
-+
-+ if (bios_parser_construct(bp, init, dce_version))
-+ return &bp->base;
-+
-+ dm_free(bp);
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-+static void destruct(struct bios_parser *bp)
-+{
-+ if (bp->base.bios_local_image)
-+ dm_free(bp->base.bios_local_image);
-+
-+ if (bp->base.integrated_info)
-+ dm_free(bp->base.integrated_info);
-+}
-+
-+static void 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);
-+ *dcb = NULL;
-+}
-+
-+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_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 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_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_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->base, 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;
-+}
-+
-+/* TODO: temporary commented out to suppress 'defined but not used' warning */
-+#if 0
-+static 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;
-+}
-+#endif
-+
-+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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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];
-+
-+ 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 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_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_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));
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+}
-+
-+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;
-+}
-+
-+/**
-+ * 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;
-+}
-+
-+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->base, 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->base, 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 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;
-+ struct gpio_ddc_hw_info hw_info = {
-+ i2c_info->i2c_hw_assist,
-+ i2c_info->i2c_line };
-+
-+ ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service,
-+ i2c_info->gpio_info.clk_a_register_index,
-+ (1 << i2c_info->gpio_info.clk_a_shift), &hw_info);
-+
-+ if (!ddc)
-+ return result;
-+
-+ /*Using SW engine */
-+ cmd.engine = I2C_COMMAND_ENGINE_SW;
-+ cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
-+
-+ {
-+ 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(
-+ ddc->ctx->i2caux,
-+ ddc,
-+ &cmd);
-+ }
-+
-+ dal_gpio_destroy_ddc(&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;
-+
-+ 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) {
-+
-+ dm_logger_write(bp->base.ctx->logger, LOG_BIOS,
-+ "%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->base.bios_local_image = dm_alloc(bp->base.bios_size);
-+ if (bp->base.bios_local_image == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ /* Failed to alloc bp->base.bios_local_image */
-+ return;
-+ }
-+
-+ memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size);
-+ original_bios = bp->base.bios;
-+ bp->base.bios = bp->base.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 */
-+ memmove(
-+ bp->base.bios_local_image,
-+ original_bios,
-+ bp->base.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) {
-+ 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);
-+}
-+
-+/**
-+ * 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)
-+{
-+ bios_set_scratch_critical_state(dcb, state);
-+}
-+
-+/*
-+ * 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)
-+{
-+ 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)
-+ return BP_RESULT_BADBIOSTABLE;
-+ 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;
-+
-+ return BP_RESULT_OK;
-+}
-+
-+/*
-+ * 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)
-+{
-+ 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)
-+ return BP_RESULT_BADBIOSTABLE;
-+
-+ 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;
-+
-+ return BP_RESULT_OK;
-+}
-+
-+/*
-+ * 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 (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(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(info);
-+
-+ return NULL;
-+}
-+
-+/******************************************************************************/
-+
-+static const struct dc_vbios_funcs vbios_funcs = {
-+ .get_connectors_number = bios_parser_get_connectors_number,
-+
-+ .get_encoder_id = bios_parser_get_encoder_id,
-+
-+ .get_connector_id = bios_parser_get_connector_id,
-+
-+ .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_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,
-+
-+ .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_encoder_cap_info = bios_parser_get_encoder_cap_info,
-+
-+ /* bios scratch register communication */
-+ .is_accelerated_mode = bios_is_accelerated_mode,
-+
-+ .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
-+
-+ .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, /* not used in DAL3. keep for now in case we need to support VGA on Bonaire */
-+
-+ .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, /* still use. should probably retire and program directly */
-+
-+ .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */
-+
-+ .program_display_engine_pll = bios_parser_program_display_engine_pll,
-+
-+ .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
-+
-+ /* SW init and patch */
-+ .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */
-+
-+ .bios_parser_destroy = bios_parser_destroy,
-+};
-+
-+static bool bios_parser_construct(
-+ struct bios_parser *bp,
-+ struct bp_init_data *init,
-+ enum dce_version dce_version)
-+{
-+ uint16_t *rom_header_offset = NULL;
-+ ATOM_ROM_HEADER *rom_header = NULL;
-+ ATOM_OBJECT_HEADER *object_info_tbl;
-+ struct atom_data_revision tbl_rev = {0};
-+
-+ if (!init)
-+ return false;
-+
-+ if (!init->bios)
-+ return false;
-+
-+ bp->base.funcs = &vbios_funcs;
-+ bp->base.bios = init->bios;
-+ bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
-+
-+ bp->base.ctx = init->ctx;
-+ bp->base.bios_local_image = NULL;
-+
-+ 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;
-+
-+ get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
-+ if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
-+ 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;
-+
-+ dal_bios_parser_init_cmd_tbl(bp);
-+ dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
-+
-+ bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
-+
-+ return true;
-+}
-+
-+/******************************************************************************/
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h
-new file mode 100644
-index 0000000..d6f1627
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.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_BIOS_PARSER_H__
-+#define __DAL_BIOS_PARSER_H__
-+
-+struct dc_bios *bios_parser_create(
-+ struct bp_init_data *init,
-+ enum dce_version dce_version);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c
-new file mode 100644
-index 0000000..8e56d2f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c
-@@ -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
-+ *
-+ */
-+
-+#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_types_internal.h"
-+
-+uint8_t *get_image(struct dc_bios *bp,
-+ uint32_t offset,
-+ uint32_t size)
-+{
-+ if (bp->bios && offset + size < bp->bios_size)
-+ return bp->bios + offset;
-+ else
-+ return NULL;
-+}
-+
-+#include "reg_helper.h"
-+
-+#define CTX \
-+ bios->ctx
-+#define REG(reg)\
-+ (bios->regs->reg)
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ ATOM_ ## field_name ## _SHIFT, ATOM_ ## field_name
-+
-+bool bios_is_accelerated_mode(
-+ struct dc_bios *bios)
-+{
-+ uint32_t acc_mode;
-+ REG_GET(BIOS_SCRATCH_6, S6_ACC_MODE, &acc_mode);
-+ return (acc_mode == 1);
-+}
-+
-+
-+void bios_set_scratch_acc_mode_change(
-+ struct dc_bios *bios)
-+{
-+ REG_UPDATE(BIOS_SCRATCH_6, S6_ACC_MODE, 1);
-+}
-+
-+
-+void bios_set_scratch_critical_state(
-+ struct dc_bios *bios,
-+ bool state)
-+{
-+ uint32_t critial_state = state ? 1 : 0;
-+ REG_UPDATE(BIOS_SCRATCH_6, S6_CRITICAL_STATE, critial_state);
-+}
-+
-+
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
-new file mode 100644
-index 0000000..a8fbb82
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
-@@ -0,0 +1,40 @@
-+/*
-+ * 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_BIOS_PARSER_HELPER_H__
-+#define __DAL_BIOS_PARSER_HELPER_H__
-+
-+struct bios_parser;
-+
-+uint8_t *get_image(struct dc_bios *bp, uint32_t offset,
-+ uint32_t size);
-+
-+bool bios_is_accelerated_mode(struct dc_bios *bios);
-+void bios_set_scratch_acc_mode_change(struct dc_bios *bios);
-+void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
-+
-+#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type)))
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c
-new file mode 100644
-index 0000000..42272c3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c
-@@ -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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "include/logger_interface.h"
-+
-+#include "bios_parser_interface.h"
-+#include "bios_parser.h"
-+
-+
-+struct dc_bios *dal_bios_parser_create(
-+ struct bp_init_data *init,
-+ enum dce_version dce_version)
-+{
-+ struct dc_bios *bios = NULL;
-+
-+ bios = bios_parser_create(init, dce_version);
-+
-+ return bios;
-+}
-+
-+void dal_bios_parser_destroy(struct dc_bios **dcb)
-+{
-+ struct dc_bios *bios = *dcb;
-+
-+ bios->funcs->bios_parser_destroy(dcb);
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h
-new file mode 100644
-index 0000000..5918923
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h
-@@ -0,0 +1,72 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_BIOS_H__
-+#define __DAL_BIOS_PARSER_TYPES_BIOS_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 object_info_table object_info_tbl;
-+ uint32_t object_info_tbl_offset;
-+ ATOM_MASTER_DATA_TABLE *master_data_tbl;
-+
-+ const struct bios_parser_helper *bios_helper;
-+
-+ const struct command_table_helper *cmd_helper;
-+ struct cmd_tbl cmd_tbl;
-+
-+ bool remap_device_tags;
-+};
-+
-+/* 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/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
-new file mode 100644
-index 0000000..51f6052
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
-@@ -0,0 +1,2609 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_types_internal.h"
-+
-+#define EXEC_BIOS_CMD_TABLE(command, params)\
-+ (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \
-+ GetIndexIntoMasterTable(COMMAND, command), \
-+ &params) == 0)
-+
-+#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
-+ cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \
-+ GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
-+
-+#define BIOS_CMD_TABLE_PARA_REVISION(command)\
-+ bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \
-+ 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_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_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);
-+}
-+
-+static uint32_t bios_cmd_table_para_revision(void *cgs_device,
-+ uint32_t index)
-+{
-+ uint8_t frev, crev;
-+
-+ if (cgs_atom_get_cmd_table_revs(cgs_device,
-+ index,
-+ &frev, &crev) != 0)
-+ return 0;
-+ return crev;
-+}
-+
-+/*******************************************************************************
-+ ********************************************************************************
-+ **
-+ ** 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);
-+
-+#ifdef LATEST_ATOM_BIOS_SUPPORT
-+static enum bp_result encoder_control_digx_v5(
-+ struct bios_parser *bp,
-+ struct bp_encoder_control *cntl);
-+#endif
-+
-+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 2:
-+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
-+ break;
-+ case 4:
-+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
-+ break;
-+
-+#ifdef LATEST_ATOM_BIOS_SUPPORT
-+ case 5:
-+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
-+ break;
-+#endif
-+
-+ 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 (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 (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
-+ result = BP_RESULT_OK;
-+
-+ return result;
-+}
-+
-+#ifdef LATEST_ATOM_BIOS_SUPPORT
-+static enum bp_result encoder_control_digx_v5(
-+ struct bios_parser *bp,
-+ struct bp_encoder_control *cntl)
-+{
-+ enum bp_result result = BP_RESULT_FAILURE;
-+ ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
-+
-+ params.ucDigId = (uint8_t)(cntl->engine_id);
-+ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
-+
-+ params.ulPixelClock = cntl->pixel_clock / 10;
-+ params.ucDigMode =
-+ (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
-+ cntl->signal,
-+ cntl->enable_dp_audio));
-+ params.ucLaneNum = (uint8_t)(cntl->lanes_number);
-+
-+ switch (cntl->color_depth) {
-+ case COLOR_DEPTH_888:
-+ params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-+ break;
-+ case COLOR_DEPTH_101010:
-+ params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-+ break;
-+ case COLOR_DEPTH_161616:
-+ params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-+ switch (cntl->color_depth) {
-+ case COLOR_DEPTH_101010:
-+ params.ulPixelClock =
-+ (params.ulPixelClock * 30) / 24;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ params.ulPixelClock =
-+ (params.ulPixelClock * 36) / 24;
-+ break;
-+ case COLOR_DEPTH_161616:
-+ params.ulPixelClock =
-+ (params.ulPixelClock * 48) / 24;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
-+ result = BP_RESULT_OK;
-+
-+ return result;
-+}
-+#endif
-+
-+/*******************************************************************************
-+ ********************************************************************************
-+ **
-+ ** 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);
-+
-+ 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);
-+
-+ 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));
-+ }
-+ 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;
-+
-+ 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));
-+ }
-+ 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;
-+
-+ 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
-+ */
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+}
-+
-+/*******************************************************************************
-+ ********************************************************************************
-+ **
-+ ** 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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;
-+
-+ 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_PS_ALLOCATION 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;
-+
-+ 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/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h
-new file mode 100644
-index 0000000..e1cd21b
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h
-@@ -0,0 +1,112 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 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/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c
-new file mode 100644
-index 0000000..40d9a99
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c
-@@ -0,0 +1,288 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "command_table_helper.h"
-+
-+bool dal_bios_parser_init_cmd_tbl_helper(
-+ const struct command_table_helper **h,
-+ enum dce_version dce)
-+{
-+ switch (dce) {
-+ case DCE_VERSION_8_0:
-+ *h = dal_cmd_tbl_helper_dce80_get_table();
-+ return true;
-+
-+ case DCE_VERSION_10_0:
-+ *h = dal_cmd_tbl_helper_dce110_get_table();
-+ return true;
-+
-+ case DCE_VERSION_11_0:
-+ *h = dal_cmd_tbl_helper_dce110_get_table();
-+ return true;
-+
-+ case DCE_VERSION_11_2:
-+ *h = dal_cmd_tbl_helper_dce112_get_table();
-+ return true;
-+
-+ 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:
-+ case SIGNAL_TYPE_VIRTUAL:
-+ 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/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h
-new file mode 100644
-index 0000000..1fab634
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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__
-+
-+#include "dce80/command_table_helper_dce80.h"
-+#include "dce110/command_table_helper_dce110.h"
-+#include "dce112/command_table_helper_dce112.h"
-+
-+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/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
-new file mode 100644
-index 0000000..dff82dd
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
-@@ -0,0 +1,364 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "../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/display/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h
-new file mode 100644
-index 0000000..eb60c2e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
-new file mode 100644
-index 0000000..8b72aa5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
-@@ -0,0 +1,418 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "../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_V6_DP;
-+
-+ switch (s) {
-+ case SIGNAL_TYPE_DISPLAY_PORT:
-+ case SIGNAL_TYPE_EDP:
-+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP;
-+ break;
-+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
-+ case SIGNAL_TYPE_DVI_DUAL_LINK:
-+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI;
-+ break;
-+ case SIGNAL_TYPE_HDMI_TYPE_A:
-+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI;
-+ break;
-+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
-+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST;
-+ break;
-+ default:
-+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_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_V6_HPD1_SEL;
-+ break;
-+ case HPD_SOURCEID2:
-+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL;
-+ break;
-+ case HPD_SOURCEID3:
-+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL;
-+ break;
-+ case HPD_SOURCEID4:
-+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL;
-+ break;
-+ case HPD_SOURCEID5:
-+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL;
-+ break;
-+ case HPD_SOURCEID6:
-+ atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL;
-+ break;
-+ case HPD_SOURCEID_UNKNOWN:
-+ default:
-+ atom_hpd_sel = 0;
-+ break;
-+ }
-+ return atom_hpd_sel;
-+}
-+
-+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_V6__DIGA_SEL;
-+ break;
-+ case ENGINE_ID_DIGB:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL;
-+ break;
-+ case ENGINE_ID_DIGC:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL;
-+ break;
-+ case ENGINE_ID_DIGD:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL;
-+ break;
-+ case ENGINE_ID_DIGE:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL;
-+ break;
-+ case ENGINE_ID_DIGF:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL;
-+ break;
-+ case ENGINE_ID_DIGG:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__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_V6__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_COMBO_PHY_PLL0:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL0;
-+ break;
-+ case CLOCK_SOURCE_COMBO_PHY_PLL1:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL1;
-+ break;
-+ case CLOCK_SOURCE_COMBO_PHY_PLL2:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL2;
-+ break;
-+ case CLOCK_SOURCE_COMBO_PHY_PLL3:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL3;
-+ break;
-+ case CLOCK_SOURCE_COMBO_PHY_PLL4:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL4;
-+ break;
-+ case CLOCK_SOURCE_COMBO_PHY_PLL5:
-+ *atom_pll_id = ATOM_COMBOPHY_PLL5;
-+ break;
-+ case CLOCK_SOURCE_COMBO_DISPLAY_PLL0:
-+ *atom_pll_id = ATOM_PPLL0;
-+ break;
-+ case CLOCK_SOURCE_ID_DFS:
-+ *atom_pll_id = ATOM_GCK_DFS;
-+ break;
-+ case CLOCK_SOURCE_ID_VCE:
-+ *atom_pll_id = ATOM_DP_DTO;
-+ break;
-+ case CLOCK_SOURCE_ID_DP_DTO:
-+ *atom_pll_id = ATOM_DP_DTO;
-+ 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_STREAM_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;
-+}
-+
-+static bool dc_clock_type_to_atom(
-+ enum bp_dce_clock_type id,
-+ uint32_t *atom_clock_type)
-+{
-+ bool retCode = true;
-+
-+ if (atom_clock_type != NULL) {
-+ switch (id) {
-+ case DCECLOCK_TYPE_DISPLAY_CLOCK:
-+ *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK;
-+ break;
-+
-+ case DCECLOCK_TYPE_DPREFCLK:
-+ *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK;
-+ break;
-+
-+ default:
-+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */
-+ break;
-+ }
-+ }
-+
-+ return retCode;
-+}
-+
-+static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id)
-+{
-+ uint8_t atomColorDepth = 0;
-+
-+ switch (id) {
-+ case TRANSMITTER_COLOR_DEPTH_24:
-+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS;
-+ break;
-+ case TRANSMITTER_COLOR_DEPTH_30:
-+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4;
-+ break;
-+ case TRANSMITTER_COLOR_DEPTH_36:
-+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2;
-+ break;
-+ case TRANSMITTER_COLOR_DEPTH_48:
-+ atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1;
-+ break;
-+ default:
-+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */
-+ break;
-+ }
-+
-+ return atomColorDepth;
-+}
-+
-+/* 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,
-+ .dc_clock_type_to_atom = dc_clock_type_to_atom,
-+ .transmitter_color_depth_to_atom = transmitter_color_depth_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_dce112_get_table()
-+{
-+ return &command_table_helper_funcs;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h
-new file mode 100644
-index 0000000..dc36609
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.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_DCE112_H__
-+#define __DAL_COMMAND_TABLE_HELPER_DCE112_H__
-+
-+struct command_table_helper;
-+
-+/* Initialize command table helper functions */
-+const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void);
-+
-+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c
-new file mode 100644
-index 0000000..295e16e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c
-@@ -0,0 +1,354 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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/grph_object_id.h"
-+#include "include/grph_object_defs.h"
-+#include "include/bios_parser_types.h"
-+
-+#include "../command_table_helper.h"
-+
-+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 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 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:
-+ BREAK_TO_DEBUGGER(); /* check when this will happen! */
-+ *atom_pll_id = ATOM_PPLL_INVALID;
-+ result = false;
-+ break;
-+ default:
-+ result = false;
-+ break;
-+ }
-+
-+ return result;
-+}
-+
-+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 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 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;
-+ default:
-+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
-+ break;
-+ }
-+
-+ return atom_dig_encoder_sel;
-+}
-+
-+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 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:
-+ BREAK_TO_DEBUGGER(); /* Unhandle action in driver! */
-+ break;
-+ }
-+
-+ return atom_pipe_action;
-+}
-+
-+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 =
-+ dal_cmd_table_helper_assign_control_parameter,
-+ .clock_source_id_to_ref_clk_src =
-+ dal_cmd_table_helper_clock_source_id_to_ref_clk_src,
-+ .transmitter_bp_to_atom = dal_cmd_table_helper_transmitter_bp_to_atom,
-+ .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,
-+};
-+
-+const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table()
-+{
-+ return &command_table_helper_funcs;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h
-new file mode 100644
-index 0000000..e675c35
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.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_COMMAND_TABLE_HELPER_DCE80_H__
-+#define __DAL_COMMAND_TABLE_HELPER_DCE80_H__
-+
-+struct command_table_helper;
-+
-+const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
-new file mode 100644
-index 0000000..4001933
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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 gamma_calcs.o
-+
-+AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS)
-diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c
-new file mode 100644
-index 0000000..0b2bb39
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c
-@@ -0,0 +1,3108 @@
-+/*
-+ * 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"
-+#include "dc.h"
-+#include "core_types.h"
-+
-+/*******************************************************************************
-+ * Private Functions
-+ ******************************************************************************/
-+
-+static void calculate_bandwidth(
-+ const struct bw_calcs_dceip *dceip,
-+ const struct bw_calcs_vbios *vbios,
-+ struct bw_calcs_data *data)
-+
-+{
-+ const int32_t pixels_per_chunk = 512;
-+ const int32_t high = 2;
-+ const int32_t mid = 1;
-+ const int32_t low = 0;
-+ const uint32_t s_low = 0;
-+ const uint32_t s_mid1 = 1;
-+ const uint32_t s_mid2 = 2;
-+ const uint32_t s_mid3 = 3;
-+ const uint32_t s_mid4 = 4;
-+ const uint32_t s_mid5 = 5;
-+ const uint32_t s_mid6 = 6;
-+ const uint32_t s_high = 7;
-+ const uint32_t bus_efficiency = 1;
-+ const uint32_t dmif_chunk_buff_margin = 1;
-+
-+ uint32_t max_chunks_fbc_mode;
-+ int32_t num_cursor_lines;
-+
-+ int32_t i, j, k;
-+ struct bw_fixed yclk[3];
-+ struct bw_fixed sclk[8];
-+ bool d0_underlay_enable;
-+ bool d1_underlay_enable;
-+ bool fbc_enabled;
-+ bool lpt_enabled;
-+ 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 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;
-+ enum bw_defines nbp_state_change_enable_blank;
-+ /*initialize variables*/
-+ int32_t number_of_displays_enabled = 0;
-+ int32_t number_of_displays_enabled_with_margin = 0;
-+ int32_t number_of_aligned_displays_with_no_margin = 0;
-+
-+ yclk[low] = vbios->low_yclk;
-+ yclk[mid] = vbios->mid_yclk;
-+ yclk[high] = vbios->high_yclk;
-+ sclk[s_low] = vbios->low_sclk;
-+ sclk[s_mid1] = vbios->mid1_sclk;
-+ sclk[s_mid2] = vbios->mid2_sclk;
-+ sclk[s_mid3] = vbios->mid3_sclk;
-+ sclk[s_mid4] = vbios->mid4_sclk;
-+ sclk[s_mid5] = vbios->mid5_sclk;
-+ sclk[s_mid6] = vbios->mid6_sclk;
-+ sclk[s_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 (data->d0_underlay_mode == bw_def_none) { d0_underlay_enable = 0; }
-+ else {
-+ d0_underlay_enable = 1;
-+ }
-+ if (data->d1_underlay_mode == bw_def_none) { d1_underlay_enable = 0; }
-+ else {
-+ d1_underlay_enable = 1;
-+ }
-+ data->number_of_underlay_surfaces = d0_underlay_enable + d1_underlay_enable;
-+ switch (data->underlay_surface_type) {
-+ case bw_def_420:
-+ surface_type[0] = bw_def_underlay420_luma;
-+ surface_type[2] = bw_def_underlay420_luma;
-+ data->bytes_per_pixel[0] = 1;
-+ data->bytes_per_pixel[2] = 1;
-+ surface_type[1] = bw_def_underlay420_chroma;
-+ surface_type[3] = bw_def_underlay420_chroma;
-+ data->bytes_per_pixel[1] = 2;
-+ data->bytes_per_pixel[3] = 2;
-+ data->lb_size_per_component[0] = dceip->underlay420_luma_lb_size_per_component;
-+ data->lb_size_per_component[1] = dceip->underlay420_chroma_lb_size_per_component;
-+ data->lb_size_per_component[2] = dceip->underlay420_luma_lb_size_per_component;
-+ data->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;
-+ data->bytes_per_pixel[0] = 2;
-+ data->bytes_per_pixel[2] = 2;
-+ data->lb_size_per_component[0] = dceip->underlay422_lb_size_per_component;
-+ data->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;
-+ data->bytes_per_pixel[0] = 4;
-+ data->bytes_per_pixel[2] = 4;
-+ data->lb_size_per_component[0] = dceip->lb_size_per_component444;
-+ data->lb_size_per_component[2] = dceip->lb_size_per_component444;
-+ break;
-+ }
-+ if (d0_underlay_enable) {
-+ switch (data->underlay_surface_type) {
-+ case bw_def_420:
-+ data->enable[0] = 1;
-+ data->enable[1] = 1;
-+ break;
-+ default:
-+ data->enable[0] = 1;
-+ data->enable[1] = 0;
-+ break;
-+ }
-+ }
-+ else {
-+ data->enable[0] = 0;
-+ data->enable[1] = 0;
-+ }
-+ if (d1_underlay_enable) {
-+ switch (data->underlay_surface_type) {
-+ case bw_def_420:
-+ data->enable[2] = 1;
-+ data->enable[3] = 1;
-+ break;
-+ default:
-+ data->enable[2] = 1;
-+ data->enable[3] = 0;
-+ break;
-+ }
-+ }
-+ else {
-+ data->enable[2] = 0;
-+ data->enable[3] = 0;
-+ }
-+ data->use_alpha[0] = 0;
-+ data->use_alpha[1] = 0;
-+ data->use_alpha[2] = 0;
-+ data->use_alpha[3] = 0;
-+ data->scatter_gather_enable_for_pipe[0] = vbios->scatter_gather_enable;
-+ data->scatter_gather_enable_for_pipe[1] = vbios->scatter_gather_enable;
-+ data->scatter_gather_enable_for_pipe[2] = vbios->scatter_gather_enable;
-+ data->scatter_gather_enable_for_pipe[3] = vbios->scatter_gather_enable;
-+ /*underlay0 same and graphics display pipe0*/
-+ data->interlace_mode[0] = data->interlace_mode[4];
-+ data->interlace_mode[1] = data->interlace_mode[4];
-+ /*underlay1 same and graphics display pipe1*/
-+ data->interlace_mode[2] = data->interlace_mode[5];
-+ data->interlace_mode[3] = data->interlace_mode[5];
-+ /*underlay0 same and graphics display pipe0*/
-+ data->h_total[0] = data->h_total[4];
-+ data->v_total[0] = data->v_total[4];
-+ data->h_total[1] = data->h_total[4];
-+ data->v_total[1] = data->v_total[4];
-+ /*underlay1 same and graphics display pipe1*/
-+ data->h_total[2] = data->h_total[5];
-+ data->v_total[2] = data->v_total[5];
-+ data->h_total[3] = data->h_total[5];
-+ data->v_total[3] = data->v_total[5];
-+ /*underlay0 same and graphics display pipe0*/
-+ data->pixel_rate[0] = data->pixel_rate[4];
-+ data->pixel_rate[1] = data->pixel_rate[4];
-+ /*underlay1 same and graphics display pipe1*/
-+ data->pixel_rate[2] = data->pixel_rate[5];
-+ data->pixel_rate[3] = data->pixel_rate[5];
-+ if ((data->underlay_tiling_mode == bw_def_array_linear_general || data->underlay_tiling_mode == bw_def_array_linear_aligned)) {
-+ 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;
-+ }
-+ data->lb_bpc[0] = data->underlay_lb_bpc;
-+ data->lb_bpc[1] = data->underlay_lb_bpc;
-+ data->lb_bpc[2] = data->underlay_lb_bpc;
-+ data->lb_bpc[3] = data->underlay_lb_bpc;
-+ data->compression_rate[0] = bw_int_to_fixed(1);
-+ data->compression_rate[1] = bw_int_to_fixed(1);
-+ data->compression_rate[2] = bw_int_to_fixed(1);
-+ data->compression_rate[3] = bw_int_to_fixed(1);
-+ data->access_one_channel_only[0] = 0;
-+ data->access_one_channel_only[1] = 0;
-+ data->access_one_channel_only[2] = 0;
-+ data->access_one_channel_only[3] = 0;
-+ data->cursor_width_pixels[0] = bw_int_to_fixed(0);
-+ data->cursor_width_pixels[1] = bw_int_to_fixed(0);
-+ data->cursor_width_pixels[2] = bw_int_to_fixed(0);
-+ data->cursor_width_pixels[3] = bw_int_to_fixed(0);
-+ /* graphics surface parameters from spreadsheet*/
-+ fbc_enabled = 0;
-+ lpt_enabled = 0;
-+ for (i = 4; i <= maximum_number_of_surfaces - 3; i++) {
-+ if (i < data->number_of_displays + 4) {
-+ if (i == 4 && data->d0_underlay_mode == bw_def_underlay_only) {
-+ data->enable[i] = 0;
-+ data->use_alpha[i] = 0;
-+ }
-+ else if (i == 4 && data->d0_underlay_mode == bw_def_blend) {
-+ data->enable[i] = 1;
-+ data->use_alpha[i] = 1;
-+ }
-+ else if (i == 4) {
-+ data->enable[i] = 1;
-+ data->use_alpha[i] = 0;
-+ }
-+ else if (i == 5 && data->d1_underlay_mode == bw_def_underlay_only) {
-+ data->enable[i] = 0;
-+ data->use_alpha[i] = 0;
-+ }
-+ else if (i == 5 && data->d1_underlay_mode == bw_def_blend) {
-+ data->enable[i] = 1;
-+ data->use_alpha[i] = 1;
-+ }
-+ else {
-+ data->enable[i] = 1;
-+ data->use_alpha[i] = 0;
-+ }
-+ }
-+ else {
-+ data->enable[i] = 0;
-+ data->use_alpha[i] = 0;
-+ }
-+ data->scatter_gather_enable_for_pipe[i] = vbios->scatter_gather_enable;
-+ surface_type[i] = bw_def_graphics;
-+ data->lb_size_per_component[i] = dceip->lb_size_per_component444;
-+ if (data->graphics_tiling_mode == bw_def_array_linear_general || data->graphics_tiling_mode == bw_def_array_linear_aligned) {
-+ tiling_mode[i] = bw_def_linear;
-+ }
-+ else {
-+ tiling_mode[i] = bw_def_tiled;
-+ }
-+ data->lb_bpc[i] = data->graphics_lb_bpc;
-+ if ((data->fbc_en[i] == 1 && (dceip->argb_compression_support || data->d0_underlay_mode != bw_def_blended))) {
-+ data->compression_rate[i] = bw_int_to_fixed(vbios->average_compression_rate);
-+ data->access_one_channel_only[i] = data->lpt_en[i];
-+ }
-+ else {
-+ data->compression_rate[i] = bw_int_to_fixed(1);
-+ data->access_one_channel_only[i] = 0;
-+ }
-+ if (data->fbc_en[i] == 1) {
-+ fbc_enabled = 1;
-+ if (data->lpt_en[i] == 1) {
-+ lpt_enabled = 1;
-+ }
-+ }
-+ data->cursor_width_pixels[i] = bw_int_to_fixed(vbios->cursor_width);
-+ }
-+ /* display_write_back420*/
-+ data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = 0;
-+ data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = 0;
-+ if (data->d1_display_write_back_dwb_enable == 1) {
-+ data->enable[maximum_number_of_surfaces - 2] = 1;
-+ data->enable[maximum_number_of_surfaces - 1] = 1;
-+ }
-+ else {
-+ data->enable[maximum_number_of_surfaces - 2] = 0;
-+ data->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;
-+ data->lb_size_per_component[maximum_number_of_surfaces - 2] = dceip->underlay420_luma_lb_size_per_component;
-+ data->lb_size_per_component[maximum_number_of_surfaces - 1] = dceip->underlay420_chroma_lb_size_per_component;
-+ data->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1;
-+ data->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2;
-+ data->interlace_mode[maximum_number_of_surfaces - 2] = data->interlace_mode[5];
-+ data->interlace_mode[maximum_number_of_surfaces - 1] = data->interlace_mode[5];
-+ data->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
-+ data->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
-+ data->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
-+ data->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
-+ data->rotation_angle[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0);
-+ data->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;
-+ data->lb_bpc[maximum_number_of_surfaces - 2] = 8;
-+ data->lb_bpc[maximum_number_of_surfaces - 1] = 8;
-+ data->compression_rate[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
-+ data->compression_rate[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
-+ data->access_one_channel_only[maximum_number_of_surfaces - 2] = 0;
-+ data->access_one_channel_only[maximum_number_of_surfaces - 1] = 0;
-+ /*assume display pipe1 has dwb enabled*/
-+ data->h_total[maximum_number_of_surfaces - 2] = data->h_total[5];
-+ data->h_total[maximum_number_of_surfaces - 1] = data->h_total[5];
-+ data->v_total[maximum_number_of_surfaces - 2] = data->v_total[5];
-+ data->v_total[maximum_number_of_surfaces - 1] = data->v_total[5];
-+ data->pixel_rate[maximum_number_of_surfaces - 2] = data->pixel_rate[5];
-+ data->pixel_rate[maximum_number_of_surfaces - 1] = data->pixel_rate[5];
-+ data->src_width[maximum_number_of_surfaces - 2] = data->src_width[5];
-+ data->src_width[maximum_number_of_surfaces - 1] = data->src_width[5];
-+ data->src_height[maximum_number_of_surfaces - 2] = data->src_height[5];
-+ data->src_height[maximum_number_of_surfaces - 1] = data->src_height[5];
-+ data->pitch_in_pixels[maximum_number_of_surfaces - 2] = data->src_width[5];
-+ data->pitch_in_pixels[maximum_number_of_surfaces - 1] = data->src_width[5];
-+ data->h_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
-+ data->h_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
-+ data->v_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
-+ data->v_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
-+ data->stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono;
-+ data->stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono;
-+ data->cursor_width_pixels[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0);
-+ data->cursor_width_pixels[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0);
-+ data->use_alpha[maximum_number_of_surfaces - 2] = 0;
-+ data->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 a graphic or 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 (data->enable[i]) {
-+ if (bw_equ(data->h_scale_ratio[i], bw_int_to_fixed(1)) && bw_equ(data->v_scale_ratio[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics && data->stereo_mode[i] == bw_def_mono && data->interlace_mode[i] == 0) {
-+ data->h_taps[i] = bw_int_to_fixed(1);
-+ data->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) {
-+ data->pitch_in_pixels_after_surface_type[i] = bw_div(data->pitch_in_pixels[i], bw_int_to_fixed(2));
-+ data->src_width_after_surface_type = bw_div(data->src_width[i], bw_int_to_fixed(2));
-+ data->src_height_after_surface_type = bw_div(data->src_height[i], bw_int_to_fixed(2));
-+ data->hsr_after_surface_type = bw_div(data->h_scale_ratio[i], bw_int_to_fixed(2));
-+ data->vsr_after_surface_type = bw_div(data->v_scale_ratio[i], bw_int_to_fixed(2));
-+ }
-+ else {
-+ data->pitch_in_pixels_after_surface_type[i] = data->pitch_in_pixels[i];
-+ data->src_width_after_surface_type = data->src_width[i];
-+ data->src_height_after_surface_type = data->src_height[i];
-+ data->hsr_after_surface_type = data->h_scale_ratio[i];
-+ data->vsr_after_surface_type = data->v_scale_ratio[i];
-+ }
-+ if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->src_width_after_rotation = data->src_height_after_surface_type;
-+ data->src_height_after_rotation = data->src_width_after_surface_type;
-+ data->hsr_after_rotation = data->vsr_after_surface_type;
-+ data->vsr_after_rotation = data->hsr_after_surface_type;
-+ }
-+ else {
-+ data->src_width_after_rotation = data->src_width_after_surface_type;
-+ data->src_height_after_rotation = data->src_height_after_surface_type;
-+ data->hsr_after_rotation = data->hsr_after_surface_type;
-+ data->vsr_after_rotation = data->vsr_after_surface_type;
-+ }
-+ switch (data->stereo_mode[i]) {
-+ case bw_def_top_bottom:
-+ data->source_width_pixels[i] = data->src_width_after_rotation;
-+ data->source_height_pixels = bw_mul(bw_int_to_fixed(2), data->src_height_after_rotation);
-+ data->hsr_after_stereo = data->hsr_after_rotation;
-+ data->vsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->vsr_after_rotation);
-+ break;
-+ case bw_def_side_by_side:
-+ data->source_width_pixels[i] = bw_mul(bw_int_to_fixed(2), data->src_width_after_rotation);
-+ data->source_height_pixels = data->src_height_after_rotation;
-+ data->hsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->hsr_after_rotation);
-+ data->vsr_after_stereo = data->vsr_after_rotation;
-+ break;
-+ default:
-+ data->source_width_pixels[i] = data->src_width_after_rotation;
-+ data->source_height_pixels = data->src_height_after_rotation;
-+ data->hsr_after_stereo = data->hsr_after_rotation;
-+ data->vsr_after_stereo = data->vsr_after_rotation;
-+ break;
-+ }
-+ data->hsr[i] = data->hsr_after_stereo;
-+ if (data->interlace_mode[i]) {
-+ data->vsr[i] = bw_mul(data->vsr_after_stereo, bw_int_to_fixed(2));
-+ }
-+ else {
-+ data->vsr[i] = data->vsr_after_stereo;
-+ }
-+ if (data->panning_and_bezel_adjustment != bw_def_none) {
-+ data->source_width_rounded_up_to_chunks[i] = bw_add(bw_floor2(bw_sub(data->source_width_pixels[i], bw_int_to_fixed(1)), bw_int_to_fixed(128)), bw_int_to_fixed(256));
-+ }
-+ else {
-+ data->source_width_rounded_up_to_chunks[i] = bw_ceil2(data->source_width_pixels[i], bw_int_to_fixed(128));
-+ }
-+ data->source_height_rounded_up_to_chunks[i] = data->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 >= data->number_of_displays && dceip->number_of_underlay_pipes >= data->number_of_underlay_surfaces && !(dceip->display_write_back_supported == 0 && 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 (data->enable[i]) {
-+ if (bw_neq(data->hsr[i], bw_int_to_fixed(1))) {
-+ if (bw_mtn(data->hsr[i], bw_int_to_fixed(4))) {
-+ hsr_check = bw_def_hsr_mtn_4;
-+ }
-+ else {
-+ if (bw_mtn(data->hsr[i], data->h_taps[i])) {
-+ hsr_check = bw_def_hsr_mtn_h_taps;
-+ }
-+ else {
-+ if (dceip->pre_downscaler_enabled == 1 && bw_mtn(data->hsr[i], bw_int_to_fixed(1)) && bw_leq(data->hsr[i], bw_ceil2(bw_div(data->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 (data->enable[i]) {
-+ if (bw_neq(data->vsr[i], bw_int_to_fixed(1))) {
-+ if (bw_mtn(data->vsr[i], bw_int_to_fixed(4))) {
-+ vsr_check = bw_def_vsr_mtn_4;
-+ }
-+ else {
-+ if (bw_mtn(data->vsr[i], data->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 (data->enable[i]) {
-+ if ((dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1)))) {
-+ data->source_width_in_lb = bw_div(data->source_width_pixels[i], data->hsr[i]);
-+ }
-+ else {
-+ data->source_width_in_lb = data->source_width_pixels[i];
-+ }
-+ switch (data->lb_bpc[i]) {
-+ case 8:
-+ data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48));
-+ break;
-+ case 10:
-+ data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48));
-+ break;
-+ default:
-+ data->lb_line_pitch = bw_ceil2(bw_mul(bw_int_to_fixed(data->lb_bpc[i]), data->source_width_in_lb), bw_int_to_fixed(48));
-+ break;
-+ }
-+ data->lb_partitions[i] = bw_floor2(bw_div(data->lb_size_per_component[i], data->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)) {
-+ data->lb_partitions_max[i] = bw_int_to_fixed(10);
-+ }
-+ else {
-+ data->lb_partitions_max[i] = bw_int_to_fixed(7);
-+ }
-+ data->lb_partitions[i] = bw_min2(data->lb_partitions_max[i], data->lb_partitions[i]);
-+ if (bw_mtn(bw_add(data->v_taps[i], bw_int_to_fixed(1)), data->lb_partitions[i])) {
-+ lb_size_check = bw_def_notok;
-+ }
-+ }
-+ }
-+ fbc_check = bw_def_ok;
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i] && data->fbc_en[i] == 1 && (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)) || data->stereo_mode[i] != bw_def_mono || data->bytes_per_pixel[i] != 4)) {
-+ fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo;
-+ }
-+ }
-+ rotation_check = bw_def_ok;
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && (tiling_mode[i] == bw_def_linear || data->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;
-+ }
-+ /*number of memory channels for write-back client*/
-+ data->number_of_dram_wrchannels = vbios->number_of_dram_channels;
-+ data->number_of_dram_channels = vbios->number_of_dram_channels;
-+ /*modify number of memory channels if lpt mode is enabled*/
-+ /* low power tiling mode register*/
-+ /* 0 = use channel 0*/
-+ /* 1 = use channel 0 and 1*/
-+ /* 2 = use channel 0,1,2,3*/
-+ if ((fbc_enabled == 1 && lpt_enabled == 1)) {
-+ data->dram_efficiency = bw_int_to_fixed(1);
-+ if (dceip->low_power_tiling_mode == 0) {
-+ data->number_of_dram_channels = 1;
-+ }
-+ else if (dceip->low_power_tiling_mode == 1) {
-+ data->number_of_dram_channels = 2;
-+ }
-+ else if (dceip->low_power_tiling_mode == 2) {
-+ data->number_of_dram_channels = 4;
-+ }
-+ else {
-+ data->number_of_dram_channels = 1;
-+ }
-+ }
-+ else {
-+ data->dram_efficiency = bw_frc_to_fixed(8, 10);
-+ }
-+ /*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 (data->enable[i]) {
-+ if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)))) {
-+ if ((i < 4)) {
-+ /*underlay portrait tiling mode is not supported*/
-+ data->orthogonal_rotation[i] = 1;
-+ }
-+ else {
-+ /*graphics portrait tiling mode*/
-+ if ((data->graphics_micro_tile_mode == bw_def_rotated_micro_tiling)) {
-+ data->orthogonal_rotation[i] = 0;
-+ }
-+ else {
-+ data->orthogonal_rotation[i] = 1;
-+ }
-+ }
-+ }
-+ else {
-+ if ((i < 4)) {
-+ /*underlay landscape tiling mode is only supported*/
-+ if ((data->underlay_micro_tile_mode == bw_def_display_micro_tiling)) {
-+ data->orthogonal_rotation[i] = 0;
-+ }
-+ else {
-+ data->orthogonal_rotation[i] = 1;
-+ }
-+ }
-+ else {
-+ /*graphics landscape tiling mode*/
-+ if ((data->graphics_micro_tile_mode == bw_def_display_micro_tiling)) {
-+ data->orthogonal_rotation[i] = 0;
-+ }
-+ else {
-+ data->orthogonal_rotation[i] = 1;
-+ }
-+ }
-+ }
-+ if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) {
-+ data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_height_efficient_for_tiling;
-+ }
-+ else {
-+ data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_width_efficient_for_tiling;
-+ }
-+ if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) {
-+ data->bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(1);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(1);
-+ }
-+ else if (tiling_mode[i] == bw_def_linear) {
-+ data->bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ }
-+ else {
-+ if (surface_type[i] == bw_def_graphics || (bw_mtn(data->source_width_rounded_up_to_chunks[i], bw_ceil2(data->underlay_maximum_source_efficient_for_tiling, bw_int_to_fixed(256))))) {
-+ switch (data->bytes_per_pixel[i]) {
-+ case 8:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ if (data->orthogonal_rotation[i]) {
-+ data->bytes_per_request[i] = bw_int_to_fixed(32);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(32);
-+ }
-+ else {
-+ data->bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(64);
-+ }
-+ break;
-+ case 4:
-+ if (data->orthogonal_rotation[i]) {
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ data->bytes_per_request[i] = bw_int_to_fixed(32);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(16);
-+ }
-+ else {
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ data->bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(64);
-+ }
-+ break;
-+ case 2:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ data->bytes_per_request[i] = bw_int_to_fixed(32);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(32);
-+ break;
-+ default:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ data->bytes_per_request[i] = bw_int_to_fixed(32);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(16);
-+ break;
-+ }
-+ }
-+ else {
-+ data->bytes_per_request[i] = bw_int_to_fixed(64);
-+ data->useful_bytes_per_request[i] = bw_int_to_fixed(64);
-+ if (data->orthogonal_rotation[i]) {
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(4);
-+ }
-+ else {
-+ switch (data->bytes_per_pixel[i]) {
-+ case 4:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(2);
-+ break;
-+ case 2:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(4);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(4);
-+ break;
-+ default:
-+ data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8);
-+ data->latency_hiding_lines[i] = bw_int_to_fixed(4);
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ /*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.*/
-+ /**/
-+ /*if the dmif data buffer size holds more than vta_ps worth of source lines, then only vsr is used.*/
-+ /*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.*/
-+ /*furthermore, 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.*/
-+ /**/
-+ /*multi-line buffer prefetching is only done in the graphics pipe when the scaler is disabled or when upscaling and the vsr <= 0.8.'*/
-+ /**/
-+ /*the horizontal blank and chunk granularity factor is indirectly used indicate the interval of time required to transfer the source pixels.*/
-+ /*the denominator of this term represents the total number of destination output pixels required for the input source pixels.*/
-+ /*it applies when the lines in per line out is not 2 or 4. it does not apply when there is a line buffer between the scl and blnd.*/
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->v_filter_init[i] = bw_floor2(bw_div((bw_add(bw_add(bw_add(bw_int_to_fixed(1), data->v_taps[i]), data->vsr[i]), bw_mul(bw_mul(bw_int_to_fixed(data->interlace_mode[i]), bw_frc_to_fixed(5, 10)), data->vsr[i]))), bw_int_to_fixed(2)), bw_int_to_fixed(1));
-+ if (data->panning_and_bezel_adjustment == bw_def_any_lines) {
-+ data->v_filter_init[i] = bw_add(data->v_filter_init[i], bw_int_to_fixed(1));
-+ }
-+ if (data->stereo_mode[i] == bw_def_top_bottom) {
-+ v_filter_init_mode[i] = bw_def_manual;
-+ data->v_filter_init[i] = bw_min2(data->v_filter_init[i], bw_int_to_fixed(4));
-+ }
-+ else {
-+ v_filter_init_mode[i] = bw_def_auto;
-+ }
-+ if (data->stereo_mode[i] == bw_def_top_bottom) {
-+ data->num_lines_at_frame_start = bw_int_to_fixed(1);
-+ }
-+ else {
-+ data->num_lines_at_frame_start = bw_int_to_fixed(3);
-+ }
-+ if ((bw_mtn(data->vsr[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics) || data->panning_and_bezel_adjustment == bw_def_any_lines) {
-+ data->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(data->lb_partitions[i], bw_add(data->v_taps[i], bw_ceil2(data->vsr[i], bw_int_to_fixed(1))))))) {
-+ data->line_buffer_prefetch[i] = 1;
-+ }
-+ else {
-+ data->line_buffer_prefetch[i] = 0;
-+ }
-+ data->lb_lines_in_per_line_out_in_beginning_of_frame[i] = bw_div(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->num_lines_at_frame_start);
-+ if (data->line_buffer_prefetch[i] == 1) {
-+ data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_max2(bw_int_to_fixed(1), data->vsr[i]);
-+ }
-+ else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) {
-+ data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1);
-+ }
-+ else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) {
-+ data->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(data->vsr[i], bw_int_to_fixed(6 / 4))) {
-+ data->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(data->vsr[i], bw_int_to_fixed(2))) {
-+ data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(2);
-+ }
-+ else if (bw_leq(data->vsr[i], bw_int_to_fixed(3))) {
-+ data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(3);
-+ }
-+ else {
-+ data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(4);
-+ }
-+ if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) {
-+ data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1);
-+ }
-+ else {
-+ data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2))));
-+ }
-+ data->request_bandwidth[i] = bw_div(bw_mul(bw_div(bw_mul(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], data->lb_lines_in_per_line_out_in_middle_of_frame[i]), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), bw_int_to_fixed(data->bytes_per_pixel[i])), data->useful_bytes_per_request[i]), data->lines_interleaved_in_mem_access[i]), data->latency_hiding_lines[i]);
-+ data->display_bandwidth[i] = bw_mul(data->request_bandwidth[i], data->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 dmif data buffer size for the graphics surface is increased by concatenating the adjacent buffers.*/
-+ /**/
-+ /*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 (data->enable[i]) {
-+ if ((dceip->dmif_pipe_en_fbc_chunk_tracker + 3 == i && fbc_enabled == 0 && tiling_mode[i] != bw_def_linear)) {
-+ data->max_chunks_non_fbc_mode[i] = 128 - dmif_chunk_buff_margin;
-+ }
-+ else {
-+ data->max_chunks_non_fbc_mode[i] = 16 - dmif_chunk_buff_margin;
-+ }
-+ }
-+ if (data->fbc_en[i] == 1) {
-+ max_chunks_fbc_mode = 128 - dmif_chunk_buff_margin;
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ switch (surface_type[i]) {
-+ case bw_def_display_write_back420_luma:
-+ data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_luma_mcifwr_buffer_size);
-+ break;
-+ case bw_def_display_write_back420_chroma:
-+ data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_chroma_mcifwr_buffer_size);
-+ break;
-+ case bw_def_underlay420_luma:
-+ data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size);
-+ break;
-+ case bw_def_underlay420_chroma:
-+ data->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 (data->orthogonal_rotation[i] == 0) {
-+ data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size);
-+ }
-+ else {
-+ data->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 (data->fbc_en[i] == 1) {
-+ /*data_buffer_size(i) = max_dmif_buffer_allocated * graphics_dmif_size*/
-+ if (data->number_of_displays == 1) {
-+ data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size)));
-+ }
-+ else {
-+ data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), 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*/
-+ if (data->number_of_displays == 1) {
-+ data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size)));
-+ }
-+ else {
-+ data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[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) {
-+ data->memory_chunk_size_in_bytes[i] = bw_int_to_fixed(1024);
-+ data->pipe_chunk_size_in_bytes[i] = bw_int_to_fixed(1024);
-+ }
-+ else {
-+ data->memory_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), data->lines_interleaved_in_mem_access[i]), bw_int_to_fixed(data->bytes_per_pixel[i]));
-+ data->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(data->bytes_per_pixel[i]));
-+ }
-+ }
-+ }
-+ data->min_dmif_size_in_time = bw_int_to_fixed(9999);
-+ data->min_mcifwr_size_in_time = bw_int_to_fixed(9999);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->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(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_dmif_size_in_time)) {
-+ data->min_dmif_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]);
-+ }
-+ }
-+ else {
-+ if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_mcifwr_size_in_time)) {
-+ data->min_mcifwr_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]);
-+ }
-+ }
-+ }
-+ }
-+ data->total_requests_for_dmif_size = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i] && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->total_requests_for_dmif_size = bw_add(data->total_requests_for_dmif_size, bw_div(data->data_buffer_size[i], data->useful_bytes_per_request[i]));
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->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 && (data->number_of_displays > 1 || bw_mtn(data->total_requests_for_dmif_size, dceip->dmif_request_buffer_size))) {
-+ data->adjusted_data_buffer_size[i] = bw_min2(data->data_buffer_size[i], bw_ceil2(bw_mul(data->min_dmif_size_in_time, data->display_bandwidth[i]), data->memory_chunk_size_in_bytes[i]));
-+ }
-+ else {
-+ data->adjusted_data_buffer_size[i] = data->data_buffer_size[i];
-+ }
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if ((data->number_of_displays == 1 && data->number_of_underlay_surfaces == 0)) {
-+ /*set maximum chunk limit if only one graphic pipe is enabled*/
-+ data->outstanding_chunk_request_limit[i] = bw_int_to_fixed(127);
-+ }
-+ else {
-+ data->outstanding_chunk_request_limit[i] = bw_ceil2(bw_div(data->adjusted_data_buffer_size[i], data->pipe_chunk_size_in_bytes[i]), bw_int_to_fixed(1));
-+ /*clamp maximum chunk limit in the graphic display pipe*/
-+ if ((i >= 4)) {
-+ data->outstanding_chunk_request_limit[i] = bw_max2(bw_int_to_fixed(127), data->outstanding_chunk_request_limit[i]);
-+ }
-+ }
-+ }
-+ }
-+ /*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 (data->number_of_displays > 1 || (bw_neq(data->rotation_angle[4], bw_int_to_fixed(0)) && bw_neq(data->rotation_angle[4], bw_int_to_fixed(180)))) {
-+ data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
-+ }
-+ else {
-+ data->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 (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) {
-+ if (tiling_mode[i] == bw_def_linear) {
-+ data->useful_pte_per_pte_request = bw_int_to_fixed(8);
-+ data->scatter_gather_page_width[i] = bw_div(bw_int_to_fixed(4096), bw_int_to_fixed(data->bytes_per_pixel[i]));
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(1);
-+ data->scatter_gather_pte_request_rows = bw_int_to_fixed(1);
-+ data->scatter_gather_row_height = bw_int_to_fixed(dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode);
-+ }
-+ else if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(0)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(180))) {
-+ data->useful_pte_per_pte_request = bw_int_to_fixed(8);
-+ switch (data->bytes_per_pixel[i]) {
-+ case 4:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(32);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(32);
-+ break;
-+ case 2:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(64);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(32);
-+ break;
-+ default:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(64);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(64);
-+ break;
-+ }
-+ data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode);
-+ data->scatter_gather_row_height = data->scatter_gather_page_height[i];
-+ }
-+ else {
-+ data->useful_pte_per_pte_request = bw_int_to_fixed(1);
-+ switch (data->bytes_per_pixel[i]) {
-+ case 4:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(32);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(32);
-+ break;
-+ case 2:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(32);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(64);
-+ break;
-+ default:
-+ data->scatter_gather_page_width[i] = bw_int_to_fixed(64);
-+ data->scatter_gather_page_height[i] = bw_int_to_fixed(64);
-+ break;
-+ }
-+ data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode);
-+ data->scatter_gather_row_height = data->scatter_gather_page_height[i];
-+ }
-+ data->pte_request_per_chunk[i] = bw_div(bw_div(bw_int_to_fixed(dceip->chunk_width), data->scatter_gather_page_width[i]), data->useful_pte_per_pte_request);
-+ data->scatter_gather_pte_requests_in_row[i] = bw_div(bw_mul(bw_ceil2(bw_mul(bw_div(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(dceip->chunk_width)), data->pte_request_per_chunk[i]), bw_int_to_fixed(1)), data->scatter_gather_row_height), data->scatter_gather_page_height[i]);
-+ data->scatter_gather_pte_requests_in_vblank = bw_mul(data->scatter_gather_pte_request_rows, data->scatter_gather_pte_requests_in_row[i]);
-+ if (bw_equ(data->peak_pte_request_to_eviction_ratio_limiting, bw_int_to_fixed(0))) {
-+ data->scatter_gather_pte_request_limit[i] = data->scatter_gather_pte_requests_in_vblank;
-+ }
-+ else {
-+ data->scatter_gather_pte_request_limit[i] = bw_max2(dceip->minimum_outstanding_pte_request_limit, bw_min2(data->scatter_gather_pte_requests_in_vblank, bw_ceil2(bw_mul(bw_mul(bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->memory_chunk_size_in_bytes[i]), data->pte_request_per_chunk[i]), data->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*/
-+ data->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(data->number_of_dram_channels));
-+
-+ /*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.*/
-+ data->cursor_total_data = bw_int_to_fixed(0);
-+ data->cursor_total_request_groups = bw_int_to_fixed(0);
-+ data->scatter_gather_total_pte_requests = bw_int_to_fixed(0);
-+ data->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->cursor_total_data = bw_add(data->cursor_total_data, bw_mul(bw_mul(bw_int_to_fixed(2), data->cursor_width_pixels[i]), bw_int_to_fixed(4)));
-+ if (dceip->large_cursor == 1) {
-+ data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_int_to_fixed((dceip->cursor_max_outstanding_group_num + 1)));
-+ }
-+ else {
-+ data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_ceil2(bw_div(data->cursor_width_pixels[i], dceip->cursor_chunk_width), bw_int_to_fixed(1)));
-+ }
-+ if (data->scatter_gather_enable_for_pipe[i]) {
-+ data->scatter_gather_total_pte_requests = bw_add(data->scatter_gather_total_pte_requests, data->scatter_gather_pte_request_limit[i]);
-+ data->scatter_gather_total_pte_request_groups = bw_add(data->scatter_gather_total_pte_request_groups, bw_ceil2(bw_div(data->scatter_gather_pte_request_limit[i], bw_ceil2(data->pte_request_per_chunk[i], bw_int_to_fixed(1))), bw_int_to_fixed(1)));
-+ }
-+ }
-+ }
-+ data->tile_width_in_pixels = bw_int_to_fixed(8);
-+ data->dmif_total_number_of_data_request_page_close_open = bw_int_to_fixed(0);
-+ data->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 (data->enable[i]) {
-+ if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] != bw_def_linear) {
-+ data->bytes_per_page_close_open = bw_mul(data->lines_interleaved_in_mem_access[i], bw_max2(bw_mul(bw_mul(bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->tile_width_in_pixels), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)), bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->scatter_gather_page_width[i])));
-+ }
-+ else if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] == bw_def_linear && bw_equ(bw_mod((bw_mul(data->pitch_in_pixels_after_surface_type[i], bw_int_to_fixed(data->bytes_per_pixel[i]))), data->inefficient_linear_pitch_in_bytes), bw_int_to_fixed(0))) {
-+ data->bytes_per_page_close_open = dceip->linear_mode_line_request_alternation_slice;
-+ }
-+ else {
-+ data->bytes_per_page_close_open = data->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) {
-+ data->dmif_total_number_of_data_request_page_close_open = bw_add(data->dmif_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open));
-+ }
-+ else {
-+ data->mcifwr_total_number_of_data_request_page_close_open = bw_add(data->mcifwr_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open));
-+ }
-+ }
-+ }
-+ data->dmif_total_page_close_open_time = bw_div(bw_mul((bw_add(bw_add(data->dmif_total_number_of_data_request_page_close_open, data->scatter_gather_total_pte_request_groups), data->cursor_total_request_groups)), vbios->trc), bw_int_to_fixed(1000));
-+ data->mcifwr_total_page_close_open_time = bw_div(bw_mul(data->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 (data->enable[i]) {
-+ data->adjusted_data_buffer_size_in_memory[i] = bw_div(bw_mul(data->adjusted_data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
-+ }
-+ }
-+ data->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->total_requests_for_adjusted_dmif_size = bw_add(data->total_requests_for_adjusted_dmif_size, bw_div(data->adjusted_data_buffer_size[i], data->useful_bytes_per_request[i]));
-+ }
-+ }
-+ }
-+ data->total_dmifmc_urgent_trips = bw_ceil2(bw_div(data->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 * data->number_of_dram_channels)))), bw_int_to_fixed(1));
-+ data->total_dmifmc_urgent_latency = bw_mul(vbios->dmifmc_urgent_latency, data->total_dmifmc_urgent_trips);
-+ data->total_display_reads_required_data = bw_int_to_fixed(0);
-+ data->total_display_reads_required_dram_access_data = bw_int_to_fixed(0);
-+ data->total_display_writes_required_data = bw_int_to_fixed(0);
-+ data->total_display_writes_required_dram_access_data = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->display_reads_required_data = data->adjusted_data_buffer_size_in_memory[i];
-+ /*for hbm memories, each channel is split into 2 pseudo-channels that are each 64 bits in width. each*/
-+ /*pseudo-channel may be read independently of one another.*/
-+ /*the read burst length (bl) for hbm memories is 4, so each read command will access 32 bytes of data.*/
-+ /*the 64 or 32 byte sized data is stored in one pseudo-channel.*/
-+ /*it will take 4 memclk cycles or 8 yclk cycles to fetch 64 bytes of data from the hbm memory (2 read commands).*/
-+ /*it will take 2 memclk cycles or 4 yclk cycles to fetch 32 bytes of data from the hbm memory (1 read command).*/
-+ /*for gddr5/ddr4 memories, there is additional overhead if the size of the request is smaller than 64 bytes.*/
-+ /*the read burst length (bl) for gddr5/ddr4 memories is 8, regardless of the size of the data request.*/
-+ /*therefore it will require 8 cycles to fetch 64 or 32 bytes of data from the memory.*/
-+ /*the memory efficiency will be 50% for the 32 byte sized data.*/
-+ if (vbios->memory_type == bw_def_hbm) {
-+ data->display_reads_required_dram_access_data = data->adjusted_data_buffer_size_in_memory[i];
-+ }
-+ else {
-+ data->display_reads_required_dram_access_data = bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed((8 * vbios->dram_channel_width_in_bits / 8)), data->bytes_per_request[i]), bw_int_to_fixed(1)));
-+ }
-+ data->total_display_reads_required_data = bw_add(data->total_display_reads_required_data, data->display_reads_required_data);
-+ data->total_display_reads_required_dram_access_data = bw_add(data->total_display_reads_required_dram_access_data, data->display_reads_required_dram_access_data);
-+ }
-+ else {
-+ data->total_display_writes_required_data = bw_add(data->total_display_writes_required_data, data->adjusted_data_buffer_size_in_memory[i]);
-+ data->total_display_writes_required_dram_access_data = bw_add(data->total_display_writes_required_dram_access_data, bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits), data->bytes_per_request[i]), bw_int_to_fixed(1))));
-+ }
-+ }
-+ }
-+ data->total_display_reads_required_data = bw_add(bw_add(data->total_display_reads_required_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64)));
-+ data->total_display_reads_required_dram_access_data = bw_add(bw_add(data->total_display_reads_required_dram_access_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64)));
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(4))) {
-+ data->src_pixels_for_first_output_pixel[i] = bw_mul(bw_int_to_fixed(4), data->source_width_rounded_up_to_chunks[i]);
-+ }
-+ else {
-+ if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(2))) {
-+ data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(512);
-+ }
-+ else {
-+ data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(0);
-+ }
-+ }
-+ data->src_data_for_first_output_pixel[i] = bw_div(bw_mul(bw_mul(data->src_pixels_for_first_output_pixel[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
-+ data->src_pixels_for_last_output_pixel[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_mul(bw_ceil2(data->vsr[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->horizontal_blank_and_chunk_granularity_factor[i])));
-+ data->src_data_for_last_output_pixel[i] = bw_div(bw_mul(bw_mul(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->lines_interleaved_in_mem_access[i])), bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
-+ data->active_time[i] = bw_div(bw_div(data->source_width_rounded_up_to_chunks[i], data->hsr[i]), data->pixel_rate[i]);
-+ }
-+ }
-+ for (i = 0; i <= 2; i++) {
-+ for (j = 0; j <= 7; j++) {
-+ data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency)))));
-+ if (data->d1_display_write_back_dwb_enable == 1) {
-+ data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency)))));
-+ }
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ for (j = 0; j <= 2; j++) {
-+ for (k = 0; k <= 7; k++) {
-+ if (data->enable[i]) {
-+ if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ /*time to transfer data from the dmif buffer to the lb. since the mc to dmif transfer time overlaps*/
-+ /*with the dmif to lb transfer time, only time to transfer the last chunk is considered.*/
-+ data->dmif_buffer_transfer_time[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], (bw_div(dceip->lb_write_pixels_per_dispclk, (bw_div(vbios->low_voltage_max_dispclk, dceip->display_pipe_throughput_factor)))));
-+ data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_add(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->dmif_buffer_transfer_time[i]), data->active_time[i]));
-+ /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/
-+ /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/
-+ /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/
-+ /*immediately serviced without a gap in the urgent requests.*/
-+ /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/
-+ if (surface_type[i] == bw_def_graphics) {
-+ switch (data->lb_bpc[i]) {
-+ case 6:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component;
-+ break;
-+ case 8:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component;
-+ break;
-+ case 10:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component;
-+ break;
-+ default:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component;
-+ break;
-+ }
-+ if (data->use_alpha[i] == 1) {
-+ data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency);
-+ }
-+ }
-+ else {
-+ switch (data->lb_bpc[i]) {
-+ case 6:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component;
-+ break;
-+ case 8:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component;
-+ break;
-+ case 10:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component;
-+ break;
-+ default:
-+ data->v_scaler_efficiency = bw_int_to_fixed(3);
-+ break;
-+ }
-+ }
-+ if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) {
-+ data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i]));
-+ }
-+ else {
-+ data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1))));
-+ }
-+ data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_mul(bw_int_to_fixed(2), bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]))))));
-+ }
-+ else {
-+ data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]));
-+ /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/
-+ /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/
-+ /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/
-+ /*immediately serviced without a gap in the urgent requests.*/
-+ /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/
-+ data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->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 (data->enable[i]) {
-+ if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) {
-+ if (bw_ltn(data->vsr[i], bw_int_to_fixed(2))) {
-+ data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(1))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]);
-+ }
-+ else {
-+ data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(3))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]);
-+ }
-+ }
-+ else {
-+ data->cursor_latency_hiding[i] = bw_int_to_fixed(9999);
-+ }
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) {
-+ data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
-+ }
-+ else {
-+ data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency);
-+ }
-+ data->minimum_latency_hiding_with_cursor[i] = bw_min2(data->minimum_latency_hiding[i], data->cursor_latency_hiding[i]);
-+ }
-+ }
-+ for (i = 0; i <= 2; i++) {
-+ for (j = 0; j <= 7; j++) {
-+ data->blackout_duration_margin[i][j] = bw_int_to_fixed(9999);
-+ data->dispclk_required_for_blackout_duration[i][j] = bw_int_to_fixed(0);
-+ data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(0);
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ if (data->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) {
-+ data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->line_source_transfer_time[k][i][j]));
-+ data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->active_time[k]))));
-+ if (bw_leq(vbios->maximum_blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))) {
-+ data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999);
-+ }
-+ else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) {
-+ data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, bw_sub(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k]));
-+ }
-+ }
-+ else {
-+ data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->line_source_transfer_time[k][i][j]));
-+ data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->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(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->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), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))) {
-+ data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999);
-+ }
-+ else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) {
-+ data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, (bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k]));
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ if (bw_mtn(data->blackout_duration_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[high][s_high], vbios->high_voltage_max_dispclk)) {
-+ data->cpup_state_change_enable = bw_def_yes;
-+ if (bw_ltn(data->dispclk_required_for_blackout_recovery[high][s_high], vbios->high_voltage_max_dispclk)) {
-+ data->cpuc_state_change_enable = bw_def_yes;
-+ }
-+ else {
-+ data->cpuc_state_change_enable = bw_def_no;
-+ }
-+ }
-+ else {
-+ data->cpup_state_change_enable = bw_def_no;
-+ data->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 (data->enable[i]) {
-+ if ((dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) {
-+ data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency));
-+ }
-+ else {
-+ /*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/
-+ data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency));
-+ }
-+ data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]);
-+ }
-+ }
-+ /*initialize variables*/
-+ number_of_displays_enabled = 0;
-+ number_of_displays_enabled_with_margin = 0;
-+ for (k = 0; k < maximum_number_of_surfaces; k++) {
-+ if (data->enable[k]) {
-+ number_of_displays_enabled = number_of_displays_enabled + 1;
-+ }
-+ }
-+ data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0;
-+ for (i = 0; i <= 2; i++) {
-+ for (j = 0; j <= 7; j++) {
-+ data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999);
-+ data->dram_speed_change_margin = bw_int_to_fixed(9999);
-+ data->dispclk_required_for_dram_speed_change[i][j] = bw_int_to_fixed(0);
-+ data->num_displays_with_margin[i][j] = 0;
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ if (data->enable[k]) {
-+ if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) {
-+ data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]);
-+ if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) {
-+ /*determine the minimum dram clock change margin for each set of clock frequencies*/
-+ data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin);
-+ /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/
-+ data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->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(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k]))));
-+ if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) {
-+ data->display_pstate_change_enable[k] = 1;
-+ data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1;
-+ }
-+ }
-+ }
-+ else {
-+ data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]);
-+ if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) {
-+ /*determine the minimum dram clock change margin for each display pipe*/
-+ data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin);
-+ /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/
-+ data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->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(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k]))));
-+ if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) {
-+ data->display_pstate_change_enable[k] = 1;
-+ data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ /*determine the number of displays with margin to switch in the v_active region*/
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ if ((data->enable[k] == 1 && data->display_pstate_change_enable[k] == 1)) {
-+ number_of_displays_enabled_with_margin = number_of_displays_enabled_with_margin + 1;
-+ }
-+ }
-+ /*determine the number of displays that don't have any dram clock change margin, but*/
-+ /*have the same resolution. these displays can switch in a common vblank region if*/
-+ /*their frames are aligned.*/
-+ data->min_vblank_dram_speed_change_margin = bw_int_to_fixed(9999);
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ if (data->enable[k]) {
-+ if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) {
-+ data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]);
-+ data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]);
-+ }
-+ else {
-+ data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->mcifwr_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]);
-+ data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]);
-+ }
-+ }
-+ }
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ data->displays_with_same_mode[i] = bw_int_to_fixed(0);
-+ if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) {
-+ for (j = 0; j <= maximum_number_of_surfaces - 1; j++) {
-+ if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) {
-+ data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1));
-+ }
-+ }
-+ }
-+ }
-+ /*compute the maximum number of aligned displays with no margin*/
-+ number_of_aligned_displays_with_no_margin = 0;
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ number_of_aligned_displays_with_no_margin = bw_fixed_to_int(bw_max2(bw_int_to_fixed(number_of_aligned_displays_with_no_margin), data->displays_with_same_mode[i]));
-+ }
-+ /*dram clock change is possible, if all displays have positive margin except for one display or a group of*/
-+ /*aligned displays with the same timing.*/
-+ /*the display(s) with the negative margin can be switched in the v_blank region while the other*/
-+ /*displays are in v_blank or v_active.*/
-+ if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) {
-+ data->nbp_state_change_enable = bw_def_yes;
-+ }
-+ else {
-+ data->nbp_state_change_enable = bw_def_no;
-+ }
-+ /*dram clock change is possible only in vblank if all displays are aligned and have no margin*/
-+ if ((number_of_aligned_displays_with_no_margin == number_of_displays_enabled)) {
-+ nbp_state_change_enable_blank = bw_def_yes;
-+ }
-+ else {
-+ nbp_state_change_enable_blank = 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.*/
-+ data->min_cursor_memory_interface_buffer_size_in_time = bw_int_to_fixed(9999);
-+ /* number of cursor lines stored in the cursor data return buffer*/
-+ num_cursor_lines = 0;
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0))) {
-+ /*compute number of cursor lines stored in data return buffer*/
-+ if (bw_leq(data->cursor_width_pixels[i], bw_int_to_fixed(64)) && dceip->large_cursor == 1) {
-+ num_cursor_lines = 4;
-+ }
-+ else {
-+ num_cursor_lines = 2;
-+ }
-+ data->min_cursor_memory_interface_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, bw_div(bw_mul(bw_div(bw_int_to_fixed(num_cursor_lines), data->vsr[i]), data->h_total[i]), data->pixel_rate[i]));
-+ }
-+ }
-+ }
-+ /*compute minimum time to read one chunk from the dmif buffer*/
-+ if ((number_of_displays_enabled > 2)) {
-+ data->chunk_request_delay = 0;
-+ }
-+ else {
-+ data->chunk_request_delay = bw_fixed_to_int(bw_div(bw_int_to_fixed(512), vbios->high_voltage_max_dispclk));
-+ }
-+ data->min_read_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, data->min_dmif_size_in_time);
-+ data->display_reads_time_for_data_transfer = bw_sub(bw_sub(data->min_read_buffer_size_in_time, data->total_dmifmc_urgent_latency), bw_int_to_fixed(data->chunk_request_delay));
-+ data->display_writes_time_for_data_transfer = bw_sub(data->min_mcifwr_size_in_time, vbios->mcifwrmc_urgent_latency);
-+ data->dmif_required_dram_bandwidth = bw_div(data->total_display_reads_required_dram_access_data, data->display_reads_time_for_data_transfer);
-+ data->mcifwr_required_dram_bandwidth = bw_div(data->total_display_writes_required_dram_access_data, data->display_writes_time_for_data_transfer);
-+ data->required_dmifmc_urgent_latency_for_page_close_open = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_total_page_close_open_time)), data->total_dmifmc_urgent_trips);
-+ data->required_mcifmcwr_urgent_latency = bw_sub(data->min_mcifwr_size_in_time, data->mcifwr_total_page_close_open_time);
-+ if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
-+ data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999);
-+ yclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
-+ data->y_clk_level = high;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
-+ }
-+ else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) {
-+ data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999);
-+ yclk_message = bw_def_exceeded_allowed_page_close_open;
-+ data->y_clk_level = high;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
-+ }
-+ else {
-+ data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000));
-+ if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) {
-+ yclk_message = bw_fixed_to_int(vbios->low_yclk);
-+ data->y_clk_level = low;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
-+ }
-+ else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) {
-+ yclk_message = bw_fixed_to_int(vbios->mid_yclk);
-+ data->y_clk_level = mid;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
-+ }
-+ else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) {
-+ yclk_message = bw_fixed_to_int(vbios->high_yclk);
-+ data->y_clk_level = high;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels));
-+ }
-+ else {
-+ yclk_message = bw_def_exceeded_allowed_maximum_bw;
-+ data->y_clk_level = high;
-+ data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->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.*/
-+ data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
-+ data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
-+ if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
-+ data->required_sclk = bw_int_to_fixed(9999);
-+ sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
-+ data->sclk_level = s_high;
-+ }
-+ else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) {
-+ data->required_sclk = bw_int_to_fixed(9999);
-+ sclk_message = bw_def_exceeded_allowed_page_close_open;
-+ data->sclk_level = s_high;
-+ }
-+ else {
-+ data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk);
-+ if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_low;
-+ data->sclk_level = s_low;
-+ data->required_sclk = vbios->low_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid1;
-+ data->required_sclk = vbios->mid1_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid2;
-+ data->required_sclk = vbios->mid2_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid3;
-+ data->required_sclk = vbios->mid3_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid4;
-+ data->required_sclk = vbios->mid4_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid5;
-+ data->required_sclk = vbios->mid5_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) {
-+ sclk_message = bw_def_mid;
-+ data->sclk_level = s_mid6;
-+ data->required_sclk = vbios->mid6_sclk;
-+ }
-+ else if (bw_ltn(data->required_sclk, sclk[s_high])) {
-+ sclk_message = bw_def_high;
-+ data->sclk_level = s_high;
-+ data->required_sclk = vbios->high_sclk;
-+ }
-+ else {
-+ sclk_message = bw_def_exceeded_allowed_maximum_sclk;
-+ data->sclk_level = s_high;
-+ /*required_sclk = high_sclk*/
-+ }
-+ }
-+ /*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")*/
-+ data->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 (data->enable[i]) {
-+ if (surface_type[i] == bw_def_graphics) {
-+ switch (data->lb_bpc[i]) {
-+ case 6:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component;
-+ break;
-+ case 8:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component;
-+ break;
-+ case 10:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component;
-+ break;
-+ default:
-+ data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component;
-+ break;
-+ }
-+ if (data->use_alpha[i] == 1) {
-+ data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency);
-+ }
-+ }
-+ else {
-+ switch (data->lb_bpc[i]) {
-+ case 6:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component;
-+ break;
-+ case 8:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component;
-+ break;
-+ case 10:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component;
-+ break;
-+ default:
-+ data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency12_bit_per_component;
-+ break;
-+ }
-+ }
-+ if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) {
-+ data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i]));
-+ }
-+ else {
-+ data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1))));
-+ }
-+ data->display_pipe_pixel_throughput = bw_div(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], bw_mul(data->lb_lines_in_per_line_out_in_middle_of_frame[i], data->horizontal_blank_and_chunk_granularity_factor[i])), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), dceip->lb_write_pixels_per_dispclk);
-+ data->dispclk_required_without_ramping[i] = bw_mul(data->downspread_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), bw_mul(dceip->display_pipe_throughput_factor, data->display_pipe_pixel_throughput)));
-+ data->dispclk_required_with_ramping[i] = bw_mul(dceip->dispclk_ramping_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), data->display_pipe_pixel_throughput));
-+ }
-+ }
-+ data->total_dispclk_required_with_ramping = bw_int_to_fixed(0);
-+ data->total_dispclk_required_without_ramping = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (bw_ltn(data->total_dispclk_required_with_ramping, data->dispclk_required_with_ramping[i])) {
-+ data->total_dispclk_required_with_ramping = data->dispclk_required_with_ramping[i];
-+ }
-+ if (bw_ltn(data->total_dispclk_required_without_ramping, data->dispclk_required_without_ramping[i])) {
-+ data->total_dispclk_required_without_ramping = data->dispclk_required_without_ramping[i];
-+ }
-+ }
-+ }
-+ data->total_read_request_bandwidth = bw_int_to_fixed(0);
-+ data->total_write_request_bandwidth = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->total_read_request_bandwidth = bw_add(data->total_read_request_bandwidth, data->request_bandwidth[i]);
-+ }
-+ else {
-+ data->total_write_request_bandwidth = bw_add(data->total_write_request_bandwidth, data->request_bandwidth[i]);
-+ }
-+ }
-+ }
-+ data->dispclk_required_for_total_read_request_bandwidth = bw_div(bw_mul(data->total_read_request_bandwidth, dceip->dispclk_per_request), dceip->request_efficiency);
-+ data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping, data->dispclk_required_for_total_read_request_bandwidth);
-+ data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping, data->dispclk_required_for_total_read_request_bandwidth);
-+ if (data->cpuc_state_change_enable == bw_def_yes) {
-+ data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]);
-+ data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]);
-+ }
-+ if (data->cpup_state_change_enable == bw_def_yes) {
-+ data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]);
-+ data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]);
-+ }
-+ if (data->nbp_state_change_enable == bw_def_yes) {
-+ data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]);
-+ data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]);
-+ }
-+ if (bw_ltn(data->total_dispclk_required_with_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) {
-+ data->dispclk = data->total_dispclk_required_with_ramping_with_request_bandwidth;
-+ }
-+ else if (bw_ltn(data->total_dispclk_required_without_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) {
-+ data->dispclk = vbios->high_voltage_max_dispclk;
-+ }
-+ else {
-+ data->dispclk = data->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 (bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) && sclk_message == bw_def_low && bw_ltn(data->dispclk, vbios->low_voltage_max_dispclk)) {
-+ voltage = bw_def_0_72;
-+ }
-+ else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid) && bw_ltn(data->dispclk, vbios->mid_voltage_max_dispclk)) {
-+ voltage = bw_def_0_8;
-+ }
-+ else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->high_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid || sclk_message == bw_def_high) && bw_leq(data->dispclk, vbios->high_voltage_max_dispclk)) {
-+ if ((data->nbp_state_change_enable == bw_def_no && nbp_state_change_enable_blank == bw_def_no)) {
-+ voltage = bw_def_high_no_nbp_state_change;
-+ }
-+ else {
-+ voltage = bw_def_0_9;
-+ }
-+ }
-+ else {
-+ voltage = bw_def_notok;
-+ }
-+ if (voltage == bw_def_0_72) {
-+ data->max_phyclk = vbios->low_voltage_max_phyclk;
-+ }
-+ else if (voltage == bw_def_0_8) {
-+ data->max_phyclk = vbios->mid_voltage_max_phyclk;
-+ }
-+ else {
-+ data->max_phyclk = vbios->high_voltage_max_phyclk;
-+ }
-+ /*required blackout recovery time*/
-+ data->blackout_recovery_time = bw_int_to_fixed(0);
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0)) && data->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) {
-+ data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level]));
-+ if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])))))) {
-+ data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->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), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k])))));
-+ }
-+ }
-+ else {
-+ data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]));
-+ if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) {
-+ data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->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), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->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 (data->enable[i]) {
-+ if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) {
-+ data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16);
-+ }
-+ else if (surface_type[i] == bw_def_graphics) {
-+ data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(64), bw_int_to_fixed(data->bytes_per_pixel[i]));
-+ }
-+ else if (data->orthogonal_rotation[i] == 0) {
-+ data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16);
-+ }
-+ else {
-+ data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(16), bw_int_to_fixed(data->bytes_per_pixel[i]));
-+ }
-+ }
-+ }
-+ data->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (bw_mtn(data->min_pixels_per_data_fifo_entry, data->pixels_per_data_fifo_entry[i])) {
-+ data->min_pixels_per_data_fifo_entry = data->pixels_per_data_fifo_entry[i];
-+ }
-+ }
-+ }
-+ data->sclk_deep_sleep = bw_max2(bw_div(bw_mul(data->dispclk, bw_frc_to_fixed(115, 100)), data->min_pixels_per_data_fifo_entry), data->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*/
-+ data->chunk_request_time = bw_int_to_fixed(0);
-+ data->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 (data->enable[i]) {
-+ data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2))))));
-+ }
-+ }
-+ /*compute total time to request cursor data*/
-+ data->cursor_request_time = (bw_div(data->cursor_total_data, (bw_mul(bw_int_to_fixed(32), sclk[data->sclk_level]))));
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->line_source_pixels_transfer_time = bw_max2(bw_div(bw_div(data->src_pixels_for_first_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), bw_sub(bw_div(bw_div(data->src_pixels_for_last_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), data->active_time[i]));
-+ if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) {
-+ data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time);
-+ data->stutter_exit_watermark[i] = bw_add(bw_sub(vbios->stutter_self_refresh_exit_latency, data->total_dmifmc_urgent_latency), data->urgent_watermark[i]);
-+ data->stutter_entry_watermark[i] = bw_add(bw_sub(bw_add(vbios->stutter_self_refresh_exit_latency, vbios->stutter_self_refresh_entry_latency), data->total_dmifmc_urgent_latency), data->urgent_watermark[i]);
-+ /*unconditionally remove black out time from the nb p_state watermark*/
-+ if ((data->display_pstate_change_enable[i] == 1)) {
-+ data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level]));
-+ }
-+ else {
-+ /*maximize the watermark to force the switch in the vb_lank region of the frame*/
-+ data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000);
-+ }
-+ }
-+ else {
-+ data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time);
-+ data->stutter_exit_watermark[i] = bw_int_to_fixed(0);
-+ data->stutter_entry_watermark[i] = bw_int_to_fixed(0);
-+ if ((data->display_pstate_change_enable[i] == 1)) {
-+ data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level]));
-+ }
-+ else {
-+ /*maximize the watermark to force the switch in the vb_lank region of the frame*/
-+ data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000);
-+ }
-+ }
-+ }
-+ }
-+ /*stutter mode enable*/
-+ /*in the multi-display case the stutter exit or entry watermark cannot exceed the minimum latency hiding capabilities of the*/
-+ /*display pipe.*/
-+ data->stutter_mode_enable = data->cpuc_state_change_enable;
-+ if (data->number_of_displays > 1) {
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if ((bw_mtn(data->stutter_exit_watermark[i], data->minimum_latency_hiding[i]) || bw_mtn(data->stutter_entry_watermark[i], data->minimum_latency_hiding[i]))) {
-+ data->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*/
-+ data->dmifdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_reads_required_dram_access_data, data->dram_bandwidth), data->dmif_total_page_close_open_time), bw_int_to_fixed(1));
-+ if (bw_mtn(data->total_display_writes_required_dram_access_data, bw_int_to_fixed(0))) {
-+ data->mcifwrdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_writes_required_dram_access_data, data->dram_bandwidth), data->mcifwr_total_page_close_open_time), bw_int_to_fixed(1));
-+ }
-+ else {
-+ data->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 (data->enable[i]) {
-+ data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]);
-+ data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]);
-+ }
-+ }
-+ data->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
-+ data->total_average_bandwidth = bw_int_to_fixed(0);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]);
-+ data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->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*/
-+ /*compute the time read all the data from the dmif buffer to the lb (dram refresh period)*/
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->stutter_refresh_duration[i] = bw_sub(bw_mul(bw_div(bw_div(bw_mul(bw_div(bw_div(data->adjusted_data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]), bw_max2(bw_int_to_fixed(0), bw_sub(data->stutter_exit_watermark[i], bw_div(bw_mul((bw_sub(data->lb_partitions[i], bw_int_to_fixed(1))), data->h_total[i]), data->pixel_rate[i]))));
-+ data->stutter_dmif_buffer_size[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(bw_mul(data->stutter_refresh_duration[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]);
-+ }
-+ }
-+ data->min_stutter_refresh_duration = bw_int_to_fixed(9999);
-+ data->total_stutter_dmif_buffer_size = 0;
-+ data->total_bytes_requested = 0;
-+ data->min_stutter_dmif_buffer_size = 9999;
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ if (bw_mtn(data->min_stutter_refresh_duration, data->stutter_refresh_duration[i])) {
-+ data->min_stutter_refresh_duration = data->stutter_refresh_duration[i];
-+ data->total_bytes_requested = bw_fixed_to_int(bw_add(bw_int_to_fixed(data->total_bytes_requested), (bw_mul(bw_mul(data->source_height_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[i]), bw_int_to_fixed(data->bytes_per_pixel[i])))));
-+ data->min_stutter_dmif_buffer_size = bw_fixed_to_int(data->stutter_dmif_buffer_size[i]);
-+ }
-+ data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size)));
-+ }
-+ }
-+ data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32))));
-+ data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size;
-+ data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time);
-+ data->time_in_self_refresh = data->min_stutter_refresh_duration;
-+ if (data->d1_display_write_back_dwb_enable == 1) {
-+ data->stutter_efficiency = bw_int_to_fixed(0);
-+ }
-+ else if (bw_ltn(data->time_in_self_refresh, bw_int_to_fixed(0))) {
-+ data->stutter_efficiency = bw_int_to_fixed(0);
-+ }
-+ else {
-+ /*compute stutter efficiency assuming 60 hz refresh rate*/
-+ data->stutter_efficiency = bw_max2(bw_int_to_fixed(0), bw_mul((bw_sub(bw_int_to_fixed(1), (bw_div(bw_mul((bw_add(vbios->stutter_self_refresh_exit_latency, data->stutter_burst_time)), bw_int_to_fixed(data->num_stutter_bursts)), bw_frc_to_fixed(166666667, 10000))))), 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*/
-+ data->worst_number_of_trips_to_memory = bw_int_to_fixed(1);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) {
-+ data->number_of_trips_to_memory_for_getting_apte_row[i] = bw_ceil2(bw_div(data->scatter_gather_pte_requests_in_row[i], data->scatter_gather_pte_request_limit[i]), bw_int_to_fixed(1));
-+ if (bw_ltn(data->worst_number_of_trips_to_memory, data->number_of_trips_to_memory_for_getting_apte_row[i])) {
-+ data->worst_number_of_trips_to_memory = data->number_of_trips_to_memory_for_getting_apte_row[i];
-+ }
-+ }
-+ }
-+ data->immediate_flip_time = bw_mul(data->worst_number_of_trips_to_memory, data->total_dmifmc_urgent_latency);
-+ /*worst latency for other clients*/
-+ /*it is the urgent latency plus the urgent burst time*/
-+ data->latency_for_non_dmif_clients = bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]);
-+ if (data->d1_display_write_back_dwb_enable == 1) {
-+ data->latency_for_non_mcifwr_clients = bw_add(vbios->mcifwrmc_urgent_latency, dceip->mcifwr_all_surfaces_burst_time);
-+ }
-+ else {
-+ data->latency_for_non_mcifwr_clients = bw_int_to_fixed(0);
-+ }
-+ /*dmif mc urgent latency suppported in high sclk and yclk*/
-+ data->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_burst_time[high][s_high])), data->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*/
-+ data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999);
-+ data->nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999);
-+ for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
-+ if (data->enable[i]) {
-+ data->nbp_state_dram_speed_change_latency_supported = bw_min2(data->nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(data->maximum_latency_hiding_with_cursor[i], data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency));
-+ data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_min2(data->v_blank_nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[i], bw_sub(bw_div(data->src_height[i], data->v_scale_ratio[i]), bw_int_to_fixed(4)))), data->h_total[i]), data->pixel_rate[i]), data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency));
-+ }
-+ }
-+ /*sclk required vs urgent latency*/
-+ for (i = 1; i <= 5; i++) {
-+ data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i)));
-+ if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) {
-+ data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency))));
-+ }
-+ else {
-+ data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na);
-+ }
-+ }
-+ /*output link bit per pixel supported*/
-+ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
-+ data->output_bpphdmi[k] = bw_def_na;
-+ data->output_bppdp4_lane_hbr[k] = bw_def_na;
-+ data->output_bppdp4_lane_hbr2[k] = bw_def_na;
-+ data->output_bppdp4_lane_hbr3[k] = bw_def_na;
-+ if (data->enable[k]) {
-+ data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24)));
-+ if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) {
-+ data->output_bppdp4_lane_hbr[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(270), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8)));
-+ }
-+ if (bw_meq(data->max_phyclk, bw_int_to_fixed(540))) {
-+ data->output_bppdp4_lane_hbr2[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(540), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8)));
-+ }
-+ if (bw_meq(data->max_phyclk, bw_int_to_fixed(810))) {
-+ data->output_bppdp4_lane_hbr3[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(810), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8)));
-+ }
-+ }
-+ }
-+}
-+
-+/*******************************************************************************
-+ * Public functions
-+ ******************************************************************************/
-+void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
-+ struct bw_calcs_vbios *bw_vbios,
-+ enum bw_calcs_version version)
-+{
-+ struct bw_calcs_dceip dceip = { 0 };
-+ struct bw_calcs_vbios vbios = { 0 };
-+
-+ dceip.version = version;
-+
-+ switch (version) {
-+ case BW_CALCS_VERSION_CARRIZO:
-+ vbios.memory_type = bw_def_gddr5;
-+ vbios.dram_channel_width_in_bits = 64;
-+ vbios.number_of_dram_channels = 2;
-+ 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.mid1_sclk = bw_int_to_fixed(300);
-+ vbios.mid2_sclk = bw_int_to_fixed(300);
-+ vbios.mid3_sclk = bw_int_to_fixed(300);
-+ vbios.mid4_sclk = bw_int_to_fixed(300);
-+ vbios.mid5_sclk = bw_int_to_fixed(300);
-+ vbios.mid6_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.low_voltage_max_phyclk = bw_int_to_fixed(540);
-+ vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.high_voltage_max_phyclk = bw_int_to_fixed(810);
-+ 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.stutter_self_refresh_entry_latency = bw_int_to_fixed(0);
-+ 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.large_cursor = false;
-+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
-+ dceip.dmif_pipe_en_fbc_chunk_tracker = false;
-+ dceip.cursor_max_outstanding_group_num = 1;
-+ dceip.lines_interleaved_into_lb = 2;
-+ dceip.chunk_width = 256;
-+ dceip.number_of_graphics_pipes = 3;
-+ dceip.number_of_underlay_pipes = 1;
-+ dceip.low_power_tiling_mode = 0;
-+ 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.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(105, 100);
-+ 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*/
-+ break;
-+ case BW_CALCS_VERSION_POLARIS10:
-+ vbios.memory_type = bw_def_gddr5;
-+ vbios.dram_channel_width_in_bits = 32;
-+ vbios.number_of_dram_channels = 8;
-+ vbios.number_of_dram_banks = 8;
-+ vbios.high_yclk = bw_int_to_fixed(6000);
-+ vbios.mid_yclk = bw_int_to_fixed(3200);
-+ vbios.low_yclk = bw_int_to_fixed(1000);
-+ vbios.low_sclk = bw_int_to_fixed(300);
-+ vbios.mid1_sclk = bw_int_to_fixed(400);
-+ vbios.mid2_sclk = bw_int_to_fixed(500);
-+ vbios.mid3_sclk = bw_int_to_fixed(600);
-+ vbios.mid4_sclk = bw_int_to_fixed(700);
-+ vbios.mid5_sclk = bw_int_to_fixed(800);
-+ vbios.mid6_sclk = bw_int_to_fixed(974);
-+ vbios.high_sclk = bw_int_to_fixed(1154);
-+ vbios.low_voltage_max_dispclk = bw_int_to_fixed(459);
-+ vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654);
-+ vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108);
-+ vbios.low_voltage_max_phyclk = bw_int_to_fixed(540);
-+ vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.high_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.data_return_bus_width = bw_int_to_fixed(32);
-+ vbios.trc = bw_int_to_fixed(48);
-+ vbios.dmifmc_urgent_latency = bw_int_to_fixed(3);
-+ vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5);
-+ vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0);
-+ vbios.nbp_state_change_latency = bw_int_to_fixed(45);
-+ 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(0); /* us */
-+ vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
-+
-+ dceip.large_cursor = false;
-+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
-+ dceip.dmif_pipe_en_fbc_chunk_tracker = false;
-+ dceip.cursor_max_outstanding_group_num = 1;
-+ dceip.lines_interleaved_into_lb = 2;
-+ dceip.chunk_width = 256;
-+ dceip.number_of_graphics_pipes = 6;
-+ dceip.number_of_underlay_pipes = 0;
-+ dceip.low_power_tiling_mode = 0;
-+ dceip.display_write_back_supported = false;
-+ dceip.argb_compression_support = true;
-+ 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 = 4;
-+ 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(245952);
-+ dceip.graphics_lb_nodownscaling_multi_line_prefetching = true;
-+ dceip.stutter_and_dram_clock_state_change_gated_before_cursor =
-+ bw_int_to_fixed(1);
-+ 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.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(105, 100);
-+ 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);
-+ break;
-+ case BW_CALCS_VERSION_POLARIS11:
-+ vbios.memory_type = bw_def_gddr5;
-+ vbios.dram_channel_width_in_bits = 32;
-+ vbios.number_of_dram_channels = 4;
-+ vbios.number_of_dram_banks = 8;
-+ vbios.high_yclk = bw_int_to_fixed(6000);
-+ vbios.mid_yclk = bw_int_to_fixed(3200);
-+ vbios.low_yclk = bw_int_to_fixed(1000);
-+ vbios.low_sclk = bw_int_to_fixed(300);
-+ vbios.mid1_sclk = bw_int_to_fixed(400);
-+ vbios.mid2_sclk = bw_int_to_fixed(500);
-+ vbios.mid3_sclk = bw_int_to_fixed(600);
-+ vbios.mid4_sclk = bw_int_to_fixed(700);
-+ vbios.mid5_sclk = bw_int_to_fixed(800);
-+ vbios.mid6_sclk = bw_int_to_fixed(974);
-+ vbios.high_sclk = bw_int_to_fixed(1154);
-+ vbios.low_voltage_max_dispclk = bw_int_to_fixed(459);
-+ vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654);
-+ vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108);
-+ vbios.low_voltage_max_phyclk = bw_int_to_fixed(540);
-+ vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.high_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.data_return_bus_width = bw_int_to_fixed(32);
-+ vbios.trc = bw_int_to_fixed(48);
-+ vbios.dmifmc_urgent_latency = bw_int_to_fixed(3);
-+ vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5);
-+ vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0);
-+ vbios.nbp_state_change_latency = bw_int_to_fixed(45);
-+ 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(0); /* us */
-+ vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0);
-+
-+ dceip.large_cursor = false;
-+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
-+ dceip.dmif_pipe_en_fbc_chunk_tracker = false;
-+ dceip.cursor_max_outstanding_group_num = 1;
-+ dceip.lines_interleaved_into_lb = 2;
-+ dceip.chunk_width = 256;
-+ dceip.number_of_graphics_pipes = 5;
-+ dceip.number_of_underlay_pipes = 0;
-+ dceip.low_power_tiling_mode = 0;
-+ dceip.display_write_back_supported = false;
-+ dceip.argb_compression_support = true;
-+ 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 = 4;
-+ 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(245952);
-+ dceip.graphics_lb_nodownscaling_multi_line_prefetching = true;
-+ dceip.stutter_and_dram_clock_state_change_gated_before_cursor =
-+ bw_int_to_fixed(1);
-+ 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.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(105, 100);
-+ 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);
-+ break;
-+ case BW_CALCS_VERSION_STONEY:
-+ vbios.memory_type = bw_def_gddr5;
-+ vbios.dram_channel_width_in_bits = 64;
-+ vbios.number_of_dram_channels = 1;
-+ vbios.number_of_dram_banks = 8;
-+ vbios.high_yclk = bw_int_to_fixed(1866);
-+ vbios.mid_yclk = bw_int_to_fixed(1866);
-+ vbios.low_yclk = bw_int_to_fixed(1333);
-+ vbios.low_sclk = bw_int_to_fixed(200);
-+ vbios.mid1_sclk = bw_int_to_fixed(600);
-+ vbios.mid2_sclk = bw_int_to_fixed(600);
-+ vbios.mid3_sclk = bw_int_to_fixed(600);
-+ vbios.mid4_sclk = bw_int_to_fixed(600);
-+ vbios.mid5_sclk = bw_int_to_fixed(600);
-+ vbios.mid6_sclk = bw_int_to_fixed(600);
-+ vbios.high_sclk = bw_int_to_fixed(800);
-+ 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.low_voltage_max_phyclk = bw_int_to_fixed(540);
-+ vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810);
-+ vbios.high_voltage_max_phyclk = bw_int_to_fixed(810);
-+ 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(158, 10);
-+ vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0);
-+ vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100);
-+ 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.large_cursor = false;
-+ dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
-+ dceip.dmif_pipe_en_fbc_chunk_tracker = false;
-+ dceip.cursor_max_outstanding_group_num = 1;
-+ dceip.lines_interleaved_into_lb = 2;
-+ dceip.chunk_width = 256;
-+ dceip.number_of_graphics_pipes = 2;
-+ dceip.number_of_underlay_pipes = 1;
-+ dceip.low_power_tiling_mode = 0;
-+ dceip.display_write_back_supported = false;
-+ dceip.argb_compression_support = true;
-+ 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.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(105, 100);
-+ 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);
-+ break;
-+ default:
-+ break;
-+ }
-+ *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;
-+}
-+
-+static void populate_initial_data(
-+ const struct pipe_ctx pipe[], int pipe_count, struct bw_calcs_data *data)
-+{
-+ int i, j;
-+ int num_displays = 0;
-+
-+ data->underlay_surface_type = bw_def_420;
-+ data->panning_and_bezel_adjustment = bw_def_none;
-+ data->graphics_lb_bpc = 10;
-+ data->underlay_lb_bpc = 8;
-+ data->underlay_tiling_mode = bw_def_tiled;
-+ data->graphics_tiling_mode = bw_def_tiled;
-+ data->underlay_micro_tile_mode = bw_def_display_micro_tiling;
-+ data->graphics_micro_tile_mode = bw_def_display_micro_tiling;
-+
-+ /* Pipes with underlay first */
-+ for (i = 0; i < pipe_count; i++) {
-+ if (!pipe[i].stream || !pipe[i].bottom_pipe)
-+ continue;
-+
-+ ASSERT(pipe[i].surface);
-+
-+ if (num_displays == 0) {
-+ if (!pipe[i].surface->public.visible)
-+ data->d0_underlay_mode = bw_def_underlay_only;
-+ else
-+ data->d0_underlay_mode = bw_def_blend;
-+ } else {
-+ if (!pipe[i].surface->public.visible)
-+ data->d1_underlay_mode = bw_def_underlay_only;
-+ else
-+ data->d1_underlay_mode = bw_def_blend;
-+ }
-+
-+ data->fbc_en[num_displays + 4] = false;
-+ data->lpt_en[num_displays + 4] = false;
-+ data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total);
-+ data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total);
-+ data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000);
-+ data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width);
-+ data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch);
-+ data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height);
-+ data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps);
-+ data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps);
-+ data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value);
-+ data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value);
-+ switch (pipe[i].surface->public.rotation) {
-+ case ROTATION_ANGLE_0:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0);
-+ break;
-+ case ROTATION_ANGLE_90:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90);
-+ break;
-+ case ROTATION_ANGLE_180:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180);
-+ break;
-+ case ROTATION_ANGLE_270:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270);
-+ break;
-+ default:
-+ break;
-+ }
-+ switch (pipe[i].surface->public.format) {
-+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
-+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
-+ data->bytes_per_pixel[num_displays + 4] = 2;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
-+ data->bytes_per_pixel[num_displays + 4] = 4;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
-+ data->bytes_per_pixel[num_displays + 4] = 8;
-+ break;
-+ default:
-+ data->bytes_per_pixel[num_displays + 4] = 4;
-+ break;
-+ }
-+ data->interlace_mode[num_displays + 4] = false;
-+ data->stereo_mode[num_displays + 4] = bw_def_mono;
-+
-+
-+ for (j = 0; j < 2; j++) {
-+ data->fbc_en[num_displays * 2 + j] = false;
-+ data->lpt_en[num_displays * 2 + j] = false;
-+
-+ data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height);
-+ data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width);
-+ data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed(
-+ pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch);
-+ data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps);
-+ data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps);
-+ data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed(
-+ pipe[i].bottom_pipe->scl_data.ratios.horz.value);
-+ data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed(
-+ pipe[i].bottom_pipe->scl_data.ratios.vert.value);
-+ switch (pipe[i].bottom_pipe->surface->public.rotation) {
-+ case ROTATION_ANGLE_0:
-+ data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0);
-+ break;
-+ case ROTATION_ANGLE_90:
-+ data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(90);
-+ break;
-+ case ROTATION_ANGLE_180:
-+ data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(180);
-+ break;
-+ case ROTATION_ANGLE_270:
-+ data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(270);
-+ break;
-+ default:
-+ break;
-+ }
-+ data->stereo_mode[num_displays * 2 + j] = bw_def_mono;
-+ }
-+
-+ num_displays++;
-+ }
-+
-+ /* Pipes without underlay after */
-+ for (i = 0; i < pipe_count; i++) {
-+ if (!pipe[i].stream || pipe[i].bottom_pipe)
-+ continue;
-+
-+
-+ data->fbc_en[num_displays + 4] = false;
-+ data->lpt_en[num_displays + 4] = false;
-+ data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total);
-+ data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total);
-+ data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000);
-+ if (pipe[i].surface) {
-+ data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width);
-+ data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch);
-+ data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height);
-+ data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps);
-+ data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps);
-+ data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value);
-+ data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value);
-+ switch (pipe[i].surface->public.rotation) {
-+ case ROTATION_ANGLE_0:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0);
-+ break;
-+ case ROTATION_ANGLE_90:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90);
-+ break;
-+ case ROTATION_ANGLE_180:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180);
-+ break;
-+ case ROTATION_ANGLE_270:
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270);
-+ break;
-+ default:
-+ break;
-+ }
-+ switch (pipe[i].surface->public.format) {
-+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
-+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
-+ data->bytes_per_pixel[num_displays + 4] = 2;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
-+ data->bytes_per_pixel[num_displays + 4] = 4;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
-+ data->bytes_per_pixel[num_displays + 4] = 8;
-+ break;
-+ default:
-+ data->bytes_per_pixel[num_displays + 4] = 4;
-+ break;
-+ }
-+ } else {
-+ data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable);
-+ data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4];
-+ data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable);
-+ data->h_taps[num_displays + 4] = bw_int_to_fixed(1);
-+ data->v_taps[num_displays + 4] = bw_int_to_fixed(1);
-+ data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1);
-+ data->v_scale_ratio[num_displays + 4] = bw_int_to_fixed(1);
-+ data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0);
-+ data->bytes_per_pixel[num_displays + 4] = 4;
-+ }
-+
-+ data->interlace_mode[num_displays + 4] = false;
-+ data->stereo_mode[num_displays + 4] = bw_def_mono;
-+ num_displays++;
-+ }
-+
-+ data->number_of_displays = num_displays;
-+}
-+
-+/**
-+ * 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 pipe_ctx pipe[],
-+ int pipe_count,
-+ struct bw_calcs_output *calcs_output)
-+{
-+ struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data));
-+
-+ populate_initial_data(pipe, pipe_count, data);
-+
-+ /*TODO: this should be taken out calcs output and assigned during timing sync for pplib use*/
-+ calcs_output->all_displays_in_sync = false;
-+
-+ if (data->number_of_displays != 0) {
-+ uint8_t yclk_lvl, sclk_lvl;
-+ struct bw_fixed high_sclk = vbios->high_sclk;
-+ struct bw_fixed mid1_sclk = vbios->mid1_sclk;
-+ struct bw_fixed mid2_sclk = vbios->mid2_sclk;
-+ struct bw_fixed mid3_sclk = vbios->mid3_sclk;
-+ struct bw_fixed mid4_sclk = vbios->mid4_sclk;
-+ struct bw_fixed mid5_sclk = vbios->mid5_sclk;
-+ struct bw_fixed mid6_sclk = vbios->mid6_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, data);
-+
-+ yclk_lvl = data->y_clk_level;
-+ sclk_lvl = data->sclk_level;
-+
-+ calcs_output->nbp_state_change_enable =
-+ data->nbp_state_change_enable;
-+ calcs_output->cpuc_state_change_enable =
-+ data->cpuc_state_change_enable;
-+ calcs_output->cpup_state_change_enable =
-+ data->cpup_state_change_enable;
-+ calcs_output->stutter_mode_enable =
-+ data->stutter_mode_enable;
-+ calcs_output->dispclk_khz =
-+ bw_fixed_to_int(bw_mul(data->dispclk,
-+ bw_int_to_fixed(1000)));
-+ calcs_output->blackout_recovery_time_us =
-+ bw_fixed_to_int(data->blackout_recovery_time);
-+ calcs_output->required_sclk =
-+ bw_fixed_to_int(bw_mul(data->required_sclk,
-+ bw_int_to_fixed(1000)));
-+ calcs_output->required_sclk_deep_sleep =
-+ bw_fixed_to_int(bw_mul(data->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].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ 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(data->
-+ 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(data->
-+ nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
-+
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->nbp_state_change_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->nbp_state_change_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->nbp_state_change_wm_ns[5].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+
-+ calcs_output->stutter_exit_wm_ns[0].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[1].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[2].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->stutter_exit_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->stutter_exit_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->stutter_exit_wm_ns[5].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+
-+ calcs_output->urgent_wm_ns[0].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[1].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[2].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->urgent_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->urgent_wm_ns[3].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->urgent_wm_ns[5].a_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[9], bw_int_to_fixed(1000)));
-+
-+ if (dceip->version != BW_CALCS_VERSION_CARRIZO) {
-+ ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk;
-+ calculate_bandwidth(dceip, vbios, data);
-+
-+ calcs_output->nbp_state_change_wm_ns[0].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ 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(data->
-+ 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(data->
-+ nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
-+
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->nbp_state_change_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->nbp_state_change_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->nbp_state_change_wm_ns[5].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+
-+ calcs_output->stutter_exit_wm_ns[0].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[1].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[2].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->stutter_exit_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->stutter_exit_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->stutter_exit_wm_ns[5].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+
-+ calcs_output->urgent_wm_ns[0].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[1].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[2].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->urgent_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->urgent_wm_ns[3].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->urgent_wm_ns[5].b_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[9], bw_int_to_fixed(1000)));
-+
-+ ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk;
-+ calculate_bandwidth(dceip, vbios, data);
-+
-+ calcs_output->nbp_state_change_wm_ns[0].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[1].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[2].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->nbp_state_change_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->nbp_state_change_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->nbp_state_change_wm_ns[5].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+ calcs_output->stutter_exit_wm_ns[0].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[1].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[2].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->stutter_exit_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->stutter_exit_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->stutter_exit_wm_ns[5].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[9], bw_int_to_fixed(1000)));
-+
-+ calcs_output->urgent_wm_ns[0].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[1].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[2].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->urgent_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->urgent_wm_ns[3].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->urgent_wm_ns[5].c_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[9], bw_int_to_fixed(1000)));
-+ }
-+
-+ if (dceip->version == BW_CALCS_VERSION_CARRIZO) {
-+ ((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)->mid1_sclk = high_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid2_sclk = high_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid3_sclk = high_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid4_sclk = high_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid5_sclk = high_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid6_sclk = high_sclk;
-+ } else {
-+ ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk;
-+ ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk;
-+ }
-+
-+ calculate_bandwidth(dceip, vbios, data);
-+
-+ calcs_output->nbp_state_change_wm_ns[0].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[1].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[2].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->nbp_state_change_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->nbp_state_change_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->nbp_state_change_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->nbp_state_change_wm_ns[5].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ nbp_state_change_watermark[9], bw_int_to_fixed(1000)));
-+
-+ calcs_output->stutter_exit_wm_ns[0].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[1].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[2].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->stutter_exit_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->stutter_exit_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->stutter_exit_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->stutter_exit_wm_ns[5].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ stutter_exit_watermark[9], bw_int_to_fixed(1000)));
-+
-+
-+ calcs_output->urgent_wm_ns[0].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[4], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[1].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[5], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[2].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[6], bw_int_to_fixed(1000)));
-+ if (ctx->dc->caps.max_slave_planes) {
-+ calcs_output->urgent_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[0], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[1], bw_int_to_fixed(1000)));
-+ } else {
-+ calcs_output->urgent_wm_ns[3].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[7], bw_int_to_fixed(1000)));
-+ calcs_output->urgent_wm_ns[4].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[8], bw_int_to_fixed(1000)));
-+ }
-+ calcs_output->urgent_wm_ns[5].d_mark =
-+ bw_fixed_to_int(bw_mul(data->
-+ urgent_watermark[9], 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)->mid1_sclk = mid1_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid3_sclk = mid3_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid4_sclk = mid4_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid5_sclk = mid5_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->mid6_sclk = mid6_sclk;
-+ ((struct bw_calcs_vbios *)vbios)->high_sclk = high_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(data);
-+
-+ return is_display_configuration_supported(vbios, calcs_output);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
-new file mode 100644
-index 0000000..fbf2adc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
-@@ -0,0 +1,299 @@
-+/*
-+ * 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 = abs_i64(numerator);
-+ arg2_value = 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/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
-new file mode 100644
-index 0000000..854796a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
-@@ -0,0 +1,1382 @@
-+/*
-+ * 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 "gamma_calcs.h"
-+
-+struct curve_config {
-+ uint32_t offset;
-+ int8_t segments[16];
-+ int8_t begin;
-+};
-+
-+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_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 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 gamma_curve *arr_curve_points,
-+ struct curve_points *arr_points,
-+ uint32_t *hw_points_num,
-+ struct hw_x_point *coordinates_x)
-+{
-+ 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, arr_curve_points,
-+ arr_points,
-+ coordinates_x, hw_points_num)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+ return true;
-+}
-+
-+struct dividers {
-+ struct fixed31_32 divider1;
-+ struct fixed31_32 divider2;
-+ struct fixed31_32 divider3;
-+};
-+
-+static void build_regamma_coefficients(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 };
-+
-+ const int32_t *numerator1;
-+ const int32_t *numerator2;
-+ const int32_t *numerator3;
-+ const int32_t *numerator4;
-+ const int32_t *numerator5;
-+
-+ uint32_t i = 0;
-+
-+ numerator1 = numerator01;
-+ numerator2 = numerator02;
-+ numerator3 = numerator03;
-+ numerator4 = numerator04;
-+ numerator5 = numerator05;
-+
-+ 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(coefficients->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 find_software_points(
-+ const struct gamma_pixel *axis_x_256,
-+ 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 + 3;
-+
-+ struct fixed31_32 left, right;
-+
-+ uint32_t i = *index_to_start;
-+
-+ while (i < max_number) {
-+ if (channel == CHANNEL_NAME_RED) {
-+ left = axis_x_256[i].r;
-+
-+ if (i < max_number - 1)
-+ right = axis_x_256[i + 1].r;
-+ else
-+ right = axis_x_256[max_number - 1].r;
-+ } else if (channel == CHANNEL_NAME_GREEN) {
-+ left = axis_x_256[i].g;
-+
-+ if (i < max_number - 1)
-+ right = axis_x_256[i + 1].g;
-+ else
-+ right = axis_x_256[max_number - 1].g;
-+ } else {
-+ left = axis_x_256[i].b;
-+
-+ if (i < max_number - 1)
-+ right = axis_x_256[i + 1].b;
-+ else
-+ right = 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 build_custom_gamma_mapping_coefficients_worker(
-+ struct pixel_gamma_point *coeff,
-+ const struct hw_x_point *coordinates_x,
-+ const struct gamma_pixel *axis_x_256,
-+ enum channel_name channel,
-+ uint32_t number_of_points,
-+ enum surface_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;
-+
-+ /*
-+ * TODO: confirm enum in surface_pixel_format
-+ * if (pixel_format == PIXEL_FORMAT_FP16)
-+ *coord_x = coordinates_x[i].adjusted_x;
-+ *else
-+ */
-+ if (channel == CHANNEL_NAME_RED)
-+ coord_x = coordinates_x[i].regamma_y_red;
-+ else if (channel == CHANNEL_NAME_GREEN)
-+ coord_x = coordinates_x[i].regamma_y_green;
-+ else
-+ coord_x = coordinates_x[i].regamma_y_blue;
-+
-+ if (!find_software_points(
-+ axis_x_256, coord_x, channel,
-+ &index_to_start, &index_left, &index_right, &hw_pos)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (index_left >= RGB_256X3X16 + 3) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (index_right >= RGB_256X3X16 + 3) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (channel == CHANNEL_NAME_RED) {
-+ point = &coeff[i].r;
-+
-+ left_pos = axis_x_256[index_left].r;
-+ right_pos = axis_x_256[index_right].r;
-+ } else if (channel == CHANNEL_NAME_GREEN) {
-+ point = &coeff[i].g;
-+
-+ left_pos = axis_x_256[index_left].g;
-+ right_pos = axis_x_256[index_right].g;
-+ } else {
-+ point = &coeff[i].b;
-+
-+ left_pos = axis_x_256[index_left].b;
-+ right_pos = 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 = dal_fixed31_32_zero;
-+ else if (hw_pos == HW_POINT_POSITION_RIGHT)
-+ point->coeff = dal_fixed31_32_from_int(2);
-+ 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_oem_custom_gamma_mapping_coefficients(
-+ struct pixel_gamma_point *coeff128_oem,
-+ const struct hw_x_point *coordinates_x,
-+ const struct gamma_pixel *axis_x_256,
-+ uint32_t number_of_points,
-+ enum surface_pixel_format pixel_format)
-+{
-+ int i;
-+
-+ for (i = 0; i < 3; i++) {
-+ if (!build_custom_gamma_mapping_coefficients_worker(
-+ coeff128_oem, coordinates_x, axis_x_256, i,
-+ number_of_points, pixel_format))
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static struct fixed31_32 calculate_mapped_value(
-+ 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 = dal_fixed31_32_zero;
-+ } else {
-+ BREAK_TO_DEBUGGER();
-+ result = dal_fixed31_32_one;
-+ }
-+
-+ return result;
-+}
-+
-+static inline struct fixed31_32 calculate_oem_mapped_value(
-+ struct pwl_float_data *rgb_oem,
-+ const struct pixel_gamma_point *coeff,
-+ uint32_t index,
-+ enum channel_name channel,
-+ uint32_t max_index)
-+{
-+ return calculate_mapped_value(
-+ rgb_oem,
-+ coeff + index,
-+ channel,
-+ max_index);
-+}
-+
-+static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma,
-+ struct pwl_float_data *rgb_oem,
-+ struct pixel_gamma_point *coeff128_oem,
-+ const struct core_gamma *ramp,
-+ const struct core_surface *surface,
-+ uint32_t hw_points_num,
-+ const struct hw_x_point *coordinate_x,
-+ const struct gamma_pixel *axis_x,
-+ struct dividers dividers)
-+{
-+ uint32_t i;
-+
-+ struct gamma_coefficients coeff;
-+ struct pwl_float_data_ex *rgb = rgb_regamma;
-+ const struct hw_x_point *coord_x = coordinate_x;
-+
-+ build_regamma_coefficients(&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 != 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;
-+ }
-+}
-+
-+static bool scale_gamma(struct pwl_float_data *pwl_rgb,
-+ const struct core_gamma *ramp,
-+ struct dividers dividers)
-+{
-+ const struct dc_gamma_ramp_rgb256x3x16 *gamma;
-+ const uint16_t max_driver = 0xFFFF;
-+ const uint16_t max_os = 0xFF00;
-+ uint16_t scaler = max_os;
-+ uint32_t i;
-+ struct pwl_float_data *rgb = pwl_rgb;
-+ struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
-+
-+ if (ramp->public.type == GAMMA_RAMP_RBG256X3X16)
-+ gamma = &ramp->public.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;
-+
-+ 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,
-+ dividers.divider1);
-+ rgb->g = dal_fixed31_32_mul(rgb_last->g,
-+ dividers.divider1);
-+ rgb->b = dal_fixed31_32_mul(rgb_last->b,
-+ dividers.divider1);
-+
-+ ++rgb;
-+
-+ rgb->r = dal_fixed31_32_mul(rgb_last->r,
-+ dividers.divider2);
-+ rgb->g = dal_fixed31_32_mul(rgb_last->g,
-+ dividers.divider2);
-+ rgb->b = dal_fixed31_32_mul(rgb_last->b,
-+ dividers.divider2);
-+
-+ ++rgb;
-+
-+ rgb->r = dal_fixed31_32_mul(rgb_last->r,
-+ dividers.divider3);
-+ rgb->g = dal_fixed31_32_mul(rgb_last->g,
-+ dividers.divider3);
-+ rgb->b = dal_fixed31_32_mul(rgb_last->b,
-+ dividers.divider3);
-+
-+ return true;
-+}
-+
-+static void build_evenly_distributed_points(
-+ struct gamma_pixel *points,
-+ uint32_t numberof_points,
-+ struct fixed31_32 max_value,
-+ struct dividers dividers)
-+{
-+ 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, dividers.divider1);
-+ p->g = dal_fixed31_32_div(p_last->g, dividers.divider1);
-+ p->b = dal_fixed31_32_div(p_last->b, dividers.divider1);
-+
-+ ++p;
-+
-+ p->r = dal_fixed31_32_div(p_last->r, dividers.divider2);
-+ p->g = dal_fixed31_32_div(p_last->g, dividers.divider2);
-+ p->b = dal_fixed31_32_div(p_last->b, dividers.divider2);
-+
-+ ++p;
-+
-+ p->r = dal_fixed31_32_div(p_last->r, dividers.divider3);
-+ p->g = dal_fixed31_32_div(p_last->g, dividers.divider3);
-+ p->b = dal_fixed31_32_div(p_last->b, dividers.divider3);
-+}
-+
-+static inline void copy_rgb_regamma_to_coordinates_x(
-+ struct hw_x_point *coordinates_x,
-+ uint32_t hw_points_num,
-+ const struct pwl_float_data_ex *rgb_ex)
-+{
-+ struct hw_x_point *coords = coordinates_x;
-+ uint32_t i = 0;
-+ const struct pwl_float_data_ex *rgb_regamma = rgb_ex;
-+
-+ while (i <= 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 pwl_result_data *rgb,
-+ struct pixel_gamma_point *coeff128,
-+ struct pwl_float_data *rgb_user,
-+ const struct hw_x_point *coordinates_x,
-+ const struct gamma_pixel *axis_x_256,
-+ uint32_t number_of_points,
-+ enum surface_pixel_format pixel_format)
-+{
-+
-+ const struct pixel_gamma_point *coeff;
-+ struct pixel_gamma_point *coeff_128 = coeff128;
-+ uint32_t max_entries = 3 - 1;
-+ struct pwl_result_data *rgb_resulted = rgb;
-+
-+ uint32_t i = 0;
-+
-+ if (!build_oem_custom_gamma_mapping_coefficients(
-+ coeff_128, coordinates_x, axis_x_256,
-+ number_of_points,
-+ pixel_format))
-+ return false;
-+
-+ coeff = coeff128;
-+ max_entries += RGB_256X3X16;
-+
-+ /* TODO: float point case */
-+
-+ while (i <= number_of_points) {
-+ rgb_resulted->red = calculate_mapped_value(
-+ rgb_user, coeff, CHANNEL_NAME_RED, max_entries);
-+ rgb_resulted->green = calculate_mapped_value(
-+ rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries);
-+ rgb_resulted->blue = calculate_mapped_value(
-+ rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries);
-+
-+ ++coeff;
-+ ++rgb_resulted;
-+ ++i;
-+ }
-+
-+ return true;
-+}
-+
-+static bool map_regamma_hw_to_x_user(
-+ struct pixel_gamma_point *coeff128,
-+ struct pwl_float_data *rgb_oem,
-+ struct pwl_result_data *rgb_resulted,
-+ struct pwl_float_data *rgb_user,
-+ struct hw_x_point *coords_x,
-+ const struct gamma_pixel *axis_x,
-+ const struct dc_gamma *gamma,
-+ const struct pwl_float_data_ex *rgb_regamma,
-+ struct dividers dividers,
-+ uint32_t hw_points_num,
-+ const struct core_surface *surface)
-+{
-+ /* setup to spare calculated ideal regamma values */
-+
-+ struct pixel_gamma_point *coeff = coeff128;
-+
-+ struct hw_x_point *coords = coords_x;
-+
-+ copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma);
-+
-+ return calculate_interpolated_hardware_curve(
-+ rgb_resulted, coeff, rgb_user, coords, axis_x,
-+ hw_points_num, surface->public.format);
-+}
-+
-+static void build_new_custom_resulted_curve(
-+ struct pwl_result_data *rgb_resulted,
-+ uint32_t hw_points_num)
-+{
-+ struct pwl_result_data *rgb = rgb_resulted;
-+ struct pwl_result_data *rgb_plus_1 = rgb + 1;
-+
-+ uint32_t i;
-+
-+ i = 0;
-+
-+ while (i != hw_points_num + 1) {
-+ rgb->red = dal_fixed31_32_clamp(
-+ rgb->red, dal_fixed31_32_zero,
-+ dal_fixed31_32_one);
-+ rgb->green = dal_fixed31_32_clamp(
-+ rgb->green, dal_fixed31_32_zero,
-+ dal_fixed31_32_one);
-+ rgb->blue = dal_fixed31_32_clamp(
-+ rgb->blue, dal_fixed31_32_zero,
-+ dal_fixed31_32_one);
-+
-+ ++rgb;
-+ ++i;
-+ }
-+
-+ rgb = rgb_resulted;
-+
-+ i = 1;
-+
-+ while (i != 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 void rebuild_curve_configuration_magic(
-+ struct curve_points *arr_points,
-+ struct pwl_result_data *rgb_resulted,
-+ const struct hw_x_point *coordinates_x,
-+ uint32_t hw_points_num)
-+{
-+ 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 = rgb_resulted[0].red;
-+ y_g = rgb_resulted[0].green;
-+ y_b = rgb_resulted[0].blue;
-+
-+ y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
-+
-+ arr_points[0].x = coordinates_x[0].adjusted_x;
-+ arr_points[0].y = y1_min;
-+ arr_points[0].slope = dal_fixed31_32_div(
-+ arr_points[0].y,
-+ arr_points[0].x);
-+
-+ arr_points[1].x = dal_fixed31_32_add(
-+ coordinates_x[hw_points_num - 1].adjusted_x,
-+ magic_number);
-+
-+ arr_points[2].x = arr_points[1].x;
-+
-+ y_r = rgb_resulted[hw_points_num - 1].red;
-+ y_g = rgb_resulted[hw_points_num - 1].green;
-+ y_b = rgb_resulted[hw_points_num - 1].blue;
-+
-+ y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
-+
-+ arr_points[1].y = y2_max;
-+
-+ y_r = rgb_resulted[hw_points_num].red;
-+ y_g = rgb_resulted[hw_points_num].green;
-+ y_b = rgb_resulted[hw_points_num].blue;
-+
-+ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
-+
-+ arr_points[2].y = y3_max;
-+
-+ arr_points[2].slope = dal_fixed31_32_one;
-+}
-+
-+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(
-+ struct pwl_result_data *rgb_resulted,
-+ struct curve_points *arr_points,
-+ uint32_t hw_points_num)
-+{
-+ struct custom_float_format fmt;
-+
-+ struct pwl_result_data *rgb = rgb_resulted;
-+
-+ uint32_t i = 0;
-+
-+ fmt.exponenta_bits = 6;
-+ fmt.mantissa_bits = 12;
-+ fmt.sign = true;
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[0].x,
-+ &fmt,
-+ &arr_points[0].custom_float_x)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[0].offset,
-+ &fmt,
-+ &arr_points[0].custom_float_offset)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[0].slope,
-+ &fmt,
-+ &arr_points[0].custom_float_slope)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ fmt.mantissa_bits = 10;
-+ fmt.sign = false;
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[1].x,
-+ &fmt,
-+ &arr_points[1].custom_float_x)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[1].y,
-+ &fmt,
-+ &arr_points[1].custom_float_y)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ if (!convert_to_custom_float_format(
-+ arr_points[2].slope,
-+ &fmt,
-+ &arr_points[2].custom_float_slope)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ fmt.mantissa_bits = 12;
-+ fmt.sign = true;
-+
-+ while (i != 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;
-+}
-+
-+bool calculate_regamma_params(struct pwl_params *params,
-+ const struct core_gamma *ramp,
-+ const struct core_surface *surface)
-+{
-+ struct gamma_curve *arr_curve_points = params->arr_curve_points;
-+ struct curve_points *arr_points = params->arr_points;
-+ struct pwl_result_data *rgb_resulted = params->rgb_resulted;
-+ struct dividers dividers;
-+
-+ struct hw_x_point *coordinates_x = NULL;
-+ struct pwl_float_data *rgb_user = NULL ;
-+ struct pwl_float_data_ex *rgb_regamma = NULL;
-+ struct pwl_float_data *rgb_oem = NULL;
-+ struct gamma_pixel *axix_x_256 = NULL;
-+ struct pixel_gamma_point *coeff128_oem = NULL;
-+ struct pixel_gamma_point *coeff128 = NULL;
-+
-+
-+ bool ret = false;
-+
-+ coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
-+ if (!coordinates_x)
-+ goto coordinates_x_alloc_fail;
-+ rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3));
-+ if (!rgb_user)
-+ goto rgb_user_alloc_fail;
-+ rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
-+ if (!rgb_regamma)
-+ goto rgb_regamma_alloc_fail;
-+ rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3));
-+ if (!rgb_oem)
-+ goto rgb_oem_alloc_fail;
-+ axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
-+ if (!axix_x_256)
-+ goto axix_x_256_alloc_fail;
-+ coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3));
-+ if (!coeff128_oem)
-+ goto coeff128_oem_alloc_fail;
-+ coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3));
-+ if (!coeff128)
-+ goto coeff128_alloc_fail;
-+
-+ dividers.divider1 = dal_fixed31_32_from_fraction(3, 2);
-+ dividers.divider2 = dal_fixed31_32_from_int(2);
-+ dividers.divider3 = dal_fixed31_32_from_fraction(5, 2);
-+
-+ build_evenly_distributed_points(
-+ axix_x_256,
-+ 256,
-+ dal_fixed31_32_one,
-+ dividers);
-+
-+ scale_gamma(rgb_user, ramp, dividers);
-+
-+ setup_distribution_points(arr_curve_points, arr_points,
-+ &params->hw_points_num, coordinates_x);
-+
-+ build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem,
-+ ramp, surface, params->hw_points_num,
-+ coordinates_x, axix_x_256, dividers);
-+
-+ map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user,
-+ coordinates_x, axix_x_256, &ramp->public, rgb_regamma,
-+ dividers, params->hw_points_num, surface);
-+
-+ build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num);
-+
-+ rebuild_curve_configuration_magic(
-+ arr_points,
-+ rgb_resulted,
-+ coordinates_x,
-+ params->hw_points_num);
-+
-+ convert_to_custom_float(rgb_resulted, arr_points,
-+ params->hw_points_num);
-+
-+ ret = true;
-+
-+ dm_free(coeff128);
-+coeff128_alloc_fail:
-+ dm_free(coeff128_oem);
-+coeff128_oem_alloc_fail:
-+ dm_free(axix_x_256);
-+axix_x_256_alloc_fail:
-+ dm_free(rgb_oem);
-+rgb_oem_alloc_fail:
-+ dm_free(rgb_regamma);
-+rgb_regamma_alloc_fail:
-+ dm_free(rgb_user);
-+rgb_user_alloc_fail:
-+ dm_free(coordinates_x);
-+coordinates_x_alloc_fail:
-+ return ret;
-+
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
-new file mode 100644
-index 0000000..f7638f8
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
-@@ -0,0 +1,1846 @@
-+/*
-+ * 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 "clock_source.h"
-+#include "dc_bios_types.h"
-+
-+#include "bandwidth_calcs.h"
-+#include "bios_parser_interface.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"
-+#include "dm_helpers.h"
-+#include "mem_input.h"
-+
-+/*******************************************************************************
-+ * Private structures
-+ ******************************************************************************/
-+
-+struct dc_target_sync_report {
-+ uint32_t h_count;
-+ uint32_t v_count;
-+};
-+
-+/*******************************************************************************
-+ * Private functions
-+ ******************************************************************************/
-+static void destroy_links(struct core_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 core_dc *dc,
-+ uint32_t num_virtual_links)
-+{
-+ int i;
-+ int connectors_num;
-+ struct dc_bios *bios = dc->ctx->dc_bios;
-+
-+ dc->link_count = 0;
-+
-+ connectors_num = bios->funcs->get_connectors_number(bios);
-+
-+ 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 && num_virtual_links == 0) {
-+ dm_error("DC: Number of connectors is zero!\n");
-+ }
-+
-+ dm_output_to_console(
-+ "DC: %s: connectors_num: physical:%d, virtual:%d\n",
-+ __func__,
-+ connectors_num,
-+ 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 = dc->ctx;
-+ 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 < num_virtual_links; i++) {
-+ struct core_link *link = dm_alloc(sizeof(*link));
-+ struct encoder_init_data enc_init = {0};
-+
-+ if (link == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ goto failed_alloc;
-+ }
-+
-+ link->ctx = dc->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(sizeof(*link->link_enc));
-+
-+ enc_init.ctx = dc->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 bool stream_adjust_vmin_vmax(struct dc *dc,
-+ const struct dc_stream **stream, int num_streams,
-+ int vmin, int vmax)
-+{
-+ /* TODO: Support multiple streams */
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
-+ int i = 0;
-+ bool ret = false;
-+ struct pipe_ctx *pipes;
-+ unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == core_stream
-+ && i != underlay_idx) {
-+
-+ pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-+ core_dc->hwss.set_drr(&pipes, 1, vmin, vmax);
-+
-+ /* build and update the info frame */
-+ resource_build_info_frame(pipes);
-+ core_dc->hwss.update_info_frame(pipes);
-+
-+ ret = true;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+
-+static bool set_gamut_remap(struct dc *dc,
-+ const struct dc_stream **stream, int num_streams)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
-+ int i = 0;
-+ bool ret = false;
-+ struct pipe_ctx *pipes;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-+ == core_stream) {
-+
-+ pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-+ core_dc->hwss.set_plane_config(core_dc, pipes,
-+ &core_dc->current_context->res_ctx);
-+ ret = true;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+/* This function is not expected to fail, proper implementation of
-+ * validation will prevent this from ever being called for unsupported
-+ * configurations.
-+ */
-+static void stream_update_scaling(
-+ const struct dc *dc,
-+ const struct dc_stream *dc_stream,
-+ const struct rect *src,
-+ const struct rect *dst)
-+{
-+ struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct validate_context *cur_ctx = core_dc->current_context;
-+ int i, j;
-+
-+ if (src)
-+ stream->public.src = *src;
-+
-+ if (dst)
-+ stream->public.dst = *dst;
-+
-+ for (i = 0; i < cur_ctx->target_count; i++) {
-+ struct core_target *target = cur_ctx->targets[i];
-+ struct dc_target_status *status = &cur_ctx->target_status[i];
-+
-+ for (j = 0; j < target->public.stream_count; j++) {
-+ if (target->public.streams[j] != dc_stream)
-+ continue;
-+
-+ if (status->surface_count)
-+ if (!dc_commit_surfaces_to_target(
-+ &core_dc->public,
-+ status->surfaces,
-+ status->surface_count,
-+ &target->public))
-+ /* Need to debug validation */
-+ BREAK_TO_DEBUGGER();
-+
-+ return;
-+ }
-+ }
-+}
-+
-+static bool set_backlight(struct dc *dc, unsigned int backlight_level,
-+ unsigned int frame_ramp, const struct dc_stream *stream)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_set_backlight_level(&core_dc->links[i]->public,
-+ backlight_level, frame_ramp, stream);
-+ }
-+
-+ return true;
-+
-+}
-+
-+static bool init_dmcu_backlight_settings(struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_init_dmcu_backlight_settings
-+ (&core_dc->links[i]->public);
-+
-+ return true;
-+}
-+
-+
-+static bool set_abm_level(struct dc *dc, unsigned int abm_level)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_set_abm_level(&core_dc->links[i]->public,
-+ abm_level);
-+
-+ return true;
-+}
-+
-+static bool set_psr_enable(struct dc *dc, bool enable)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_set_psr_enable(&core_dc->links[i]->public,
-+ enable);
-+
-+ return true;
-+}
-+
-+
-+static bool setup_psr(struct dc *dc, const struct dc_stream *stream)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
-+ struct pipe_ctx *pipes;
-+ int i;
-+ unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
-+
-+ for (i = 0; i < core_dc->link_count; i++) {
-+ if (core_stream->sink->link == core_dc->links[i])
-+ dc_link_setup_psr(&core_dc->links[i]->public,
-+ stream);
-+ }
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-+ == core_stream && i != underlay_idx) {
-+ pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-+ core_dc->hwss.set_static_screen_control(&pipes, 1,
-+ 0x182);
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+static void set_drive_settings(struct dc *dc,
-+ struct link_training_settings *lt_settings)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_dp_set_drive_settings(&core_dc->links[i]->public,
-+ lt_settings);
-+}
-+
-+static void perform_link_training(struct dc *dc,
-+ struct dc_link_settings *link_setting,
-+ bool skip_video_pattern)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ dc_link_dp_perform_link_training(
-+ &core_dc->links[i]->public,
-+ link_setting,
-+ skip_video_pattern);
-+}
-+
-+static void set_preferred_link_settings(struct dc *dc,
-+ struct dc_link_settings *link_setting)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ for (i = 0; i < core_dc->link_count; i++) {
-+ core_dc->links[i]->public.verified_link_cap.lane_count =
-+ link_setting->lane_count;
-+ core_dc->links[i]->public.verified_link_cap.link_rate =
-+ link_setting->link_rate;
-+ }
-+}
-+
-+static void enable_hpd(const struct dc_link *link)
-+{
-+ dc_link_dp_enable_hpd(link);
-+}
-+
-+static void disable_hpd(const struct dc_link *link)
-+{
-+ dc_link_dp_disable_hpd(link);
-+}
-+
-+
-+static void set_test_pattern(
-+ const struct dc_link *link,
-+ enum dp_test_pattern test_pattern,
-+ const struct link_training_settings *p_link_settings,
-+ const unsigned char *p_custom_pattern,
-+ unsigned int cust_pattern_size)
-+{
-+ if (link != NULL)
-+ dc_link_dp_set_test_pattern(
-+ link,
-+ test_pattern,
-+ p_link_settings,
-+ p_custom_pattern,
-+ cust_pattern_size);
-+}
-+
-+static void allocate_dc_stream_funcs(struct core_dc *core_dc)
-+{
-+ core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling;
-+ if (core_dc->hwss.set_drr != NULL) {
-+ core_dc->public.stream_funcs.adjust_vmin_vmax =
-+ stream_adjust_vmin_vmax;
-+ }
-+
-+ core_dc->public.stream_funcs.set_gamut_remap =
-+ set_gamut_remap;
-+
-+ core_dc->public.stream_funcs.set_backlight =
-+ set_backlight;
-+
-+ core_dc->public.stream_funcs.init_dmcu_backlight_settings =
-+ init_dmcu_backlight_settings;
-+
-+ core_dc->public.stream_funcs.set_abm_level =
-+ set_abm_level;
-+
-+ core_dc->public.stream_funcs.set_psr_enable =
-+ set_psr_enable;
-+
-+ core_dc->public.stream_funcs.setup_psr =
-+ setup_psr;
-+
-+ core_dc->public.link_funcs.set_drive_settings =
-+ set_drive_settings;
-+
-+ core_dc->public.link_funcs.perform_link_training =
-+ perform_link_training;
-+
-+ core_dc->public.link_funcs.set_preferred_link_settings =
-+ set_preferred_link_settings;
-+
-+ core_dc->public.link_funcs.enable_hpd =
-+ enable_hpd;
-+
-+ core_dc->public.link_funcs.disable_hpd =
-+ disable_hpd;
-+
-+ core_dc->public.link_funcs.set_test_pattern =
-+ set_test_pattern;
-+}
-+
-+static void destruct(struct core_dc *dc)
-+{
-+ resource_validate_ctx_destruct(dc->current_context);
-+
-+ dm_free(dc->temp_flip_context);
-+ dc->temp_flip_context = NULL;
-+
-+ destroy_links(dc);
-+
-+ dc_destroy_resource_pool(dc);
-+
-+ if (dc->ctx->gpio_service)
-+ dal_gpio_service_destroy(&dc->ctx->gpio_service);
-+
-+ if (dc->ctx->i2caux)
-+ dal_i2caux_destroy(&dc->ctx->i2caux);
-+
-+ if (dc->ctx->created_bios)
-+ dal_bios_parser_destroy(&dc->ctx->dc_bios);
-+
-+ if (dc->ctx->logger)
-+ dal_logger_destroy(&dc->ctx->logger);
-+
-+ dm_free(dc->current_context);
-+ dc->current_context = NULL;
-+
-+ dm_free(dc->ctx);
-+ dc->ctx = NULL;
-+}
-+
-+static bool construct(struct core_dc *dc,
-+ const struct dc_init_data *init_params)
-+{
-+ struct dal_logger *logger;
-+ struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx));
-+ enum dce_version dc_version = DCE_VERSION_UNKNOWN;
-+
-+ if (!dc_ctx) {
-+ dm_error("%s: failed to create ctx\n", __func__);
-+ goto ctx_fail;
-+ }
-+
-+ dc->current_context = dm_alloc(sizeof(*dc->current_context));
-+ dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context));
-+
-+ if (!dc->current_context || !dc->temp_flip_context) {
-+ dm_error("%s: failed to create validate ctx\n", __func__);
-+ goto val_ctx_fail;
-+ }
-+
-+ dc_ctx->cgs_device = init_params->cgs_device;
-+ dc_ctx->driver_context = init_params->driver;
-+ dc_ctx->dc = &dc->public;
-+ dc_ctx->asic_id = init_params->asic_id;
-+
-+ /* Create logger */
-+ logger = dal_logger_create(dc_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_ctx->logger = logger;
-+ dc->ctx = dc_ctx;
-+ dc->ctx->dce_environment = init_params->dce_environment;
-+
-+ dc_version = resource_parse_asic_id(init_params->asic_id);
-+ dc->ctx->dce_version = dc_version;
-+
-+ /* Resource should construct all asic specific resources.
-+ * This should be the only place where we need to parse the asic id
-+ */
-+ if (init_params->vbios_override)
-+ dc_ctx->dc_bios = init_params->vbios_override;
-+ else {
-+ /* Create BIOS parser */
-+ struct bp_init_data bp_init_data;
-+ bp_init_data.ctx = dc_ctx;
-+ bp_init_data.bios = init_params->asic_id.atombios_base_address;
-+
-+ dc_ctx->dc_bios = dal_bios_parser_create(
-+ &bp_init_data, dc_version);
-+
-+ if (!dc_ctx->dc_bios) {
-+ ASSERT_CRITICAL(false);
-+ goto bios_fail;
-+ }
-+
-+ dc_ctx->created_bios = true;
-+ }
-+
-+ /* Create I2C AUX */
-+ dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
-+
-+ if (!dc_ctx->i2caux) {
-+ ASSERT_CRITICAL(false);
-+ goto failed_to_create_i2caux;
-+ }
-+
-+ /* Create GPIO service */
-+ dc_ctx->gpio_service = dal_gpio_service_create(
-+ dc_version,
-+ dc_ctx->dce_environment,
-+ dc_ctx);
-+
-+ if (!dc_ctx->gpio_service) {
-+ ASSERT_CRITICAL(false);
-+ goto gpio_fail;
-+ }
-+
-+ dc->res_pool = dc_create_resource_pool(
-+ dc,
-+ init_params->num_virtual_links,
-+ dc_version,
-+ init_params->asic_id);
-+ if (!dc->res_pool)
-+ goto create_resource_fail;
-+
-+ if (!create_links(dc, init_params->num_virtual_links))
-+ goto create_links_fail;
-+
-+ allocate_dc_stream_funcs(dc);
-+
-+ return true;
-+
-+ /**** error handling here ****/
-+create_links_fail:
-+create_resource_fail:
-+gpio_fail:
-+failed_to_create_i2caux:
-+bios_fail:
-+logger_fail:
-+val_ctx_fail:
-+ctx_fail:
-+ destruct(dc);
-+ return false;
-+}
-+
-+/*
-+void ProgramPixelDurationV(unsigned int pixelClockInKHz )
-+{
-+ fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10;
-+ unsigned int pixDurationInPico = round(pixel_duration);
-+
-+ DPG_PIPE_ARBITRATION_CONTROL1 arb_control;
-+
-+ arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1);
-+ arb_control.bits.PIXEL_DURATION = pixDurationInPico;
-+ WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All);
-+
-+ arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1);
-+ arb_control.bits.PIXEL_DURATION = pixDurationInPico;
-+ WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All);
-+
-+ WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800);
-+ WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11);
-+
-+ WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800);
-+ WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11);
-+}
-+*/
-+
-+/*******************************************************************************
-+ * Public functions
-+ ******************************************************************************/
-+
-+struct dc *dc_create(const struct dc_init_data *init_params)
-+ {
-+ struct core_dc *core_dc = dm_alloc(sizeof(*core_dc));
-+ unsigned int full_pipe_count;
-+
-+ if (NULL == core_dc)
-+ goto alloc_fail;
-+
-+ if (false == construct(core_dc, init_params))
-+ goto construct_fail;
-+
-+ /*TODO: separate HW and SW initialization*/
-+ core_dc->hwss.init_hw(core_dc);
-+
-+ full_pipe_count = core_dc->res_pool->pipe_count;
-+ if (core_dc->res_pool->underlay_pipe_index >= 0)
-+ full_pipe_count--;
-+ core_dc->public.caps.max_targets = dm_min(
-+ full_pipe_count,
-+ core_dc->res_pool->stream_enc_count);
-+
-+ core_dc->public.caps.max_links = core_dc->link_count;
-+ core_dc->public.caps.max_audios = core_dc->res_pool->audio_count;
-+
-+ core_dc->public.config = init_params->flags;
-+
-+ dm_logger_write(core_dc->ctx->logger, LOG_DC,
-+ "Display Core initialized\n");
-+
-+
-+ /* TODO: missing feature to be enabled */
-+ core_dc->public.debug.disable_dfs_bypass = true;
-+
-+ return &core_dc->public;
-+
-+construct_fail:
-+ dm_free(core_dc);
-+
-+alloc_fail:
-+ return NULL;
-+}
-+
-+void dc_destroy(struct dc **dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(*dc);
-+ destruct(core_dc);
-+ dm_free(core_dc);
-+ *dc = NULL;
-+}
-+
-+static bool is_validation_required(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count)
-+{
-+ const struct validate_context *context = dc->current_context;
-+ int i, j;
-+
-+ if (context->target_count != set_count)
-+ return true;
-+
-+ for (i = 0; i < set_count; i++) {
-+
-+ if (set[i].surface_count != context->target_status[i].surface_count)
-+ return true;
-+ if (!is_target_unchanged(DC_TARGET_TO_CORE(set[i].target), context->targets[i]))
-+ return true;
-+
-+ for (j = 0; j < set[i].surface_count; j++) {
-+ struct dc_surface temp_surf = { 0 };
-+
-+ temp_surf = *context->target_status[i].surfaces[j];
-+ temp_surf.clip_rect = set[i].surfaces[j]->clip_rect;
-+ temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x;
-+ temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y;
-+
-+ if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0)
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+bool dc_validate_resources(
-+ const struct dc *dc,
-+ const struct dc_validation_set set[],
-+ uint8_t set_count)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ struct validate_context *context;
-+
-+ if (!is_validation_required(core_dc, set, set_count))
-+ return true;
-+
-+ context = dm_alloc(sizeof(struct validate_context));
-+ if(context == NULL)
-+ goto context_alloc_fail;
-+
-+ result = core_dc->res_pool->funcs->validate_with_context(
-+ core_dc, set, set_count, context);
-+
-+ resource_validate_ctx_destruct(context);
-+ dm_free(context);
-+
-+context_alloc_fail:
-+ if (result != DC_OK) {
-+ dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
-+ "%s:resource validation failed, dc_status:%d\n",
-+ __func__,
-+ result);
-+ }
-+
-+ return (result == DC_OK);
-+
-+}
-+
-+bool dc_validate_guaranteed(
-+ const struct dc *dc,
-+ const struct dc_target *dc_target)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ struct validate_context *context;
-+
-+ context = dm_alloc(sizeof(struct validate_context));
-+ if (context == NULL)
-+ goto context_alloc_fail;
-+
-+ result = core_dc->res_pool->funcs->validate_guaranteed(
-+ core_dc, dc_target, context);
-+
-+ resource_validate_ctx_destruct(context);
-+ dm_free(context);
-+
-+context_alloc_fail:
-+ if (result != DC_OK) {
-+ dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
-+ "%s:guaranteed validation failed, dc_status:%d\n",
-+ __func__,
-+ result);
-+ }
-+
-+ return (result == DC_OK);
-+}
-+
-+static void program_timing_sync(
-+ struct core_dc *core_dc,
-+ struct validate_context *ctx)
-+{
-+ int i, j;
-+ int group_index = 0;
-+ int pipe_count = ctx->res_ctx.pool->pipe_count;
-+ struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
-+
-+ for (i = 0; i < pipe_count; i++) {
-+ if (!ctx->res_ctx.pipe_ctx[i].stream || ctx->res_ctx.pipe_ctx[i].top_pipe)
-+ continue;
-+
-+ unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i];
-+ }
-+
-+ for (i = 0; i < pipe_count; i++) {
-+ int group_size = 1;
-+ struct pipe_ctx *pipe_set[MAX_PIPES];
-+
-+ if (!unsynced_pipes[i])
-+ continue;
-+
-+ pipe_set[0] = unsynced_pipes[i];
-+ unsynced_pipes[i] = NULL;
-+
-+ /* 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 < pipe_count; j++) {
-+ if (!unsynced_pipes[j])
-+ continue;
-+
-+ if (resource_are_streams_timing_synchronizable(
-+ unsynced_pipes[j]->stream,
-+ pipe_set[0]->stream)) {
-+ pipe_set[group_size] = unsynced_pipes[j];
-+ unsynced_pipes[j] = NULL;
-+ group_size++;
-+ }
-+ }
-+
-+ /* set first unblanked pipe as master */
-+ for (j = 0; j < group_size; j++) {
-+ struct pipe_ctx *temp;
-+
-+ if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) {
-+ if (j == 0)
-+ break;
-+
-+ temp = pipe_set[0];
-+ pipe_set[0] = pipe_set[j];
-+ pipe_set[j] = temp;
-+ break;
-+ }
-+ }
-+
-+ /* remove any other unblanked pipes as they have already been synced */
-+ for (j = j + 1; j < group_size; j++) {
-+ if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) {
-+ group_size--;
-+ pipe_set[j] = pipe_set[group_size];
-+ j--;
-+ }
-+ }
-+
-+ if (group_size > 1) {
-+ core_dc->hwss.enable_timing_synchronization(
-+ core_dc, group_index, group_size, pipe_set);
-+ group_index++;
-+ }
-+ }
-+}
-+
-+static bool targets_changed(
-+ struct core_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;
-+}
-+
-+static void fill_display_configs(
-+ const struct validate_context *context,
-+ struct dm_pp_display_configuration *pp_display_cfg)
-+{
-+ uint8_t i, j, k;
-+ 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 dm_pp_single_disp_config *cfg =
-+ &pp_display_cfg->disp_configs[num_cfgs];
-+ const struct pipe_ctx *pipe_ctx = NULL;
-+
-+ for (k = 0; k < MAX_PIPES; k++)
-+ if (stream ==
-+ context->res_ctx.pipe_ctx[k].stream) {
-+ pipe_ctx = &context->res_ctx.pipe_ctx[k];
-+ break;
-+ }
-+
-+ ASSERT(pipe_ctx != NULL);
-+
-+ num_cfgs++;
-+ cfg->signal = pipe_ctx->stream->signal;
-+ cfg->pipe_idx = pipe_ctx->pipe_idx;
-+ 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.lane_count = stream->sink->link->public.cur_link_settings.lane_count;
-+ cfg->link_settings.link_rate = stream->sink->link->public.cur_link_settings.link_rate;
-+ cfg->link_settings.link_spread = stream->sink->link->public.cur_link_settings.link_spread;
-+ cfg->sym_clock = stream->phy_pix_clk;
-+ /* Round v_refresh*/
-+ cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000;
-+ cfg->v_refresh /= stream->public.timing.h_total;
-+ cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2)
-+ / stream->public.timing.v_total;
-+ }
-+ }
-+ pp_display_cfg->display_count = num_cfgs;
-+}
-+
-+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 int determine_sclk_from_bounding_box(
-+ const struct core_dc *dc,
-+ int required_sclk)
-+{
-+ int i;
-+
-+ /*
-+ * Some asics do not give us sclk levels, so we just report the actual
-+ * required sclk
-+ */
-+ if (dc->sclk_lvls.num_levels == 0)
-+ return required_sclk;
-+
-+ for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
-+ if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
-+ return dc->sclk_lvls.clocks_in_khz[i];
-+ }
-+ /*
-+ * even maximum level could not satisfy requirement, this
-+ * is unexpected at this stage, should have been caught at
-+ * validation time
-+ */
-+ ASSERT(0);
-+ return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
-+}
-+
-+void pplib_apply_display_requirements(
-+ struct core_dc *dc,
-+ const struct validate_context *context,
-+ struct dm_pp_display_configuration *pp_display_cfg)
-+{
-+ 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.blackout_recovery_time_us;
-+
-+ pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk
-+ / MEMORY_TYPE_MULTIPLIER;
-+
-+ pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
-+ dc,
-+ 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);
-+ /* TODO: dce11.2*/
-+ 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;
-+ }
-+
-+ if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
-+ struct dm_pp_display_configuration)) != 0)
-+ dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
-+
-+ dc->prev_display_config = *pp_display_cfg;
-+
-+}
-+
-+bool dc_commit_targets(
-+ struct dc *dc,
-+ struct dc_target *targets[],
-+ uint8_t target_count)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct dc_bios *dcb = core_dc->ctx->dc_bios;
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ struct validate_context *context;
-+ struct dc_validation_set set[MAX_TARGETS];
-+ int i, j, k;
-+
-+ if (false == targets_changed(core_dc, targets, target_count))
-+ return DC_OK;
-+
-+ dm_logger_write(core_dc->ctx->logger, LOG_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,
-+ core_dc->ctx->logger,
-+ LOG_DC);
-+
-+ set[i].target = targets[i];
-+ set[i].surface_count = 0;
-+
-+ }
-+
-+ context = dm_alloc(sizeof(struct validate_context));
-+ if (context == NULL)
-+ goto context_alloc_fail;
-+
-+ result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, target_count, context);
-+ if (result != DC_OK){
-+ dm_logger_write(core_dc->ctx->logger, LOG_ERROR,
-+ "%s: Context validation failed! dc_status:%d\n",
-+ __func__,
-+ result);
-+ BREAK_TO_DEBUGGER();
-+ resource_validate_ctx_destruct(context);
-+ goto fail;
-+ }
-+
-+ if (!dcb->funcs->is_accelerated_mode(dcb)) {
-+ core_dc->hwss.enable_accelerated_mode(core_dc);
-+ }
-+
-+ if (result == DC_OK) {
-+ result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
-+ }
-+
-+ program_timing_sync(core_dc, context);
-+
-+ for (i = 0; i < context->target_count; i++) {
-+ struct dc_target *dc_target = &context->targets[i]->public;
-+ struct core_sink *sink = DC_SINK_TO_CORE(dc_target->streams[0]->sink);
-+
-+ for (j = 0; j < context->target_status[i].surface_count; j++) {
-+ const struct dc_surface *dc_surface =
-+ context->target_status[i].surfaces[j];
-+
-+ for (k = 0; k < context->res_ctx.pool->pipe_count; k++) {
-+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k];
-+
-+ if (dc_surface != &pipe->surface->public
-+ || !dc_surface->visible)
-+ continue;
-+
-+ pipe->tg->funcs->set_blank(pipe->tg, false);
-+ }
-+ }
-+
-+ CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
-+ dc_target->streams[0]->timing.h_addressable,
-+ dc_target->streams[0]->timing.v_addressable,
-+ dc_target->streams[0]->timing.h_total,
-+ dc_target->streams[0]->timing.v_total,
-+ dc_target->streams[0]->timing.pix_clk_khz);
-+ }
-+
-+ pplib_apply_display_requirements(core_dc,
-+ context, &context->pp_display_cfg);
-+
-+ resource_validate_ctx_destruct(core_dc->current_context);
-+
-+ dm_free(core_dc->current_context);
-+ core_dc->current_context = context;
-+
-+ return (result == DC_OK);
-+
-+fail:
-+ dm_free(context);
-+
-+context_alloc_fail:
-+ return (result == DC_OK);
-+}
-+
-+bool dc_pre_update_surfaces_to_target(
-+ struct dc *dc,
-+ const struct dc_surface *const *new_surfaces,
-+ uint8_t new_surface_count,
-+ struct dc_target *dc_target)
-+{
-+ int i, j;
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz;
-+ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
-+ struct dc_target_status *target_status = NULL;
-+ struct validate_context *context;
-+ struct validate_context *temp_context;
-+ bool ret = true;
-+
-+ pre_surface_trace(dc, new_surfaces, new_surface_count);
-+
-+ if (core_dc->current_context->target_count == 0)
-+ return false;
-+
-+ /* Cannot commit surface to a target that is not commited */
-+ for (i = 0; i < core_dc->current_context->target_count; i++)
-+ if (target == core_dc->current_context->targets[i])
-+ break;
-+
-+ if (i == core_dc->current_context->target_count)
-+ return false;
-+
-+ target_status = &core_dc->current_context->target_status[i];
-+
-+ if (new_surface_count == target_status->surface_count) {
-+ bool skip_pre = true;
-+
-+ for (i = 0; i < target_status->surface_count; i++) {
-+ struct dc_surface temp_surf = { 0 };
-+
-+ temp_surf = *target_status->surfaces[i];
-+ temp_surf.clip_rect = new_surfaces[i]->clip_rect;
-+ temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x;
-+ temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y;
-+
-+ if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) {
-+ skip_pre = false;
-+ break;
-+ }
-+ }
-+
-+ if (skip_pre)
-+ return true;
-+ }
-+
-+ context = dm_alloc(sizeof(struct validate_context));
-+
-+ if (!context) {
-+ dm_error("%s: failed to create validate ctx\n", __func__);
-+ ret = false;
-+ goto val_ctx_fail;
-+ }
-+
-+ resource_validate_ctx_copy_construct(core_dc->current_context, context);
-+
-+ dm_logger_write(core_dc->ctx->logger, LOG_DC,
-+ "%s: commit %d surfaces to target 0x%x\n",
-+ __func__,
-+ new_surface_count,
-+ dc_target);
-+
-+ if (!resource_attach_surfaces_to_context(
-+ new_surfaces, new_surface_count, dc_target, context)) {
-+ BREAK_TO_DEBUGGER();
-+ ret = false;
-+ goto unexpected_fail;
-+ }
-+
-+ for (i = 0; i < new_surface_count; i++)
-+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-+ if (context->res_ctx.pipe_ctx[j].surface !=
-+ DC_SURFACE_TO_CORE(new_surfaces[i]))
-+ continue;
-+
-+ resource_build_scaling_params(
-+ new_surfaces[i], &context->res_ctx.pipe_ctx[j]);
-+
-+ if (dc->debug.surface_visual_confirm) {
-+ context->res_ctx.pipe_ctx[j].scl_data.recout.height -= 2;
-+ context->res_ctx.pipe_ctx[j].scl_data.recout.width -= 2;
-+ }
-+ }
-+
-+ if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) {
-+ BREAK_TO_DEBUGGER();
-+ ret = false;
-+ goto unexpected_fail;
-+ }
-+
-+ if (core_dc->res_pool->funcs->apply_clk_constraints) {
-+ temp_context = core_dc->res_pool->funcs->apply_clk_constraints(
-+ core_dc,
-+ context);
-+ if (!temp_context) {
-+ dm_error("%s:failed apply clk constraints\n", __func__);
-+ ret = false;
-+ goto unexpected_fail;
-+ }
-+ resource_validate_ctx_destruct(context);
-+ dm_free(context);
-+ context = temp_context;
-+ }
-+
-+ if (prev_disp_clk < context->bw_results.dispclk_khz) {
-+ pplib_apply_display_requirements(core_dc, context,
-+ &context->pp_display_cfg);
-+ core_dc->hwss.set_display_clock(context);
-+ core_dc->current_context->bw_results.dispclk_khz =
-+ context->bw_results.dispclk_khz;
-+ }
-+
-+ for (i = 0; i < new_surface_count; i++)
-+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-+ if (context->res_ctx.pipe_ctx[j].surface !=
-+ DC_SURFACE_TO_CORE(new_surfaces[i]))
-+ continue;
-+
-+ core_dc->hwss.prepare_pipe_for_context(
-+ core_dc,
-+ &context->res_ctx.pipe_ctx[j],
-+ context);
-+
-+ if (!new_surfaces[i]->visible)
-+ context->res_ctx.pipe_ctx[j].tg->funcs->set_blank(
-+ context->res_ctx.pipe_ctx[j].tg, true);
-+ }
-+
-+unexpected_fail:
-+ resource_validate_ctx_destruct(context);
-+ dm_free(context);
-+val_ctx_fail:
-+
-+ return ret;
-+}
-+
-+bool dc_post_update_surfaces_to_target(struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i;
-+
-+ post_surface_trace(dc);
-+
-+ for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++)
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL)
-+ core_dc->hwss.power_down_front_end(
-+ core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]);
-+
-+ if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context)
-+ != DC_OK) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ core_dc->hwss.set_bandwidth(core_dc);
-+
-+ pplib_apply_display_requirements(
-+ core_dc, core_dc->current_context, &core_dc->current_context->pp_display_cfg);
-+
-+ return true;
-+}
-+
-+bool dc_commit_surfaces_to_target(
-+ struct dc *dc,
-+ const struct dc_surface **new_surfaces,
-+ uint8_t new_surface_count,
-+ struct dc_target *dc_target)
-+{
-+ struct dc_surface_update updates[MAX_SURFACES] = { 0 };
-+ struct dc_flip_addrs flip_addr[MAX_SURFACES] = { 0 };
-+ struct dc_plane_info plane_info[MAX_SURFACES] = { 0 };
-+ struct dc_scaling_info scaling_info[MAX_SURFACES] = { 0 };
-+ int i;
-+
-+ if (!dc_pre_update_surfaces_to_target(
-+ dc, new_surfaces, new_surface_count, dc_target))
-+ return false;
-+
-+ for (i = 0; i < new_surface_count; i++) {
-+ updates[i].surface = new_surfaces[i];
-+ updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction;
-+
-+ flip_addr[i].address = new_surfaces[i]->address;
-+ flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate;
-+ plane_info[i].color_space = new_surfaces[i]->color_space;
-+ plane_info[i].format = new_surfaces[i]->format;
-+ plane_info[i].plane_size = new_surfaces[i]->plane_size;
-+ plane_info[i].rotation = new_surfaces[i]->rotation;
-+ plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror;
-+ plane_info[i].stereo_format = new_surfaces[i]->stereo_format;
-+ plane_info[i].tiling_info = new_surfaces[i]->tiling_info;
-+ plane_info[i].visible = new_surfaces[i]->visible;
-+ scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality;
-+ scaling_info[i].src_rect = new_surfaces[i]->src_rect;
-+ scaling_info[i].dst_rect = new_surfaces[i]->dst_rect;
-+ scaling_info[i].clip_rect = new_surfaces[i]->clip_rect;
-+
-+ updates[i].flip_addr = &flip_addr[i];
-+ updates[i].plane_info = &plane_info[i];
-+ updates[i].scaling_info = &scaling_info[i];
-+ }
-+ dc_update_surfaces_for_target(dc, updates, new_surface_count, dc_target);
-+
-+ return dc_post_update_surfaces_to_target(dc);
-+}
-+
-+void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates,
-+ int surface_count, struct dc_target *dc_target)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct validate_context *context = core_dc->temp_flip_context;
-+ int i, j;
-+ bool is_new_pipe_surface[MAX_SURFACES];
-+ const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 };
-+
-+ update_surface_trace(dc, updates, surface_count);
-+
-+ *context = *core_dc->current_context;
-+
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
-+
-+ if (cur_pipe->top_pipe)
-+ cur_pipe->top_pipe =
-+ &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
-+
-+ if (cur_pipe->bottom_pipe)
-+ cur_pipe->bottom_pipe =
-+ &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
-+ }
-+
-+ for (j = 0; j < MAX_SURFACES; j++)
-+ is_new_pipe_surface[j] = true;
-+
-+ for (i = 0 ; i < surface_count; i++) {
-+ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
-+
-+ new_surfaces[i] = updates[i].surface;
-+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
-+
-+ if (surface == pipe_ctx->surface)
-+ is_new_pipe_surface[i] = false;
-+ }
-+ }
-+
-+ if (dc_target) {
-+ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
-+
-+ if (core_dc->current_context->target_count == 0)
-+ return;
-+
-+ /* Cannot commit surface to a target that is not commited */
-+ for (i = 0; i < core_dc->current_context->target_count; i++)
-+ if (target == core_dc->current_context->targets[i])
-+ break;
-+ if (i == core_dc->current_context->target_count)
-+ return;
-+
-+ if (!resource_attach_surfaces_to_context(
-+ new_surfaces, surface_count, dc_target, context)) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+ }
-+
-+ for (i = 0; i < surface_count; i++) {
-+ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
-+
-+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
-+
-+ if (pipe_ctx->surface != surface)
-+ continue;
-+
-+ if (updates[i].flip_addr) {
-+ surface->public.address = updates[i].flip_addr->address;
-+ surface->public.flip_immediate =
-+ updates[i].flip_addr->flip_immediate;
-+ }
-+
-+ if (updates[i].plane_info || updates[i].scaling_info
-+ || is_new_pipe_surface[j]) {
-+
-+ if (updates[i].plane_info) {
-+ surface->public.color_space =
-+ updates[i].plane_info->color_space;
-+ surface->public.format =
-+ updates[i].plane_info->format;
-+ surface->public.plane_size =
-+ updates[i].plane_info->plane_size;
-+ surface->public.rotation =
-+ updates[i].plane_info->rotation;
-+ surface->public.horizontal_mirror =
-+ updates[i].plane_info->horizontal_mirror;
-+ surface->public.stereo_format =
-+ updates[i].plane_info->stereo_format;
-+ surface->public.tiling_info =
-+ updates[i].plane_info->tiling_info;
-+ surface->public.visible =
-+ updates[i].plane_info->visible;
-+ }
-+
-+ if (updates[i].scaling_info) {
-+ surface->public.scaling_quality =
-+ updates[i].scaling_info->scaling_quality;
-+ surface->public.dst_rect =
-+ updates[i].scaling_info->dst_rect;
-+ surface->public.src_rect =
-+ updates[i].scaling_info->src_rect;
-+ surface->public.clip_rect =
-+ updates[i].scaling_info->clip_rect;
-+ }
-+
-+ resource_build_scaling_params(updates[i].surface, pipe_ctx);
-+ if (dc->debug.surface_visual_confirm) {
-+ pipe_ctx->scl_data.recout.height -= 2;
-+ pipe_ctx->scl_data.recout.width -= 2;
-+ }
-+ }
-+ }
-+ }
-+
-+ for (i = 0; i < surface_count; i++) {
-+ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
-+ bool apply_ctx = false;
-+
-+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
-+
-+ if (pipe_ctx->surface != surface)
-+ continue;
-+
-+ if (updates[i].flip_addr) {
-+ core_dc->hwss.pipe_control_lock(
-+ core_dc->hwseq,
-+ pipe_ctx->pipe_idx,
-+ PIPE_LOCK_CONTROL_SURFACE,
-+ true);
-+ core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
-+ }
-+
-+ if (updates[i].plane_info || updates[i].scaling_info
-+ || is_new_pipe_surface[j]) {
-+
-+ apply_ctx = true;
-+
-+ if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
-+ core_dc->hwss.pipe_control_lock(
-+ core_dc->hwseq,
-+ pipe_ctx->pipe_idx,
-+ PIPE_LOCK_CONTROL_SURFACE |
-+ PIPE_LOCK_CONTROL_GRAPHICS |
-+ PIPE_LOCK_CONTROL_SCL |
-+ PIPE_LOCK_CONTROL_BLENDER |
-+ PIPE_LOCK_CONTROL_MODE,
-+ true);
-+ }
-+ }
-+
-+ if (updates[i].gamma)
-+ core_dc->hwss.prepare_pipe_for_context(
-+ core_dc, pipe_ctx, context);
-+ }
-+ if (apply_ctx)
-+ core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
-+ }
-+
-+ for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ for (j = 0; j < surface_count; j++) {
-+ if (updates[j].surface == &pipe_ctx->surface->public) {
-+ if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
-+ core_dc->hwss.pipe_control_lock(
-+ core_dc->hwseq,
-+ pipe_ctx->pipe_idx,
-+ PIPE_LOCK_CONTROL_GRAPHICS |
-+ PIPE_LOCK_CONTROL_SCL |
-+ PIPE_LOCK_CONTROL_BLENDER |
-+ PIPE_LOCK_CONTROL_SURFACE,
-+ false);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+
-+ core_dc->temp_flip_context = core_dc->current_context;
-+ core_dc->current_context = context;
-+}
-+
-+uint8_t dc_get_current_target_count(const struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return core_dc->current_context->target_count;
-+}
-+
-+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ if (i < core_dc->current_context->target_count)
-+ return &(core_dc->current_context->targets[i]->public);
-+ return NULL;
-+}
-+
-+const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return &core_dc->links[link_index]->public;
-+}
-+
-+const struct graphics_object_id dc_get_link_id_at_index(
-+ struct dc *dc, uint32_t link_index)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return core_dc->links[link_index]->link_id;
-+}
-+
-+const struct ddc_service *dc_get_ddc_at_index(
-+ struct dc *dc, uint32_t link_index)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return core_dc->links[link_index]->ddc;
-+}
-+
-+enum dc_irq_source dc_get_hpd_irq_source_at_index(
-+ struct dc *dc, uint32_t link_index)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return core_dc->links[link_index]->public.irq_source_hpd;
-+}
-+
-+const struct audio **dc_get_audios(struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return (const struct audio **)core_dc->res_pool->audios;
-+}
-+
-+void dc_flip_surface_addrs(
-+ struct dc *dc,
-+ const struct dc_surface *const surfaces[],
-+ struct dc_flip_addrs flip_addrs[],
-+ uint32_t count)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ int i, j;
-+
-+ for (i = 0; i < count; i++) {
-+ struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
-+
-+ surface->public.address = flip_addrs[i].address;
-+ surface->public.flip_immediate = flip_addrs[i].flip_immediate;
-+
-+ for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
-+ struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
-+
-+ if (pipe_ctx->surface != surface)
-+ continue;
-+
-+ core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
-+ }
-+ }
-+}
-+
-+enum dc_irq_source dc_interrupt_to_irq_source(
-+ struct dc *dc,
-+ uint32_t src_id,
-+ uint32_t ext_id)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id);
-+}
-+
-+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ dal_irq_service_set(core_dc->res_pool->irqs, src, enable);
-+}
-+
-+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ dal_irq_service_ack(core_dc->res_pool->irqs, src);
-+}
-+
-+void dc_set_power_state(
-+ struct dc *dc,
-+ enum dc_acpi_cm_power_state power_state,
-+ enum dc_video_power_state video_power_state)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+
-+ core_dc->previous_power_state = core_dc->current_power_state;
-+ core_dc->current_power_state = video_power_state;
-+
-+ switch (power_state) {
-+ case DC_ACPI_CM_POWER_STATE_D0:
-+ core_dc->hwss.init_hw(core_dc);
-+ break;
-+ default:
-+ /* NULL means "reset/release all DC targets" */
-+ dc_commit_targets(dc, NULL, 0);
-+
-+ core_dc->hwss.power_down(core_dc);
-+
-+ /* Zero out the current context so that on resume we start with
-+ * clean state, and dc hw programming optimizations will not
-+ * cause any trouble.
-+ */
-+ memset(core_dc->current_context, 0,
-+ sizeof(*core_dc->current_context));
-+
-+ core_dc->current_context->res_ctx.pool = core_dc->res_pool;
-+
-+ break;
-+ }
-+
-+}
-+
-+void dc_resume(const struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+
-+ uint32_t i;
-+
-+ for (i = 0; i < core_dc->link_count; i++)
-+ core_link_resume(core_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_dc *core_dc = DC_TO_CORE(dc);
-+
-+ struct core_link *link = core_dc->links[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_dc *core_dc = DC_TO_CORE(dc);
-+
-+ struct core_link *link = core_dc->links[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_dc *core_dc = DC_TO_CORE(dc);
-+
-+ struct core_link *link = core_dc->links[link_index];
-+ struct ddc_service *ddc = link->ddc;
-+
-+ return dal_i2caux_submit_i2c_command(
-+ ddc->ctx->i2caux,
-+ ddc->ddc_pin,
-+ cmd);
-+}
-+
-+static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink)
-+{
-+ struct dc_link *dc_link = &core_link->public;
-+
-+ if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ dc_sink_retain(sink);
-+
-+ dc_link->remote_sinks[dc_link->sink_count] = sink;
-+ dc_link->sink_count++;
-+
-+ return true;
-+}
-+
-+struct dc_sink *dc_link_add_remote_sink(
-+ const struct dc_link *link,
-+ const uint8_t *edid,
-+ int len,
-+ struct dc_sink_init_data *init_data)
-+{
-+ struct dc_sink *dc_sink;
-+ enum dc_edid_status edid_status;
-+ struct core_link *core_link = DC_LINK_TO_LINK(link);
-+
-+ if (len > MAX_EDID_BUFFER_SIZE) {
-+ dm_error("Max EDID buffer size breached!\n");
-+ return NULL;
-+ }
-+
-+ if (!init_data) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ if (!init_data->link) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ dc_sink = dc_sink_create(init_data);
-+
-+ if (!dc_sink)
-+ return NULL;
-+
-+ memmove(dc_sink->dc_edid.raw_edid, edid, len);
-+ dc_sink->dc_edid.length = len;
-+
-+ if (!link_add_remote_sink_helper(
-+ core_link,
-+ dc_sink))
-+ goto fail_add_sink;
-+
-+ edid_status = dm_helpers_parse_edid_caps(
-+ core_link->ctx,
-+ &dc_sink->dc_edid,
-+ &dc_sink->edid_caps);
-+
-+ if (edid_status != EDID_OK)
-+ goto fail;
-+
-+ return dc_sink;
-+fail:
-+ dc_link_remove_remote_sink(link, dc_sink);
-+fail_add_sink:
-+ dc_sink_release(dc_sink);
-+ return NULL;
-+}
-+
-+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->type = dc_connection_none;
-+ } else {
-+ 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;
-+ }
-+ }
-+}
-+
-+const struct dc_stream_status *dc_stream_get_status(
-+ const struct dc_stream *dc_stream)
-+{
-+ struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
-+
-+ return &stream->status;
-+}
-+
-+bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data)
-+{
-+ int i;
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct mem_input *mi = NULL;
-+
-+ for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
-+ if (core_dc->res_pool->mis[i] != NULL) {
-+ mi = core_dc->res_pool->mis[i];
-+ break;
-+ }
-+ }
-+ if (mi == NULL) {
-+ dm_error("no mem_input!\n");
-+ return false;
-+ }
-+
-+ if (mi->funcs->mem_input_update_dchub)
-+ mi->funcs->mem_input_update_dchub(mi, dh_data);
-+ else
-+ ASSERT(mi->funcs->mem_input_update_dchub);
-+
-+
-+ return true;
-+
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
-new file mode 100644
-index 0000000..8ca0f1e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
-@@ -0,0 +1,270 @@
-+/*
-+ * dc_debug.c
-+ *
-+ * Created on: Nov 3, 2016
-+ * Author: yonsun
-+ */
-+
-+#include "dm_services.h"
-+
-+#include "dc.h"
-+
-+#include "core_status.h"
-+#include "core_types.h"
-+#include "hw_sequencer.h"
-+
-+#include "resource.h"
-+
-+#define SURFACE_TRACE(...) do {\
-+ if (dc->debug.surface_trace) \
-+ dm_logger_write(logger, \
-+ LOG_IF_TRACE, \
-+ ##__VA_ARGS__); \
-+} while (0)
-+
-+void pre_surface_trace(
-+ const struct dc *dc,
-+ const struct dc_surface *const *surfaces,
-+ int surface_count)
-+{
-+ int i;
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct dal_logger *logger = core_dc->ctx->logger;
-+
-+ for (i = 0; i < surface_count; i++) {
-+ const struct dc_surface *surface = surfaces[i];
-+
-+ SURFACE_TRACE("Surface %d:\n", i);
-+
-+ SURFACE_TRACE(
-+ "surface->visible = %d;\n"
-+ "surface->flip_immediate = %d;\n"
-+ "surface->address.type = %d;\n"
-+ "surface->address.grph.addr.quad_part = 0x%X;\n"
-+ "surface->address.grph.meta_addr.quad_part = 0x%X;\n"
-+ "surface->scaling_quality.h_taps = %d;\n"
-+ "surface->scaling_quality.v_taps = %d;\n"
-+ "surface->scaling_quality.h_taps_c = %d;\n"
-+ "surface->scaling_quality.v_taps_c = %d;\n",
-+ surface->visible,
-+ surface->flip_immediate,
-+ surface->address.type,
-+ surface->address.grph.addr.quad_part,
-+ surface->address.grph.meta_addr.quad_part,
-+ surface->scaling_quality.h_taps,
-+ surface->scaling_quality.v_taps,
-+ surface->scaling_quality.h_taps_c,
-+ surface->scaling_quality.v_taps_c);
-+
-+ SURFACE_TRACE(
-+ "surface->src_rect.x = %d;\n"
-+ "surface->src_rect.y = %d;\n"
-+ "surface->src_rect.width = %d;\n"
-+ "surface->src_rect.height = %d;\n"
-+ "surface->dst_rect.x = %d;\n"
-+ "surface->dst_rect.y = %d;\n"
-+ "surface->dst_rect.width = %d;\n"
-+ "surface->dst_rect.height = %d;\n"
-+ "surface->clip_rect.x = %d;\n"
-+ "surface->clip_rect.y = %d;\n"
-+ "surface->clip_rect.width = %d;\n"
-+ "surface->clip_rect.height = %d;\n",
-+ surface->src_rect.x,
-+ surface->src_rect.y,
-+ surface->src_rect.width,
-+ surface->src_rect.height,
-+ surface->dst_rect.x,
-+ surface->dst_rect.y,
-+ surface->dst_rect.width,
-+ surface->dst_rect.height,
-+ surface->clip_rect.x,
-+ surface->clip_rect.y,
-+ surface->clip_rect.width,
-+ surface->clip_rect.height);
-+
-+ SURFACE_TRACE(
-+ "surface->plane_size.grph.surface_size.x = %d;\n"
-+ "surface->plane_size.grph.surface_size.y = %d;\n"
-+ "surface->plane_size.grph.surface_size.width = %d;\n"
-+ "surface->plane_size.grph.surface_size.height = %d;\n"
-+ "surface->plane_size.grph.surface_pitch = %d;\n"
-+ "surface->plane_size.grph.meta_pitch = %d;\n",
-+ surface->plane_size.grph.surface_size.x,
-+ surface->plane_size.grph.surface_size.y,
-+ surface->plane_size.grph.surface_size.width,
-+ surface->plane_size.grph.surface_size.height,
-+ surface->plane_size.grph.surface_pitch,
-+ surface->plane_size.grph.meta_pitch);
-+
-+
-+ SURFACE_TRACE(
-+ "surface->tiling_info.gfx8.num_banks = %d;\n"
-+ "surface->tiling_info.gfx8.bank_width = %d;\n"
-+ "surface->tiling_info.gfx8.bank_width_c = %d;\n"
-+ "surface->tiling_info.gfx8.bank_height = %d;\n"
-+ "surface->tiling_info.gfx8.bank_height_c = %d;\n"
-+ "surface->tiling_info.gfx8.tile_aspect = %d;\n"
-+ "surface->tiling_info.gfx8.tile_aspect_c = %d;\n"
-+ "surface->tiling_info.gfx8.tile_split = %d;\n"
-+ "surface->tiling_info.gfx8.tile_split_c = %d;\n"
-+ "surface->tiling_info.gfx8.tile_mode = %d;\n"
-+ "surface->tiling_info.gfx8.tile_mode_c = %d;\n",
-+ surface->tiling_info.gfx8.num_banks,
-+ surface->tiling_info.gfx8.bank_width,
-+ surface->tiling_info.gfx8.bank_width_c,
-+ surface->tiling_info.gfx8.bank_height,
-+ surface->tiling_info.gfx8.bank_height_c,
-+ surface->tiling_info.gfx8.tile_aspect,
-+ surface->tiling_info.gfx8.tile_aspect_c,
-+ surface->tiling_info.gfx8.tile_split,
-+ surface->tiling_info.gfx8.tile_split_c,
-+ surface->tiling_info.gfx8.tile_mode,
-+ surface->tiling_info.gfx8.tile_mode_c);
-+
-+ SURFACE_TRACE(
-+ "surface->tiling_info.gfx8.pipe_config = %d;\n"
-+ "surface->tiling_info.gfx8.array_mode = %d;\n"
-+ "surface->color_space = %d;\n"
-+ "surface->dcc.enable = %d;\n"
-+ "surface->format = %d;\n"
-+ "surface->rotation = %d;\n"
-+ "surface->stereo_format = %d;\n",
-+ surface->tiling_info.gfx8.pipe_config,
-+ surface->tiling_info.gfx8.array_mode,
-+ surface->color_space,
-+ surface->dcc.enable,
-+ surface->format,
-+ surface->rotation,
-+ surface->stereo_format);
-+ SURFACE_TRACE("\n");
-+ }
-+ SURFACE_TRACE("\n");
-+}
-+
-+void update_surface_trace(
-+ const struct dc *dc,
-+ const struct dc_surface_update *updates,
-+ int surface_count)
-+{
-+ int i;
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct dal_logger *logger = core_dc->ctx->logger;
-+
-+ for (i = 0; i < surface_count; i++) {
-+ const struct dc_surface_update *update = &updates[i];
-+
-+ SURFACE_TRACE("Update %d\n", i);
-+ if (update->flip_addr) {
-+ SURFACE_TRACE("flip_addr->address.type = %d;\n"
-+ "flip_addr->address.grph.addr.quad_part = 0x%X;\n"
-+ "flip_addr->address.grph.meta_addr.quad_part = 0x%X;\n"
-+ "flip_addr->flip_immediate = %d;\n",
-+ update->flip_addr->address.type,
-+ update->flip_addr->address.grph.addr.quad_part,
-+ update->flip_addr->address.grph.meta_addr.quad_part,
-+ update->flip_addr->flip_immediate);
-+ }
-+
-+ if (update->plane_info) {
-+ SURFACE_TRACE(
-+ "plane_info->color_space = %d;\n"
-+ "plane_info->format = %d;\n"
-+ "plane_info->plane_size.grph.meta_pitch = %d;\n"
-+ "plane_info->plane_size.grph.surface_pitch = %d;\n"
-+ "plane_info->plane_size.grph.surface_size.height = %d;\n"
-+ "plane_info->plane_size.grph.surface_size.width = %d;\n"
-+ "plane_info->plane_size.grph.surface_size.x = %d;\n"
-+ "plane_info->plane_size.grph.surface_size.y = %d;\n"
-+ "plane_info->rotation = %d;\n",
-+ update->plane_info->color_space,
-+ update->plane_info->format,
-+ update->plane_info->plane_size.grph.meta_pitch,
-+ update->plane_info->plane_size.grph.surface_pitch,
-+ update->plane_info->plane_size.grph.surface_size.height,
-+ update->plane_info->plane_size.grph.surface_size.width,
-+ update->plane_info->plane_size.grph.surface_size.x,
-+ update->plane_info->plane_size.grph.surface_size.y,
-+ update->plane_info->rotation,
-+ update->plane_info->stereo_format);
-+
-+ SURFACE_TRACE(
-+ "plane_info->tiling_info.gfx8.num_banks = %d;\n"
-+ "plane_info->tiling_info.gfx8.bank_width = %d;\n"
-+ "plane_info->tiling_info.gfx8.bank_width_c = %d;\n"
-+ "plane_info->tiling_info.gfx8.bank_height = %d;\n"
-+ "plane_info->tiling_info.gfx8.bank_height_c = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_aspect = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_aspect_c = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_split = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_split_c = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_mode = %d;\n"
-+ "plane_info->tiling_info.gfx8.tile_mode_c = %d;\n",
-+ update->plane_info->tiling_info.gfx8.num_banks,
-+ update->plane_info->tiling_info.gfx8.bank_width,
-+ update->plane_info->tiling_info.gfx8.bank_width_c,
-+ update->plane_info->tiling_info.gfx8.bank_height,
-+ update->plane_info->tiling_info.gfx8.bank_height_c,
-+ update->plane_info->tiling_info.gfx8.tile_aspect,
-+ update->plane_info->tiling_info.gfx8.tile_aspect_c,
-+ update->plane_info->tiling_info.gfx8.tile_split,
-+ update->plane_info->tiling_info.gfx8.tile_split_c,
-+ update->plane_info->tiling_info.gfx8.tile_mode,
-+ update->plane_info->tiling_info.gfx8.tile_mode_c);
-+
-+ SURFACE_TRACE(
-+ "plane_info->tiling_info.gfx8.pipe_config = %d;\n"
-+ "plane_info->tiling_info.gfx8.array_mode = %d;\n"
-+ "plane_info->visible = %d;\n",
-+ update->plane_info->tiling_info.gfx8.pipe_config,
-+ update->plane_info->tiling_info.gfx8.array_mode,
-+ update->plane_info->visible);
-+ }
-+
-+ if (update->scaling_info) {
-+ SURFACE_TRACE(
-+ "scaling_info->src_rect.x = %d;\n"
-+ "scaling_info->src_rect.y = %d;\n"
-+ "scaling_info->src_rect.width = %d;\n"
-+ "scaling_info->src_rect.height = %d;\n"
-+ "scaling_info->dst_rect.x = %d;\n"
-+ "scaling_info->dst_rect.y = %d;\n"
-+ "scaling_info->dst_rect.width = %d;\n"
-+ "scaling_info->dst_rect.height = %d;\n"
-+ "scaling_info->clip_rect.x = %d;\n"
-+ "scaling_info->clip_rect.y = %d;\n"
-+ "scaling_info->clip_rect.width = %d;\n"
-+ "scaling_info->clip_rect.height = %d;\n"
-+ "scaling_info->scaling_quality.h_taps = %d;\n"
-+ "scaling_info->scaling_quality.v_taps = %d;\n"
-+ "scaling_info->scaling_quality.h_taps_c = %d;\n"
-+ "scaling_info->scaling_quality.v_taps_c = %d;\n",
-+ update->scaling_info->src_rect.x,
-+ update->scaling_info->src_rect.y,
-+ update->scaling_info->src_rect.width,
-+ update->scaling_info->src_rect.height,
-+ update->scaling_info->dst_rect.x,
-+ update->scaling_info->dst_rect.y,
-+ update->scaling_info->dst_rect.width,
-+ update->scaling_info->dst_rect.height,
-+ update->scaling_info->clip_rect.x,
-+ update->scaling_info->clip_rect.y,
-+ update->scaling_info->clip_rect.width,
-+ update->scaling_info->clip_rect.height,
-+ update->scaling_info->scaling_quality.h_taps,
-+ update->scaling_info->scaling_quality.v_taps,
-+ update->scaling_info->scaling_quality.h_taps_c,
-+ update->scaling_info->scaling_quality.v_taps_c);
-+ }
-+ SURFACE_TRACE("\n");
-+ }
-+ SURFACE_TRACE("\n");
-+}
-+
-+void post_surface_trace(const struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct dal_logger *logger = core_dc->ctx->logger;
-+
-+ SURFACE_TRACE("post surface process.\n");
-+
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
-new file mode 100644
-index 0000000..d5cffa5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
-@@ -0,0 +1,93 @@
-+/*
-+ * 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"
-+#include "core_dc.h"
-+#include "timing_generator.h"
-+#include "hw_sequencer.h"
-+
-+/* used as index in array of black_color_format */
-+enum black_color_format {
-+ BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,
-+ BLACK_COLOR_FORMAT_RGB_LIMITED,
-+ BLACK_COLOR_FORMAT_YUV_TV,
-+ BLACK_COLOR_FORMAT_YUV_CV,
-+ BLACK_COLOR_FORMAT_YUV_SUPER_AA,
-+ BLACK_COLOR_FORMAT_DEBUG,
-+};
-+
-+static const struct tg_color black_color_format[] = {
-+ /* BlackColorFormat_RGB_FullRange */
-+ {0, 0, 0},
-+ /* BlackColorFormat_RGB_Limited */
-+ {0x40, 0x40, 0x40},
-+ /* BlackColorFormat_YUV_TV */
-+ {0x200, 0x40, 0x200},
-+ /* BlackColorFormat_YUV_CV */
-+ {0x1f4, 0x40, 0x1f4},
-+ /* BlackColorFormat_YUV_SuperAA */
-+ {0x1a2, 0x20, 0x1a2},
-+ /* visual confirm debug */
-+ {0xff, 0xff, 0},
-+};
-+
-+void color_space_to_black_color(
-+ const struct core_dc *dc,
-+ enum dc_color_space colorspace,
-+ struct tg_color *black_color)
-+{
-+ if (dc->public.debug.surface_visual_confirm) {
-+ *black_color =
-+ black_color_format[BLACK_COLOR_FORMAT_DEBUG];
-+ return;
-+ }
-+
-+ 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:
-+ case COLOR_SPACE_YCBCR601_LIMITED:
-+ case COLOR_SPACE_YCBCR709_LIMITED:
-+ *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
-+ break;
-+
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ *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;
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
-new file mode 100644
-index 0000000..70a2554
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
-@@ -0,0 +1,1899 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "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 "resource.h"
-+#include "fixed31_32.h"
-+#include "include/asic_capability_interface.h"
-+
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_enum.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+#ifndef mmDMCU_STATUS__UC_IN_RESET__SHIFT
-+#define mmDMCU_STATUS__UC_IN_RESET__SHIFT 0x0
-+#endif
-+
-+#ifndef mmDMCU_STATUS__UC_IN_RESET_MASK
-+#define mmDMCU_STATUS__UC_IN_RESET_MASK 0x00000001L
-+#endif
-+
-+#define LINK_INFO(...) \
-+ dm_logger_write(dc_ctx->logger, LOG_HW_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)
-+{
-+ int i;
-+
-+ if (link->ddc)
-+ dal_ddc_service_destroy(&link->ddc);
-+
-+ if(link->link_enc)
-+ link->link_enc->funcs->destroy(&link->link_enc);
-+
-+ if (link->public.local_sink)
-+ dc_sink_release(link->public.local_sink);
-+
-+ for (i = 0; i < link->public.sink_count; ++i)
-+ dc_sink_release(link->public.remote_sinks[i]);
-+}
-+
-+static struct gpio *get_hpd_gpio(const struct core_link *link)
-+{
-+ enum bp_result bp_result;
-+ struct dc_bios *dcb = link->ctx->dc_bios;
-+ struct graphics_object_hpd_info hpd_info;
-+ struct gpio_pin_info pin_info;
-+
-+ if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK)
-+ 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(
-+ link->ctx->gpio_service,
-+ pin_info.offset,
-+ pin_info.mask);
-+}
-+
-+/*
-+ * 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 gpio *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 */
-+ /* 500: not able to detect MST <-> SST switch as HPD is low for
-+ * only 100ms on DELL U2413
-+ * 0: some passive dongle still show aux mode instead of i2c
-+ * 20-50:not enough to hide bouncing HPD with passive dongle.
-+ * also see intermittent i2c read issues.
-+ */
-+ delay_on_connect_in_ms = 80;
-+ 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 = get_hpd_gpio(link);
-+
-+ if (!hpd)
-+ return result;
-+
-+ /* Setup HPD filtering */
-+ if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == 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_gpio_close(hpd);
-+
-+ result = true;
-+ } else {
-+ ASSERT_CRITICAL(false);
-+ }
-+
-+ /* Release HPD handle */
-+ dal_gpio_destroy_irq(&hpd);
-+
-+ return result;
-+}
-+
-+static bool detect_sink(struct core_link *link, enum dc_connection_type *type)
-+{
-+ uint32_t is_hpd_high = 0;
-+ struct gpio *hpd_pin;
-+
-+ /* todo: may need to lock gpio access */
-+ hpd_pin = get_hpd_gpio(link);
-+ if (hpd_pin == NULL)
-+ goto hpd_gpio_failure;
-+
-+ dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
-+ dal_gpio_get_value(hpd_pin, &is_hpd_high);
-+ dal_gpio_close(hpd_pin);
-+ dal_gpio_destroy_irq(&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_ddc_service_get_ddc_pin(link->ddc);
-+
-+ if (!ddc) {
-+ BREAK_TO_DEBUGGER();
-+ 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_gpio_destroy_ddc(&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_gpio_get_value(ddc->pin_clock, &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_gpio_get_value(ddc->pin_data, &data_pin);
-+
-+ present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin);
-+
-+ dal_ddc_close(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 */
-+ struct audio_support *aud_support = &link->dc->res_pool->audio_support;
-+
-+ if (!aud_support->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,
-+ struct audio_support *audio_support)
-+{
-+ enum signal_type signal = SIGNAL_TYPE_NONE;
-+
-+ switch (dongle_type) {
-+ case DISPLAY_DONGLE_DP_HDMI_DONGLE:
-+ if (audio_support->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->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,
-+ struct audio_support *audio_support)
-+{
-+ 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)
-+ dm_logger_write(link->ctx->logger, LOG_WARNING,
-+ "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,
-+ struct 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)) {
-+ link->public.type = dc_connection_active_dongle;
-+ if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
-+ /*
-+ * 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;
-+ struct audio_support *aud_support = &link->dc->res_pool->audio_support;
-+ 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;
-+ }
-+
-+ if (link->public.connector_signal == SIGNAL_TYPE_EDP &&
-+ link->public.local_sink)
-+ return true;
-+
-+ 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 (aud_support->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,
-+ aud_support, boot);
-+
-+ /* Active dongle downstream unplug */
-+ if (link->public.type == dc_connection_active_dongle
-+ && link->dpcd_caps.sink_count.
-+ bits.SINK_COUNT == 0)
-+ 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:
-+ dm_logger_write(link->ctx->logger, LOG_ERROR,
-+ "EDID checksum invalid.\n");
-+ break;
-+ case EDID_NO_RESPONSE:
-+ dm_logger_write(link->ctx->logger, LOG_ERROR,
-+ "No EDID read.\n");
-+ return false;
-+
-+ default:
-+ break;
-+ }
-+
-+ /* HDMI-DVI Dongle */
-+ if (dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
-+ !dc_sink->edid_caps.edid_hdmi)
-+ dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
-+
-+ /* Connectivity log: detection */
-+ for (i = 0; i < sink->public.dc_edid.length / EDID_BLOCK_SIZE; i++) {
-+ CONN_DATA_DETECT(link,
-+ &sink->public.dc_edid.raw_edid[i * EDID_BLOCK_SIZE],
-+ EDID_BLOCK_SIZE,
-+ "%s: [Block %d] ", sink->public.edid_caps.display_name, i);
-+ }
-+
-+ dm_logger_write(link->ctx->logger, LOG_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++) {
-+ dm_logger_write(link->ctx->logger, LOG_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->mst_stream_alloc_table.stream_count = 0;
-+ memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations));
-+ }
-+
-+ 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 gpio *hpd;
-+ enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
-+
-+ hpd = get_hpd_gpio(link);
-+
-+ 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_gpio_destroy_irq(&hpd);
-+ }
-+
-+ return hpd_id;
-+}
-+
-+static enum channel_id get_ddc_line(struct core_link *link)
-+{
-+ struct ddc *ddc;
-+ enum channel_id channel = CHANNEL_ID_UNKNOWN;
-+
-+ ddc = dal_ddc_service_get_ddc_pin(link->ddc);
-+
-+ 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;
-+ }
-+ }
-+
-+ 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 gpio *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 }}};
-+ struct dc_bios *bios = init_params->dc->ctx->dc_bios;
-+ const struct dc_vbios_funcs *bp_funcs = bios->funcs;
-+
-+ link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID;
-+ link->public.irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
-+
-+ link->link_status.dpcd_caps = &link->dpcd_caps;
-+
-+ link->dc = init_params->dc;
-+ link->ctx = dc_ctx;
-+ link->public.link_index = init_params->link_index;
-+
-+ link->link_id = bios->funcs->get_connector_id(bios, 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;
-+ }
-+
-+ hpd_gpio = get_hpd_gpio(link);
-+
-+ if (hpd_gpio != NULL)
-+ link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio);
-+
-+ 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;
-+
-+ if (hpd_gpio != NULL)
-+ link->public.irq_source_hpd_rx =
-+ dal_irq_get_rx_source(hpd_gpio);
-+
-+ break;
-+ case CONNECTOR_ID_EDP:
-+ link->public.connector_signal = SIGNAL_TYPE_EDP;
-+
-+ if (hpd_gpio != NULL) {
-+ link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID;
-+ link->public.irq_source_hpd_rx =
-+ dal_irq_get_rx_source(hpd_gpio);
-+ }
-+ break;
-+ default:
-+ dm_logger_write(dc_ctx->logger, LOG_WARNING,
-+ "Unsupported Connector type:%d!\n", link->link_id.id);
-+ goto create_fail;
-+ }
-+
-+ if (hpd_gpio != NULL) {
-+ dal_gpio_destroy_irq(&hpd_gpio);
-+ hpd_gpio = NULL;
-+ }
-+
-+ /* TODO: #DAL3 Implement id to str function.*/
-+ LINK_INFO("Connector[%d] description:"
-+ "signal %d\n",
-+ init_params->connector_index,
-+ link->public.connector_signal);
-+
-+ 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 ddc_create_fail;
-+ }
-+
-+ link->public.ddc_hw_inst =
-+ dal_ddc_get_line(
-+ dal_ddc_service_get_ddc_pin(link->ddc));
-+
-+ enc_init_data.ctx = dc_ctx;
-+ bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder);
-+ enc_init_data.connector = link->link_id;
-+ enc_init_data.channel = get_ddc_line(link);
-+ enc_init_data.hpd_source = get_hpd_line(link);
-+ enc_init_data.transmitter =
-+ translate_encoder_to_transmitter(enc_init_data.encoder);
-+ link->link_enc = link->dc->res_pool->funcs->link_enc_create(
-+ &enc_init_data);
-+
-+ if( link->link_enc == NULL) {
-+ DC_ERROR("Failed to create link encoder!\n");
-+ goto link_enc_create_fail;
-+ }
-+
-+ link->public.link_enc_hw_inst = link->link_enc->transmitter;
-+
-+ for (i = 0; i < 4; i++) {
-+ if (BP_RESULT_OK !=
-+ bp_funcs->get_device_tag(dc_ctx->dc_bios, link->link_id, i, &link->device_tag)) {
-+ DC_ERROR("Failed to find device tag!\n");
-+ goto device_tag_fail;
-+ }
-+
-+ /* Look for device tag that matches connector signal,
-+ * CRT for rgb, LCD for other supported signal tyes
-+ */
-+ if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, 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;
-+ }
-+
-+ if (bios->integrated_info)
-+ info = *bios->integrated_info;
-+
-+ /* 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;
-+device_tag_fail:
-+ link->link_enc->funcs->destroy(&link->link_enc);
-+link_enc_create_fail:
-+ dal_ddc_service_destroy(&link->ddc);
-+ddc_create_fail:
-+create_fail:
-+
-+ if (hpd_gpio != NULL) {
-+ dal_gpio_destroy_irq(&hpd_gpio);
-+ }
-+
-+ return false;
-+}
-+
-+/*******************************************************************************
-+ * Public functions
-+ ******************************************************************************/
-+struct core_link *link_create(const struct link_init_data *init_params)
-+{
-+ struct core_link *link =
-+ dm_alloc(sizeof(*link));
-+
-+ if (NULL == link)
-+ goto alloc_fail;
-+
-+ if (false == construct(link, init_params))
-+ goto construct_fail;
-+
-+ return link;
-+
-+construct_fail:
-+ dm_free(link);
-+
-+alloc_fail:
-+ return NULL;
-+}
-+
-+void link_destroy(struct core_link **link)
-+{
-+ destruct(*link);
-+ dm_free(*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;
-+
-+ 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);
-+ }
-+ }
-+ dm_logger_write(link->ctx->logger, LOG_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 void enable_stream_features(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct core_link *link = stream->sink->link;
-+ union down_spread_ctrl downspread;
-+
-+ core_link_read_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL,
-+ &downspread.raw, sizeof(downspread));
-+
-+ downspread.bits.IGNORE_MSA_TIMING_PARAM =
-+ (stream->public.ignore_msa_timing_param) ? 1 : 0;
-+
-+ core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL,
-+ &downspread.raw, sizeof(downspread));
-+}
-+
-+static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ enum dc_status status;
-+ bool skip_video_pattern;
-+ struct core_link *link = stream->sink->link;
-+ struct dc_link_settings link_settings = {0};
-+ enum dp_panel_mode panel_mode;
-+ enum clocks_state cur_min_clock_state;
-+ enum dc_link_rate max_link_rate = LINK_RATE_HIGH2;
-+
-+ /* get link settings for video mode timing */
-+ decide_link_settings(stream, &link_settings);
-+
-+ /* raise clock state for HBR3 if required. Confirmed with HW DCE/DPCS
-+ * logic for HBR3 still needs Nominal (0.8V) on VDDC rail
-+ */
-+ if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
-+ max_link_rate = LINK_RATE_HIGH3;
-+
-+ if (link_settings.link_rate == max_link_rate) {
-+ cur_min_clock_state = CLOCKS_STATE_INVALID;
-+
-+ if (dal_display_clock_get_min_clocks_state(
-+ pipe_ctx->dis_clk, &cur_min_clock_state)) {
-+ if (cur_min_clock_state < CLOCKS_STATE_NOMINAL)
-+ dal_display_clock_set_min_clocks_state(
-+ pipe_ctx->dis_clk,
-+ CLOCKS_STATE_NOMINAL);
-+ } else {
-+ }
-+ }
-+
-+ dp_enable_link_phy(
-+ link,
-+ pipe_ctx->stream->signal,
-+ pipe_ctx->clock_source->id,
-+ &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_with_retries(
-+ link,
-+ &link_settings,
-+ skip_video_pattern,
-+ LINK_TRAINING_ATTEMPTS)) {
-+ link->public.cur_link_settings = link_settings;
-+ status = DC_OK;
-+ }
-+ else
-+ status = DC_ERROR_UNEXPECTED;
-+
-+ enable_stream_features(pipe_ctx);
-+
-+ return status;
-+}
-+
-+static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_link *link = pipe_ctx->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->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
-+ return DC_OK;
-+
-+ return enable_link_dp(pipe_ctx);
-+}
-+
-+static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct core_link *link = stream->sink->link;
-+
-+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
-+ dal_ddc_service_write_scdc_data(
-+ stream->sink->link->ddc,
-+ stream->phy_pix_clk,
-+ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE);
-+
-+ memset(&stream->sink->link->public.cur_link_settings, 0,
-+ sizeof(struct dc_link_settings));
-+
-+ link->link_enc->funcs->enable_tmds_output(
-+ link->link_enc,
-+ pipe_ctx->clock_source->id,
-+ stream->public.timing.display_color_depth,
-+ pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
-+ pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
-+ stream->phy_pix_clk);
-+
-+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-+ dal_ddc_service_read_scdc_data(link->ddc);
-+}
-+
-+/****************************enable_link***********************************/
-+static enum dc_status enable_link(struct pipe_ctx *pipe_ctx)
-+{
-+ enum dc_status status = DC_ERROR_UNEXPECTED;
-+ switch (pipe_ctx->stream->signal) {
-+ case SIGNAL_TYPE_DISPLAY_PORT:
-+ case SIGNAL_TYPE_EDP:
-+ status = enable_link_dp(pipe_ctx);
-+ break;
-+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
-+ status = enable_link_dp_mst(pipe_ctx);
-+ msleep(200);
-+ break;
-+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
-+ case SIGNAL_TYPE_DVI_DUAL_LINK:
-+ case SIGNAL_TYPE_HDMI_TYPE_A:
-+ enable_link_hdmi(pipe_ctx);
-+ status = DC_OK;
-+ break;
-+ case SIGNAL_TYPE_VIRTUAL:
-+ status = DC_OK;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (pipe_ctx->audio && status == DC_OK) {
-+ /* notify audio driver for audio modes of monitor */
-+ pipe_ctx->audio->funcs->az_enable(pipe_ctx->audio);
-+
-+ /* un-mute audio */
-+ /* TODO: audio should be per stream rather than per link */
-+ pipe_ctx->stream_enc->funcs->audio_mute_control(
-+ pipe_ctx->stream_enc, false);
-+ }
-+
-+ return status;
-+}
-+
-+static void disable_link(struct core_link *link, enum signal_type signal)
-+{
-+ /*
-+ * TODO: implement call for dp_set_hw_test_pattern
-+ * it is needed for compliance testing
-+ */
-+
-+ /* 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(signal)) {
-+ /* SST DP, eDP */
-+ if (dc_is_dp_sst_signal(signal))
-+ dp_disable_link_phy(link, signal);
-+ else
-+ dp_disable_link_phy_mst(link, signal);
-+ } else
-+ link->link_enc->funcs->disable_output(link->link_enc, signal);
-+}
-+
-+enum dc_status dc_link_validate_mode_timing(
-+ const struct core_stream *stream,
-+ struct core_link *link,
-+ const struct dc_crtc_timing *timing)
-+{
-+ uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
-+
-+ /* A hack to avoid failing any modes for EDID override feature on
-+ * topology change such as lower quality cable for DP or different dongle
-+ */
-+ if (link->public.remote_sinks[0])
-+ return DC_OK;
-+
-+ if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
-+ return DC_EXCEED_DONGLE_MAX_CLK;
-+
-+ switch (stream->signal) {
-+ case SIGNAL_TYPE_EDP:
-+ 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 *dc_link, uint32_t level,
-+ uint32_t frame_ramp, const struct dc_stream *stream)
-+{
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+ struct dc_context *ctx = link->ctx;
-+ struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
-+ unsigned int controller_id = 0;
-+ int i;
-+ uint32_t dmcu_status;
-+
-+ dm_logger_write(ctx->logger, LOG_BACKLIGHT,
-+ "New Backlight level: %d (0x%X)\n", level, level);
-+
-+ dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS);
-+
-+ /* If DMCU is in reset state, DMCU is uninitialized */
-+ if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) {
-+ link->link_enc->funcs->set_lcd_backlight_level(link->link_enc,
-+ level);
-+ } else {
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-+ == core_stream)
-+ /* dmcu -1 for all controller id values,
-+ * therefore +1 here
-+ */
-+ controller_id = core_dc->current_context->res_ctx.
-+ pipe_ctx[i].tg->inst + 1;
-+ }
-+
-+ link->link_enc->funcs->set_dmcu_backlight_level
-+ (link->link_enc, level,
-+ frame_ramp, controller_id);
-+ }
-+ return true;
-+}
-+
-+
-+bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link)
-+{
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+
-+ if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL)
-+ link->link_enc->funcs->
-+ init_dmcu_backlight_settings(link->link_enc);
-+
-+ return true;
-+}
-+
-+bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level)
-+{
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+ struct dc_context *ctx = link->ctx;
-+
-+ dm_logger_write(ctx->logger, LOG_BACKLIGHT,
-+ "New abm level: %d (0x%X)\n", level, level);
-+
-+ link->link_enc->funcs->set_dmcu_abm_level(link->link_enc, level);
-+ return true;
-+}
-+
-+bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable)
-+{
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+
-+ if (dc_link != NULL && dc_link->psr_caps.psr_version > 0)
-+ link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc,
-+ enable);
-+ return true;
-+}
-+
-+bool dc_link_setup_psr(const struct dc_link *dc_link,
-+ const struct dc_stream *stream)
-+{
-+
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+ struct dc_context *ctx = link->ctx;
-+ struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
-+ struct psr_dmcu_context psr_context = {0};
-+ int i;
-+
-+ psr_context.controllerId = CONTROLLER_ID_UNDEFINED;
-+
-+
-+ if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) {
-+ /* updateSinkPsrDpcdConfig*/
-+ union dpcd_psr_configuration psr_configuration;
-+
-+ memset(&psr_configuration, 0, sizeof(psr_configuration));
-+
-+ psr_configuration.bits.ENABLE = 1;
-+ psr_configuration.bits.CRC_VERIFICATION = 1;
-+ psr_configuration.bits.FRAME_CAPTURE_INDICATION =
-+ dc_link->psr_caps.psr_frame_capture_indication_req;
-+
-+ /* Check for PSR v2*/
-+ if (dc_link->psr_caps.psr_version == 0x2) {
-+ /* For PSR v2 selective update.
-+ * Indicates whether sink should start capturing
-+ * immediately following active scan line,
-+ * or starting with the 2nd active scan line.
-+ */
-+ psr_configuration.bits.LINE_CAPTURE_INDICATION = 0;
-+ /*For PSR v2, determines whether Sink should generate
-+ * IRQ_HPD when CRC mismatch is detected.
-+ */
-+ psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1;
-+ }
-+ dal_ddc_service_write_dpcd_data(
-+ link->ddc,
-+ 368,
-+ &psr_configuration.raw,
-+ sizeof(psr_configuration.raw));
-+
-+ psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel;
-+ if (psr_context.channel == 0)
-+ psr_context.channel = 1;
-+ psr_context.transmitterId = link->link_enc->transmitter;
-+ psr_context.engineId = link->link_enc->preferred_engine;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-+ == core_stream) {
-+ /* dmcu -1 for all controller id values,
-+ * therefore +1 here
-+ */
-+ psr_context.controllerId =
-+ core_dc->current_context->res_ctx.
-+ pipe_ctx[i].tg->inst + 1;
-+ break;
-+ }
-+ }
-+
-+ /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/
-+ psr_context.phyType = PHY_TYPE_UNIPHY;
-+ /*PhyId is associated with the transmitter id*/
-+ psr_context.smuPhyId = link->link_enc->transmitter;
-+
-+ psr_context.crtcTimingVerticalTotal = stream->timing.v_total;
-+ psr_context.vsyncRateHz = div64_u64(div64_u64((stream->
-+ timing.pix_clk_khz * 1000),
-+ stream->timing.v_total),
-+ stream->timing.h_total);
-+
-+ psr_context.psrSupportedDisplayConfig =
-+ (dc_link->psr_caps.psr_version > 0) ? true : false;
-+ psr_context.psrExitLinkTrainingRequired =
-+ dc_link->psr_caps.psr_exit_link_training_required;
-+ psr_context.sdpTransmitLineNumDeadline =
-+ dc_link->psr_caps.psr_sdp_transmit_line_num_deadline;
-+ psr_context.psrFrameCaptureIndicationReq =
-+ dc_link->psr_caps.psr_frame_capture_indication_req;
-+
-+ psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */
-+
-+ psr_context.numberOfControllers =
-+ link->dc->res_pool->res_cap->num_timing_generator;
-+
-+ psr_context.rfb_update_auto_en = true;
-+
-+ /* 2 frames before enter PSR. */
-+ psr_context.timehyst_frames = 2;
-+ /* half a frame
-+ * (units in 100 lines, i.e. a value of 1 represents 100 lines)
-+ */
-+ psr_context.hyst_lines = stream->timing.v_total / 2 / 100;
-+ psr_context.aux_repeats = 10;
-+
-+ psr_context.psr_level.u32all = 0;
-+
-+ /* SMU will perform additional powerdown sequence.
-+ * For unsupported ASICs, set psr_level flag to skip PSR
-+ * static screen notification to SMU.
-+ * (Always set for DAL2, did not check ASIC)
-+ */
-+ psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1;
-+
-+ /* Controls additional delay after remote frame capture before
-+ * continuing power down, default = 0
-+ */
-+ psr_context.frame_delay = 0;
-+
-+ link->link_enc->funcs->setup_dmcu_psr
-+ (link->link_enc, &psr_context);
-+ return true;
-+ } else
-+ return false;
-+
-+}
-+
-+const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link)
-+{
-+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
-+
-+ return &link->link_status;
-+}
-+
-+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 dc_link_settings *link_settings =
-+ &stream->sink->link->public.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(enum dc_color_depth color_depth)
-+{
-+ switch (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 pipe_ctx *pipe_ctx)
-+{
-+ uint32_t bpc;
-+ uint64_t kbps;
-+ struct fixed31_32 peak_kbps;
-+ uint32_t numerator;
-+ uint32_t denominator;
-+
-+ bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth);
-+ kbps = pipe_ctx->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 stream_encoder *stream_enc,
-+ 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_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 pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct core_link *link = stream->sink->link;
-+ struct link_encoder *link_encoder = link->link_enc;
-+ struct stream_encoder *stream_encoder = pipe_ctx->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 */
-+ if (dm_helpers_dp_mst_write_payload_allocation_table(
-+ stream->ctx,
-+ &stream->public,
-+ &proposed_table,
-+ true)) {
-+ update_mst_stream_alloc_table(
-+ link, pipe_ctx->stream_enc, &proposed_table);
-+ }
-+ else
-+ dm_logger_write(link->ctx->logger, LOG_WARNING,
-+ "Failed to update"
-+ "MST allocation table for"
-+ "pipe idx:%d\n",
-+ pipe_ctx->pipe_idx);
-+
-+ dm_logger_write(link->ctx->logger, LOG_MST,
-+ "%s "
-+ "stream_count: %d: \n ",
-+ __func__,
-+ link->mst_stream_alloc_table.stream_count);
-+
-+ for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
-+ dm_logger_write(link->ctx->logger, LOG_MST,
-+ "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);
-+
-+ /* 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(pipe_ctx);
-+ 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 pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct core_link *link = stream->sink->link;
-+ struct link_encoder *link_encoder = link->link_enc;
-+ struct stream_encoder *stream_encoder = pipe_ctx->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) {
-+ if (dm_helpers_dp_mst_write_payload_allocation_table(
-+ stream->ctx,
-+ &stream->public,
-+ &proposed_table,
-+ false)) {
-+
-+ update_mst_stream_alloc_table(
-+ link, pipe_ctx->stream_enc, &proposed_table);
-+ }
-+ else {
-+ dm_logger_write(link->ctx->logger, LOG_WARNING,
-+ "Failed to update"
-+ "MST allocation table for"
-+ "pipe idx:%d\n",
-+ pipe_ctx->pipe_idx);
-+ }
-+ }
-+
-+ dm_logger_write(link->ctx->logger, LOG_MST,
-+ "%s"
-+ "stream_count: %d: ",
-+ __func__,
-+ link->mst_stream_alloc_table.stream_count);
-+
-+ for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
-+ dm_logger_write(link->ctx->logger, LOG_MST,
-+ "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 pipe_ctx *pipe_ctx)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc);
-+
-+ if (DC_OK != enable_link(pipe_ctx)) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ core_dc->hwss.enable_stream(pipe_ctx);
-+
-+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
-+ allocate_mst_payload(pipe_ctx);
-+}
-+
-+void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc);
-+
-+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
-+ deallocate_mst_payload(pipe_ctx);
-+
-+ core_dc->hwss.disable_stream(pipe_ctx);
-+
-+ disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
-new file mode 100644
-index 0000000..6379ccf
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
-@@ -0,0 +1,1098 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "gpio_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(sizeof(struct i2c_payloads));
-+
-+ if (!payloads)
-+ return NULL;
-+
-+ if (dal_vector_construct(
-+ &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
-+ return payloads;
-+
-+ dm_free(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);
-+ *p = NULL;
-+
-+}
-+
-+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
-+{
-+ struct aux_payloads *payloads;
-+
-+ payloads = dm_alloc(sizeof(struct aux_payloads));
-+
-+ if (!payloads)
-+ return NULL;
-+
-+ if (dal_vector_construct(
-+ &payloads->payloads, ctx, count, sizeof(struct aux_payloads)))
-+ return payloads;
-+
-+ dm_free(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);
-+ *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);
-+
-+ struct gpio_service *gpio_service = init_data->ctx->gpio_service;
-+ struct graphics_object_i2c_info i2c_info;
-+ struct gpio_ddc_hw_info hw_info;
-+ struct dc_bios *dcb = init_data->ctx->dc_bios;
-+
-+ ddc_service->link = init_data->link;
-+ ddc_service->ctx = init_data->ctx;
-+
-+ if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
-+ ddc_service->ddc_pin = NULL;
-+ } else {
-+ hw_info.ddc_channel = i2c_info.i2c_line;
-+ hw_info.hw_supported = i2c_info.i2c_hw_assist;
-+
-+ ddc_service->ddc_pin = dal_gpio_create_ddc(
-+ gpio_service,
-+ i2c_info.gpio_info.clk_a_register_index,
-+ 1 << i2c_info.gpio_info.clk_a_shift,
-+ &hw_info);
-+ }
-+
-+ ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
-+ ddc_service->flags.FORCE_READ_REPEATED_START = false;
-+ ddc_service->flags.EDID_STRESS_READ = false;
-+
-+ 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(sizeof(struct ddc_service));
-+
-+ if (!ddc_service)
-+ return NULL;
-+
-+ if (construct(ddc_service, init_data))
-+ return ddc_service;
-+
-+ dm_free(ddc_service);
-+ return NULL;
-+}
-+
-+static void destruct(struct ddc_service *ddc)
-+{
-+ if (ddc->ddc_pin)
-+ dal_gpio_destroy_ddc(&ddc->ddc_pin);
-+}
-+
-+void dal_ddc_service_destroy(struct ddc_service **ddc)
-+{
-+ if (!ddc || !*ddc) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+ destruct(*ddc);
-+ dm_free(*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 core_link *link = ddc->link;
-+
-+ if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_4 &&
-+ !memcmp(link->dpcd_caps.branch_dev_name,
-+ DP_DVI_CONVERTER_ID_4,
-+ sizeof(link->dpcd_caps.branch_dev_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 = ddc->ctx->dc->caps.i2c_speed_in_khz };
-+
-+ 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(
-+ ddc->ctx->i2caux,
-+ 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(
-+ ddc->ctx->i2caux,
-+ ddc->ddc_pin,
-+ &cmd);
-+
-+ if (false == result)
-+ dm_logger_write(
-+ ddc->ctx->logger, LOG_ERROR,
-+ "%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 = ddc->ctx->dc->caps.i2c_speed_in_khz };
-+
-+ 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)) {
-+ 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)
-+{
-+ 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))) {
-+ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
-+ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
-+ "DP-DVI passive dongle %dMhz: ",
-+ DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
-+ 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) {
-+ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
-+ sizeof(type2_dongle_buf),
-+ "DP-DVI passive dongle %dMhz: ",
-+ DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
-+ } else {
-+ if (is_valid_hdmi_signature == true) {
-+ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
-+ sizeof(type2_dongle_buf),
-+ "Type 2 DP-HDMI passive dongle %dMhz: ",
-+ max_tmds_clk);
-+ } else {
-+ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
-+ sizeof(type2_dongle_buf),
-+ "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ",
-+ 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) {
-+ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
-+ sizeof(type2_dongle_buf),
-+ "Type 1 DP-HDMI passive dongle %dMhz: ",
-+ sink_cap->max_hdmi_pixel_clock / 1000);
-+ } else {
-+ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
-+
-+ CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
-+ sizeof(type2_dongle_buf),
-+ "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ",
-+ sink_cap->max_hdmi_pixel_clock / 1000);
-+ }
-+ }
-+
-+ 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(
-+ ddc->ctx->i2caux,
-+ 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 = ddc->ctx->dc->caps.i2c_speed_in_khz };
-+
-+ 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;
-+}
-+
-+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(
-+ ddc->ctx->i2caux,
-+ 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(
-+ ddc->ctx->i2caux,
-+ 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_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/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
-new file mode 100644
-index 0000000..2585ec3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
-@@ -0,0 +1,2462 @@
-+/* 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"
-+
-+#include "core_dc.h"
-+
-+/* maximum pre emphasis level allowed for each voltage swing level*/
-+static const enum dc_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 dc_link_settings link_training_fallback_table[] = {
-+/* 4320 Mbytes/sec*/
-+{ LANE_COUNT_FOUR, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED },
-+/* 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 },
-+/* 2160 Mbytes/sec*/
-+{ LANE_COUNT_TWO, LINK_RATE_HIGH3, 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 },
-+/* 1080 Mbytes/sec*/
-+{ LANE_COUNT_ONE, LINK_RATE_HIGH3, 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)
-+{
-+ union training_aux_rd_interval 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,
-+ (uint8_t *)&training_rd_interval,
-+ sizeof(training_rd_interval));
-+
-+ if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
-+ default_wait_in_micro_secs =
-+ training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
-+ }
-+
-+ udelay(default_wait_in_micro_secs);
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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);
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
-+ "%s\n %x pattern = %x\n",
-+ __func__,
-+ DPCD_ADDRESS_TRAINING_PATTERN_SET,
-+ dpcd_pattern.v1_4.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));
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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;
-+ case HW_DP_TRAINING_PATTERN_4:
-+ dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
-+ break;
-+ default:
-+ ASSERT(0);
-+ dm_logger_write(link->ctx->logger, LOG_HW_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.v1_4.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;
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
-+ "%s\n %x pattern = %x\n",
-+ __func__,
-+ DPCD_ADDRESS_TRAINING_PATTERN_SET,
-+ dpcd_pattern.v1_4.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
-+ memmove(
-+ &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset],
-+ dpcd_lane,
-+ size_in_bytes);
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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->public.cur_lane_setting = lt_settings->lane_settings[0];
-+}
-+
-+static bool is_cr_done(enum dc_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 dc_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 dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
-+ enum dc_voltage_swing voltage)
-+{
-+ enum dc_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 dc_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;
-+
-+ 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];
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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]);
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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 dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
-+ VOLTAGE_SWING_LANE);
-+ request_settings.lane_settings[lane].PRE_EMPHASIS =
-+ (enum dc_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);
-+ }
-+ */
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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->public.cur_lane_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 dc_link_dp_set_drive_settings(
-+ struct dc_link *link,
-+ struct link_training_settings *lt_settings)
-+{
-+ struct core_link *core_link = DC_LINK_TO_CORE(link);
-+ /* program ASIC PHY settings*/
-+ dp_set_hw_lane_settings(core_link, lt_settings);
-+
-+ /* Notify DP sink the PHY settings from source */
-+ dpcd_set_lane_settings(core_link, lt_settings);
-+}
-+
-+static bool perform_post_lt_adj_req_sequence(
-+ struct core_link *link,
-+ struct link_training_settings *lt_settings)
-+{
-+ enum dc_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);
-+
-+ dc_link_dp_set_drive_settings(&link->public,
-+ lt_settings);
-+ break;
-+ }
-+
-+ msleep(1);
-+ }
-+
-+ if (!req_drv_setting_changed) {
-+ dm_logger_write(link->ctx->logger, LOG_WARNING,
-+ "%s: Post Link Training Adjust Request Timed out\n",
-+ __func__);
-+
-+ ASSERT(0);
-+ return true;
-+ }
-+ }
-+ dm_logger_write(link->ctx->logger, LOG_WARNING,
-+ "%s: Post Link Training Adjust Request limit reached\n",
-+ __func__);
-+
-+ ASSERT(0);
-+ return true;
-+
-+}
-+
-+static enum hw_dp_training_pattern get_supported_tp(struct core_link *link)
-+{
-+ enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2;
-+ struct encoder_feature_support *features = &link->link_enc->features;
-+ struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
-+
-+ if (features->flags.bits.IS_TPS3_CAPABLE)
-+ highest_tp = HW_DP_TRAINING_PATTERN_3;
-+
-+ if (features->flags.bits.IS_TPS4_CAPABLE)
-+ highest_tp = HW_DP_TRAINING_PATTERN_4;
-+
-+ if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
-+ highest_tp >= HW_DP_TRAINING_PATTERN_4)
-+ return HW_DP_TRAINING_PATTERN_4;
-+
-+ if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
-+ highest_tp >= HW_DP_TRAINING_PATTERN_3)
-+ return HW_DP_TRAINING_PATTERN_3;
-+
-+ return HW_DP_TRAINING_PATTERN_2;
-+}
-+
-+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 dc_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}}};;
-+
-+ hw_tr_pattern = get_supported_tp(link);
-+
-+ 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 dc_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)) {
-+
-+ memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
-+ 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);
-+ dm_logger_write(link->ctx->logger, LOG_ERROR,
-+ "%s: Link Training Error, could not \
-+ get CR after %d tries. \
-+ Possibly voltage swing issue", __func__,
-+ LINK_TRAINING_MAX_CR_RETRY);
-+
-+ }
-+
-+ return false;
-+}
-+
-+static inline bool perform_link_training_int(
-+ struct core_link *link,
-+ struct link_training_settings *lt_settings,
-+ bool status)
-+{
-+ union lane_count_set lane_count_set = { {0} };
-+ union dpcd_training_pattern dpcd_pattern = { {0} };
-+
-+ /* 3. set training not in progress*/
-+ dpcd_pattern.v1_4.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, NULL, 0);
-+
-+ /*
-+ * 5. post training adjust if required
-+ * If the upstream DPTX and downstream DPRX both support TPS4,
-+ * TPS4 must be used instead of POST_LT_ADJ_REQ.
-+ */
-+ if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 &&
-+ get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
-+ return status;
-+
-+ if (status &&
-+ 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));
-+
-+ return status;
-+}
-+
-+bool dc_link_dp_perform_link_training(
-+ struct dc_link *link,
-+ const struct dc_link_settings *link_setting,
-+ bool skip_video_pattern)
-+{
-+ struct core_link *core_link = DC_LINK_TO_CORE(link);
-+ bool status;
-+
-+ char *link_rate = "Unknown";
-+ struct link_training_settings lt_settings;
-+
-+ status = false;
-+ 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(core_link, &lt_settings);
-+
-+ /* 2. perform link training (set link training done
-+ * to false is done as well)*/
-+ if (perform_clock_recovery_sequence(core_link, &lt_settings)) {
-+
-+ if (perform_channel_equalization_sequence(core_link,
-+ &lt_settings))
-+ status = true;
-+ }
-+
-+ if (status || !skip_video_pattern)
-+ status = perform_link_training_int(core_link,
-+ &lt_settings, status);
-+
-+ /* 6. print status message*/
-+ switch (lt_settings.link_settings.link_rate) {
-+
-+ case LINK_RATE_LOW:
-+ link_rate = "RBR";
-+ break;
-+ case LINK_RATE_HIGH:
-+ link_rate = "HBR";
-+ break;
-+ case LINK_RATE_HIGH2:
-+ link_rate = "HBR2";
-+ break;
-+ case LINK_RATE_RBR2:
-+ link_rate = "RBR2";
-+ break;
-+ case LINK_RATE_HIGH3:
-+ link_rate = "HBR3";
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ /* Connectivity log: link training */
-+ CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d",
-+ link_rate,
-+ lt_settings.link_settings.lane_count,
-+ status ? "pass" : "fail",
-+ lt_settings.lane_settings[0].VOLTAGE_SWING,
-+ lt_settings.lane_settings[0].PRE_EMPHASIS);
-+
-+ return status;
-+}
-+
-+
-+bool perform_link_training_with_retries(
-+ struct core_link *link,
-+ const struct dc_link_settings *link_setting,
-+ bool skip_video_pattern,
-+ int attempts)
-+{
-+ uint8_t j;
-+ uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
-+
-+ for (j = 0; j < attempts; ++j) {
-+
-+ if (dc_link_dp_perform_link_training(
-+ &link->public,
-+ link_setting,
-+ skip_video_pattern))
-+ return true;
-+
-+ msleep(delay_between_attempts);
-+ delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
-+ }
-+
-+ return false;
-+}
-+
-+/*TODO add more check to see if link support request link configuration */
-+static bool is_link_setting_supported(
-+ const struct dc_link_settings *link_setting,
-+ const struct dc_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 dc_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 dc_link_settings *link_setting,
-+ const struct dc_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);
-+}
-+
-+static struct dc_link_settings get_max_link_cap(struct core_link *link)
-+{
-+ /* Set Default link settings */
-+ struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
-+ LINK_SPREAD_05_DOWNSPREAD_30KHZ};
-+
-+ /* Higher link settings based on feature supported */
-+ if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE)
-+ max_link_cap.link_rate = LINK_RATE_HIGH2;
-+
-+ if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
-+ max_link_cap.link_rate = LINK_RATE_HIGH3;
-+
-+ /* Lower link settings based on sink's link cap */
-+ if (link->public.reported_link_cap.lane_count < max_link_cap.lane_count)
-+ max_link_cap.lane_count =
-+ link->public.reported_link_cap.lane_count;
-+ if (link->public.reported_link_cap.link_rate < max_link_cap.link_rate)
-+ max_link_cap.link_rate =
-+ link->public.reported_link_cap.link_rate;
-+ if (link->public.reported_link_cap.link_spread <
-+ max_link_cap.link_spread)
-+ max_link_cap.link_spread =
-+ link->public.reported_link_cap.link_spread;
-+ return max_link_cap;
-+}
-+
-+bool dp_hbr_verify_link_cap(
-+ struct core_link *link,
-+ struct dc_link_settings *known_limit_link_setting)
-+{
-+ struct dc_link_settings max_link_cap = {0};
-+ bool success;
-+ bool skip_link_training;
-+ const struct dc_link_settings *cur;
-+ bool skip_video_pattern;
-+ uint32_t i;
-+ struct clock_source *dp_cs;
-+ enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
-+
-+ success = false;
-+ skip_link_training = false;
-+
-+ max_link_cap = get_max_link_cap(link);
-+
-+ /* 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);
-+
-+ dp_cs = link->dc->res_pool->dp_clock_source;
-+
-+ if (dp_cs)
-+ dp_cs_id = dp_cs->id;
-+ else {
-+ /*
-+ * dp clock source is not initialized for some reason.
-+ * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
-+ */
-+ ASSERT(dp_cs);
-+ }
-+
-+ 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,
-+ dp_cs_id,
-+ cur);
-+
-+ if (skip_link_training)
-+ success = true;
-+ else {
-+ success = dc_link_dp_perform_link_training(
-+ &link->public,
-+ cur,
-+ skip_video_pattern);
-+ }
-+
-+ if (success)
-+ link->public.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->public.verified_link_cap.lane_count = LANE_COUNT_ONE;
-+ link->public.verified_link_cap.link_rate = LINK_RATE_LOW;
-+
-+ link->public.verified_link_cap.link_spread =
-+ LINK_SPREAD_DISABLED;
-+ }
-+
-+ link->public.max_link_setting = link->public.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 dc_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 dc_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;
-+
-+ /* We always use verified link settings */
-+ link_setting = &link->public.verified_link_cap;
-+
-+ /* TODO: DYNAMIC_VALIDATION needs to be implemented */
-+ /*if (flags.DYNAMIC_VALIDATION == 1 &&
-+ link->public.verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
-+ link_setting = &link->public.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 dc_link_settings *link_setting)
-+{
-+
-+ const struct dc_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->public.reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) &&
-+ (link->public.reported_link_cap.link_rate <=
-+ link->public.verified_link_cap.link_rate)) {
-+
-+ link_bw = bandwidth_in_kbps_from_link_settings(
-+ &link->public.reported_link_cap);
-+
-+ if (req_bw < link_bw) {
-+ *link_setting = link->public.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->public.max_link_setting)) {
-+ *link_setting = *cur_ls;
-+ return;
-+ }
-+ }
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ ASSERT(link->public.verified_link_cap.lane_count !=
-+ LANE_COUNT_UNKNOWN);
-+
-+ *link_setting = link->public.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->public.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;
-+ dm_logger_write(link->ctx->logger, LOG_HW_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->public.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) {
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_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->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
-+ (link->public.type == dc_connection_mst_branch) ||
-+ is_dp_active_dongle(link))
-+ return true;
-+
-+ return false;
-+}
-+
-+static bool handle_hpd_irq_psr_sink(const struct core_link *link)
-+{
-+ union dpcd_psr_configuration psr_configuration;
-+
-+ if (link->public.psr_caps.psr_version == 0)
-+ return false;
-+
-+ dal_ddc_service_read_dpcd_data(
-+ link->ddc,
-+ 368 /*DpcdAddress_PSR_Enable_Cfg*/,
-+ &psr_configuration.raw,
-+ sizeof(psr_configuration.raw));
-+
-+ if (psr_configuration.bits.ENABLE) {
-+ unsigned char dpcdbuf[3] = {0};
-+ union psr_error_status psr_error_status;
-+ union psr_sink_psr_status psr_sink_psr_status;
-+
-+ dal_ddc_service_read_dpcd_data(
-+ link->ddc,
-+ 0x2006 /*DpcdAddress_PSR_Error_Status*/,
-+ (unsigned char *) dpcdbuf,
-+ sizeof(dpcdbuf));
-+
-+ /*DPCD 2006h ERROR STATUS*/
-+ psr_error_status.raw = dpcdbuf[0];
-+ /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
-+ psr_sink_psr_status.raw = dpcdbuf[2];
-+
-+ if (psr_error_status.bits.LINK_CRC_ERROR ||
-+ psr_error_status.bits.RFB_STORAGE_ERROR) {
-+ /* Acknowledge and clear error bits */
-+ dal_ddc_service_write_dpcd_data(
-+ link->ddc,
-+ 8198 /*DpcdAddress_PSR_Error_Status*/,
-+ &psr_error_status.raw,
-+ sizeof(psr_error_status.raw));
-+
-+ /* PSR error, disable and re-enable PSR */
-+ dc_link_set_psr_enable(&link->public, false);
-+ dc_link_set_psr_enable(&link->public, true);
-+
-+ return true;
-+ } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
-+ PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
-+ /* No error is detect, PSR is active.
-+ * We should return with IRQ_HPD handled without
-+ * checking for loss of sync since PSR would have
-+ * powered down main link.
-+ */
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+static void dp_test_send_link_training(struct core_link *link)
-+{
-+ struct dc_link_settings link_settings;
-+
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_LANE_COUNT,
-+ (unsigned char *)(&link_settings.lane_count),
-+ 1);
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_LINK_RATE,
-+ (unsigned char *)(&link_settings.link_rate),
-+ 1);
-+
-+ /* Set preferred link settings */
-+ link->public.verified_link_cap.lane_count = link_settings.lane_count;
-+ link->public.verified_link_cap.link_rate = link_settings.link_rate;
-+
-+ dp_retrain_link(link);
-+}
-+
-+static void dp_test_send_phy_test_pattern(struct core_link *link)
-+{
-+ union phy_test_pattern dpcd_test_pattern;
-+ union lane_adjust dpcd_lane_adjustment[2];
-+ unsigned char dpcd_post_cursor_2_adjustment = 0;
-+ unsigned char test_80_bit_pattern[
-+ (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 -
-+ DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
-+ enum dp_test_pattern test_pattern;
-+ struct dc_link_training_settings link_settings;
-+ union lane_adjust dpcd_lane_adjust;
-+ unsigned int lane;
-+ struct link_training_settings link_training_settings;
-+ int i = 0;
-+
-+ dpcd_test_pattern.raw = 0;
-+ memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
-+ memset(&link_settings, 0, sizeof(link_settings));
-+
-+ /* get phy test pattern and pattern parameters from DP receiver */
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_PHY_PATTERN,
-+ &dpcd_test_pattern.raw,
-+ sizeof(dpcd_test_pattern));
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1,
-+ &dpcd_lane_adjustment[0].raw,
-+ sizeof(dpcd_lane_adjustment));
-+
-+ /*get post cursor 2 parameters
-+ * For DP 1.1a or eariler, this DPCD register's value is 0
-+ * For DP 1.2 or later:
-+ * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
-+ * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
-+ */
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2,
-+ &dpcd_post_cursor_2_adjustment,
-+ sizeof(dpcd_post_cursor_2_adjustment));
-+
-+ /* translate request */
-+ switch (dpcd_test_pattern.bits.PATTERN) {
-+ case PHY_TEST_PATTERN_D10_2:
-+ test_pattern = DP_TEST_PATTERN_D102;
-+ break;
-+ case PHY_TEST_PATTERN_SYMBOL_ERROR:
-+ test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
-+ break;
-+ case PHY_TEST_PATTERN_PRBS7:
-+ test_pattern = DP_TEST_PATTERN_PRBS7;
-+ break;
-+ case PHY_TEST_PATTERN_80BIT_CUSTOM:
-+ test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
-+ break;
-+ case PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE:
-+ test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
-+ break;
-+ default:
-+ test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
-+ break;
-+ }
-+
-+ if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM)
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0,
-+ test_80_bit_pattern,
-+ sizeof(test_80_bit_pattern));
-+
-+ /* prepare link training settings */
-+ link_settings.link = link->public.cur_link_settings;
-+
-+ for (lane = 0; lane <
-+ (unsigned int)(link->public.cur_link_settings.lane_count);
-+ lane++) {
-+ dpcd_lane_adjust.raw =
-+ get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
-+ link_settings.lane_settings[lane].VOLTAGE_SWING =
-+ (enum dc_voltage_swing)
-+ (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
-+ link_settings.lane_settings[lane].PRE_EMPHASIS =
-+ (enum dc_pre_emphasis)
-+ (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
-+ link_settings.lane_settings[lane].POST_CURSOR2 =
-+ (enum dc_post_cursor2)
-+ ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
-+ }
-+
-+ for (i = 0; i < 4; i++)
-+ link_training_settings.lane_settings[i] =
-+ link_settings.lane_settings[i];
-+ link_training_settings.link_settings = link_settings.link;
-+ link_training_settings.allow_invalid_msa_timing_param = false;
-+ /*Usage: Measure DP physical lane signal
-+ * by DP SI test equipment automatically.
-+ * PHY test pattern request is generated by equipment via HPD interrupt.
-+ * HPD needs to be active all the time. HPD should be active
-+ * all the time. Do not touch it.
-+ * forward request to DS
-+ */
-+ dc_link_dp_set_test_pattern(
-+ &link->public,
-+ test_pattern,
-+ &link_training_settings,
-+ test_80_bit_pattern,
-+ (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 -
-+ DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1);
-+}
-+
-+static void dp_test_send_link_test_pattern(struct core_link *link)
-+{
-+ union link_test_pattern dpcd_test_pattern;
-+ union test_misc dpcd_test_params;
-+ enum dp_test_pattern test_pattern;
-+
-+ memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
-+ memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
-+
-+ /* get link test pattern and pattern parameters */
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_PATTERN,
-+ &dpcd_test_pattern.raw,
-+ sizeof(dpcd_test_pattern));
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_MISC1,
-+ &dpcd_test_params.raw,
-+ sizeof(dpcd_test_params));
-+
-+ switch (dpcd_test_pattern.bits.PATTERN) {
-+ case LINK_TEST_PATTERN_COLOR_RAMP:
-+ test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
-+ break;
-+ case LINK_TEST_PATTERN_VERTICAL_BARS:
-+ test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
-+ break; /* black and white */
-+ case LINK_TEST_PATTERN_COLOR_SQUARES:
-+ test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
-+ TEST_DYN_RANGE_VESA ?
-+ DP_TEST_PATTERN_COLOR_SQUARES :
-+ DP_TEST_PATTERN_COLOR_SQUARES_CEA);
-+ break;
-+ default:
-+ test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
-+ break;
-+ }
-+
-+ dc_link_dp_set_test_pattern(
-+ &link->public,
-+ test_pattern,
-+ NULL,
-+ NULL,
-+ 0);
-+}
-+
-+static void handle_automated_test(struct core_link *link)
-+{
-+ union test_request test_request;
-+ union test_response test_response;
-+
-+ memset(&test_request, 0, sizeof(test_request));
-+ memset(&test_response, 0, sizeof(test_response));
-+
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_REQUEST,
-+ &test_request.raw,
-+ sizeof(union test_request));
-+ if (test_request.bits.LINK_TRAINING) {
-+ /* ACK first to let DP RX test box monitor LT sequence */
-+ test_response.bits.ACK = 1;
-+ core_link_write_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_RESPONSE,
-+ &test_response.raw,
-+ sizeof(test_response));
-+ dp_test_send_link_training(link);
-+ /* no acknowledge request is needed again */
-+ test_response.bits.ACK = 0;
-+ }
-+ if (test_request.bits.LINK_TEST_PATTRN) {
-+ dp_test_send_link_test_pattern(link);
-+ link->public.compliance_test_state.bits.
-+ SET_TEST_PATTERN_PENDING = 1;
-+ }
-+ if (test_request.bits.PHY_TEST_PATTERN) {
-+ dp_test_send_phy_test_pattern(link);
-+ test_response.bits.ACK = 1;
-+ }
-+ if (!test_request.raw)
-+ /* no requests, revert all test signals
-+ * TODO: revert all test signals
-+ */
-+ test_response.bits.ACK = 1;
-+ /* send request acknowledgment */
-+ if (test_response.bits.ACK)
-+ core_link_write_dpcd(
-+ link,
-+ DPCD_ADDRESS_TEST_RESPONSE,
-+ &test_response.raw,
-+ sizeof(test_response));
-+}
-+
-+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}}}};
-+ union device_service_irq device_service_clear = {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*/
-+
-+ dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
-+ "%s: Got short pulse HPD on link %d\n",
-+ __func__, link->public.link_index);
-+
-+ /* 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) {
-+ dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
-+ "%s: DPCD read failed to obtain irq data\n",
-+ __func__);
-+ return false;
-+ }
-+
-+ if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
-+ device_service_clear.bits.AUTOMATED_TEST = 1;
-+ core_link_write_dpcd(
-+ link,
-+ DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR,
-+ &device_service_clear.raw,
-+ sizeof(device_service_clear.raw));
-+ device_service_clear.raw = 0;
-+ handle_automated_test(link);
-+ return false;
-+ }
-+
-+ if (!allow_hpd_rx_irq(link)) {
-+ dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
-+ "%s: skipping HPD handling on %d\n",
-+ __func__, link->public.link_index);
-+ return false;
-+ }
-+
-+ if (handle_hpd_irq_psr_sink(link))
-+ /* PSR-related error was detected and handled */
-+ return true;
-+
-+ /* If PSR-related error handled, Main link may be off,
-+ * so do not handle as a normal sink status change interrupt.
-+ */
-+
-+ /* 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)) {
-+ /* Connectivity log: link loss */
-+ CONN_DATA_LINK_LOSS(link,
-+ hpd_irq_dpcd_data.raw,
-+ sizeof(hpd_irq_dpcd_data),
-+ "Status: ");
-+
-+ perform_link_training_with_retries(link,
-+ &link->public.cur_link_settings,
-+ true, LINK_TRAINING_ATTEMPTS);
-+
-+ status = false;
-+ }
-+
-+ if (link->public.type == dc_connection_active_dongle &&
-+ 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);
-+
-+ {
-+ struct dp_device_vendor_id dp_id;
-+
-+ /* 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];
-+
-+ memmove(
-+ link->dpcd_caps.branch_dev_name,
-+ dp_id.ieee_device_id,
-+ sizeof(dp_id.ieee_device_id));
-+ }
-+
-+ {
-+ struct dp_sink_hw_fw_revision dp_hw_fw_revision;
-+
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_BRANCH_REVISION_START,
-+ (uint8_t *)&dp_hw_fw_revision,
-+ sizeof(dp_hw_fw_revision));
-+
-+ link->dpcd_caps.branch_hw_revision =
-+ dp_hw_fw_revision.ieee_hw_rev;
-+ }
-+}
-+
-+static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data,
-+ int length)
-+{
-+ int retry = 0;
-+ 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];
-+
-+ 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_psr_link_cap(struct core_link *link,
-+ enum edp_revision edp_revision)
-+{
-+ if (edp_revision >= EDP_REVISION_13) {
-+ core_link_read_dpcd(link,
-+ DPCD_ADDRESS_PSR_SUPPORT_VER,
-+ (uint8_t *)(&link->public.psr_caps),
-+ sizeof(link->public.psr_caps));
-+ if (link->public.psr_caps.psr_version != 0) {
-+ unsigned char psr_capability = 0;
-+
-+ core_link_read_dpcd(link,
-+ DPCD_ADDRESS_PSR_CAPABILITY,
-+ &psr_capability,
-+ sizeof(psr_capability));
-+ /* Bit 0 determines whether fast link training is
-+ * required on PSR exit. If set to 0, link training
-+ * is required. If set to 1, sink must lock within
-+ * five Idle Patterns after Main Link is turned on.
-+ */
-+ link->public.psr_caps.psr_exit_link_training_required
-+ = !(psr_capability & 0x1);
-+
-+ psr_capability = (psr_capability >> 1) & 0x7;
-+ link->public.psr_caps.psr_rfb_setup_time =
-+ 55 * (6 - psr_capability);
-+ }
-+ }
-+}
-+
-+static void retrieve_link_cap(struct core_link *link)
-+{
-+ uint8_t dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL - DPCD_ADDRESS_DPCD_REV + 1];
-+
-+ union down_stream_port_count down_strm_port_count;
-+ union edp_configuration_cap edp_config_cap;
-+ union dp_downstream_port_present ds_port = { 0 };
-+
-+ memset(dpcd_data, '\0', sizeof(dpcd_data));
-+ memset(&down_strm_port_count,
-+ '\0', sizeof(union down_stream_port_count));
-+ memset(&edp_config_cap, '\0',
-+ sizeof(union edp_configuration_cap));
-+
-+ 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];
-+
-+ {
-+ union training_aux_rd_interval aux_rd_interval;
-+
-+ aux_rd_interval.raw =
-+ dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL];
-+
-+ if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) {
-+ core_link_read_dpcd(
-+ link,
-+ DPCD_ADDRESS_DP13_DPCD_REV,
-+ dpcd_data,
-+ sizeof(dpcd_data));
-+ }
-+ }
-+
-+ 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];
-+
-+ link->dpcd_caps.max_down_spread.raw = dpcd_data[
-+ DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV];
-+
-+ link->public.reported_link_cap.lane_count =
-+ link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
-+ link->public.reported_link_cap.link_rate = dpcd_data[
-+ DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV];
-+ link->public.reported_link_cap.link_spread =
-+ link->dpcd_caps.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;
-+
-+ link->public.test_pattern_enabled = false;
-+ link->public.compliance_test_state.raw = 0;
-+
-+ link->public.psr_caps.psr_exit_link_training_required = false;
-+ link->public.psr_caps.psr_frame_capture_indication_req = false;
-+ link->public.psr_caps.psr_rfb_setup_time = 0;
-+ link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0;
-+ link->public.psr_caps.psr_version = 0;
-+
-+ /* 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));
-+ }
-+
-+ /* Connectivity log: detection */
-+ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
-+
-+ /* TODO: Confirm if need retrieve_psr_link_cap */
-+ retrieve_psr_link_cap(link, link->edp_revision);
-+}
-+
-+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->public.verified_link_cap = link->public.reported_link_cap;
-+ } else {
-+ dp_hbr_verify_link_cap(link,
-+ &link->public.reported_link_cap);
-+ }
-+ /* TODO save sink caps in link->sink */
-+}
-+
-+void dc_link_dp_enable_hpd(const struct dc_link *link)
-+{
-+ struct core_link *core_link = DC_LINK_TO_CORE(link);
-+ struct link_encoder *encoder = core_link->link_enc;
-+
-+ if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
-+ encoder->funcs->enable_hpd(encoder);
-+}
-+
-+void dc_link_dp_disable_hpd(const struct dc_link *link)
-+{
-+ struct core_link *core_link = DC_LINK_TO_CORE(link);
-+ struct link_encoder *encoder = core_link->link_enc;
-+
-+ if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
-+ encoder->funcs->disable_hpd(encoder);
-+}
-+
-+static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
-+{
-+ if (test_pattern == DP_TEST_PATTERN_D102 ||
-+ test_pattern == DP_TEST_PATTERN_SYMBOL_ERROR ||
-+ test_pattern == DP_TEST_PATTERN_PRBS7 ||
-+ test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM ||
-+ test_pattern == DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE ||
-+ test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN1 ||
-+ test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN2 ||
-+ test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN3 ||
-+ test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN4 ||
-+ test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+static void set_crtc_test_pattern(struct core_link *link,
-+ struct pipe_ctx *pipe_ctx,
-+ enum dp_test_pattern test_pattern)
-+{
-+ enum controller_dp_test_pattern controller_test_pattern;
-+ enum dc_color_depth color_depth = pipe_ctx->
-+ stream->public.timing.display_color_depth;
-+ struct bit_depth_reduction_params params;
-+
-+ memset(&params, 0, sizeof(params));
-+
-+ switch (test_pattern) {
-+ case DP_TEST_PATTERN_COLOR_SQUARES:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
-+ break;
-+ case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
-+ break;
-+ case DP_TEST_PATTERN_VERTICAL_BARS:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
-+ break;
-+ case DP_TEST_PATTERN_HORIZONTAL_BARS:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
-+ break;
-+ case DP_TEST_PATTERN_COLOR_RAMP:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
-+ break;
-+ default:
-+ controller_test_pattern =
-+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
-+ break;
-+ }
-+
-+ switch (test_pattern) {
-+ case DP_TEST_PATTERN_COLOR_SQUARES:
-+ case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
-+ case DP_TEST_PATTERN_VERTICAL_BARS:
-+ case DP_TEST_PATTERN_HORIZONTAL_BARS:
-+ case DP_TEST_PATTERN_COLOR_RAMP:
-+ {
-+ /* disable bit depth reduction */
-+ pipe_ctx->stream->bit_depth_params = params;
-+ pipe_ctx->opp->funcs->
-+ opp_program_bit_depth_reduction(pipe_ctx->opp, &params);
-+
-+ pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg,
-+ controller_test_pattern, color_depth);
-+ }
-+ break;
-+ case DP_TEST_PATTERN_VIDEO_MODE:
-+ {
-+ /* restore bitdepth reduction */
-+ link->dc->current_context->res_ctx.pool->funcs->
-+ build_bit_depth_reduction_params(pipe_ctx->stream,
-+ &params);
-+ pipe_ctx->stream->bit_depth_params = params;
-+ pipe_ctx->opp->funcs->
-+ opp_program_bit_depth_reduction(pipe_ctx->opp, &params);
-+
-+ pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg,
-+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-+ color_depth);
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+}
-+
-+bool dc_link_dp_set_test_pattern(
-+ const struct dc_link *link,
-+ enum dp_test_pattern test_pattern,
-+ const struct link_training_settings *p_link_settings,
-+ const unsigned char *p_custom_pattern,
-+ unsigned int cust_pattern_size)
-+{
-+ struct core_link *core_link = DC_LINK_TO_CORE(link);
-+ struct pipe_ctx *pipes =
-+ core_link->dc->current_context->res_ctx.pipe_ctx;
-+ struct pipe_ctx pipe_ctx = pipes[0];
-+ unsigned int lane;
-+ unsigned int i;
-+ unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
-+ union dpcd_training_pattern training_pattern;
-+ union test_response test_response;
-+ enum dpcd_phy_test_patterns pattern;
-+
-+ memset(&training_pattern, 0, sizeof(training_pattern));
-+ memset(&test_response, 0, sizeof(test_response));
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (pipes[i].stream->sink->link == core_link) {
-+ pipe_ctx = pipes[i];
-+ break;
-+ }
-+ }
-+
-+ /* Reset CRTC Test Pattern if it is currently running and request
-+ * is VideoMode Reset DP Phy Test Pattern if it is currently running
-+ * and request is VideoMode
-+ */
-+ if (core_link->public.test_pattern_enabled && test_pattern ==
-+ DP_TEST_PATTERN_VIDEO_MODE) {
-+ /* Set CRTC Test Pattern */
-+ set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern);
-+ dp_set_hw_test_pattern(core_link, test_pattern,
-+ (uint8_t *)p_custom_pattern,
-+ (uint32_t)cust_pattern_size);
-+
-+ /* Unblank Stream */
-+ core_link->dc->hwss.unblank_stream(
-+ &pipe_ctx,
-+ &core_link->public.verified_link_cap);
-+ /* TODO:m_pHwss->MuteAudioEndpoint
-+ * (pPathMode->pDisplayPath, false);
-+ */
-+
-+ /* Reset Test Pattern state */
-+ core_link->public.test_pattern_enabled = false;
-+
-+ return true;
-+ }
-+
-+ /* Check for PHY Test Patterns */
-+ if (is_dp_phy_pattern(test_pattern)) {
-+ /* Set DPCD Lane Settings before running test pattern */
-+ if (p_link_settings != NULL) {
-+ dp_set_hw_lane_settings(core_link, p_link_settings);
-+ dpcd_set_lane_settings(core_link, p_link_settings);
-+ }
-+
-+ /* Blank stream if running test pattern */
-+ if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
-+ /*TODO:
-+ * m_pHwss->
-+ * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
-+ */
-+ /* Blank stream */
-+ pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc);
-+ }
-+
-+ dp_set_hw_test_pattern(core_link, test_pattern,
-+ (uint8_t *)p_custom_pattern,
-+ (uint32_t)cust_pattern_size);
-+
-+ if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
-+ /* Set Test Pattern state */
-+ core_link->public.test_pattern_enabled = true;
-+ if (p_link_settings != NULL)
-+ dpcd_set_link_settings(core_link,
-+ p_link_settings);
-+ }
-+
-+ switch (test_pattern) {
-+ case DP_TEST_PATTERN_VIDEO_MODE:
-+ pattern = PHY_TEST_PATTERN_NONE;
-+ break;
-+ case DP_TEST_PATTERN_D102:
-+ pattern = PHY_TEST_PATTERN_D10_2;
-+ break;
-+ case DP_TEST_PATTERN_SYMBOL_ERROR:
-+ pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
-+ break;
-+ case DP_TEST_PATTERN_PRBS7:
-+ pattern = PHY_TEST_PATTERN_PRBS7;
-+ break;
-+ case DP_TEST_PATTERN_80BIT_CUSTOM:
-+ pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
-+ break;
-+ case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE:
-+ pattern = PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
-+ break;
-+ default:
-+ return false;
-+ }
-+
-+ if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
-+ /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
-+ return false;
-+
-+ if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
-+ /* tell receiver that we are sending qualification
-+ * pattern DP 1.2 or later - DP receiver's link quality
-+ * pattern is set using DPCD LINK_QUAL_LANEx_SET
-+ * register (0x10B~0x10E)\
-+ */
-+ for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
-+ link_qual_pattern[lane] =
-+ (unsigned char)(pattern);
-+
-+ core_link_write_dpcd(core_link,
-+ DPCD_ADDRESS_LINK_QUAL_LANE0_SET,
-+ link_qual_pattern,
-+ sizeof(link_qual_pattern));
-+ } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
-+ core_link->dpcd_caps.dpcd_rev.raw == 0) {
-+ /* tell receiver that we are sending qualification
-+ * pattern DP 1.1a or earlier - DP receiver's link
-+ * quality pattern is set using
-+ * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
-+ * register (0x102). We will use v_1.3 when we are
-+ * setting test pattern for DP 1.1.
-+ */
-+ core_link_read_dpcd(core_link,
-+ DPCD_ADDRESS_TRAINING_PATTERN_SET,
-+ &training_pattern.raw,
-+ sizeof(training_pattern));
-+ training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
-+ core_link_write_dpcd(core_link,
-+ DPCD_ADDRESS_TRAINING_PATTERN_SET,
-+ &training_pattern.raw,
-+ sizeof(training_pattern));
-+ }
-+ } else {
-+ /* CRTC Patterns */
-+ set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern);
-+ /* Set Test Pattern state */
-+ core_link->public.test_pattern_enabled = true;
-+
-+ /* If this is called because of compliance test request,
-+ * we respond ack here.
-+ */
-+ if (core_link->public.compliance_test_state.bits.
-+ SET_TEST_PATTERN_PENDING == 1) {
-+ core_link->public.compliance_test_state.bits.
-+ SET_TEST_PATTERN_PENDING = 0;
-+ test_response.bits.ACK = 1;
-+ core_link_write_dpcd(core_link,
-+ DPCD_ADDRESS_TEST_RESPONSE,
-+ &test_response.raw,
-+ sizeof(test_response));
-+ }
-+ }
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
-new file mode 100644
-index 0000000..e89f5f1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
-@@ -0,0 +1,222 @@
-+/* 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_dp.h"
-+#include "dc_link_ddc.h"
-+#include "dm_helpers.h"
-+#include "dce/dce_link_encoder.h"
-+#include "dce/dce_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,
-+ enum clock_source_id clock_source,
-+ const struct dc_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);
-+ } else {
-+ link_enc->funcs->enable_dp_mst_output(
-+ link_enc,
-+ link_settings,
-+ clock_source);
-+ }
-+
-+ 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.*/
-+ memset(&link->public.cur_link_settings, 0,
-+ sizeof(link->public.cur_link_settings));
-+}
-+
-+void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal)
-+{
-+ /* 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, 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;
-+
-+ 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;
-+ case HW_DP_TRAINING_PATTERN_4:
-+ test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
-+
-+ 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,
-+ uint8_t *custom_pattern,
-+ uint32_t custom_pattern_size)
-+{
-+ 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 = custom_pattern;
-+ pattern_param.custom_pattern_size = custom_pattern_size;
-+ pattern_param.dp_panel_mode = dp_get_panel_mode(link);
-+
-+ encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
-+}
-+
-+
-+void dp_retrain_link(struct core_link *link)
-+{
-+ struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx;
-+ unsigned int i;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (pipes[i].stream_enc != NULL) {
-+ dm_delay_in_microseconds(link->ctx, 100);
-+ pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc);
-+ link->dc->hwss.disable_stream(&pipes[i]);
-+ dc_link_dp_perform_link_training(
-+ &link->public,
-+ &link->public.verified_link_cap,
-+ true);
-+ link->dc->hwss.enable_stream(&pipes[i]);
-+ link->dc->hwss.unblank_stream(&pipes[i],
-+ &link->public.verified_link_cap);
-+ }
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
-new file mode 100644
-index 0000000..bd53d27
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
-@@ -0,0 +1,1934 @@
-+/*
-+* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "timing_generator.h"
-+#include "transform.h"
-+#include "set_mode_types.h"
-+
-+#include "virtual/virtual_stream_encoder.h"
-+
-+#include "dce80/dce80_resource.h"
-+#include "dce100/dce100_resource.h"
-+#include "dce110/dce110_resource.h"
-+#include "dce112/dce112_resource.h"
-+
-+enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
-+{
-+ enum dce_version dc_version = DCE_VERSION_UNKNOWN;
-+ switch (asic_id.chip_family) {
-+
-+ case FAMILY_CI:
-+ case FAMILY_KV:
-+ dc_version = DCE_VERSION_8_0;
-+ break;
-+ case FAMILY_CZ:
-+ dc_version = DCE_VERSION_11_0;
-+ break;
-+
-+ case FAMILY_VI:
-+ if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
-+ ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
-+ dc_version = DCE_VERSION_10_0;
-+ break;
-+ }
-+ if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
-+ ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) {
-+ dc_version = DCE_VERSION_11_2;
-+ }
-+ break;
-+ default:
-+ dc_version = DCE_VERSION_UNKNOWN;
-+ break;
-+ }
-+ return dc_version;
-+}
-+
-+struct resource_pool *dc_create_resource_pool(
-+ struct core_dc *dc,
-+ int num_virtual_links,
-+ enum dce_version dc_version,
-+ struct hw_asic_id asic_id)
-+{
-+
-+ switch (dc_version) {
-+ case DCE_VERSION_8_0:
-+ return dce80_create_resource_pool(
-+ num_virtual_links, dc);
-+ case DCE_VERSION_10_0:
-+ return dce100_create_resource_pool(
-+ num_virtual_links, dc);
-+ case DCE_VERSION_11_0:
-+ return dce110_create_resource_pool(
-+ num_virtual_links, dc, asic_id);
-+ case DCE_VERSION_11_2:
-+ return dce112_create_resource_pool(
-+ num_virtual_links, dc);
-+ default:
-+ break;
-+ }
-+
-+ return false;
-+}
-+
-+void dc_destroy_resource_pool(struct core_dc *dc)
-+{
-+ if (dc) {
-+ if (dc->res_pool)
-+ dc->res_pool->funcs->destroy(&dc->res_pool);
-+
-+ if (dc->hwseq)
-+ dm_free(dc->hwseq);
-+ }
-+}
-+
-+static void update_num_audio(
-+ const struct resource_straps *straps,
-+ unsigned int *num_audio,
-+ struct audio_support *aud_support)
-+{
-+ if (straps->hdmi_disable == 0) {
-+ aud_support->hdmi_audio_native = true;
-+ aud_support->hdmi_audio_on_dongle = true;
-+ aud_support->dp_audio = true;
-+ } else {
-+ if (straps->dc_pinstraps_audio & 0x2) {
-+ aud_support->hdmi_audio_on_dongle = true;
-+ aud_support->dp_audio = true;
-+ } else {
-+ aud_support->dp_audio = true;
-+ }
-+ }
-+
-+ switch (straps->audio_stream_number) {
-+ case 0: /* multi streams supported */
-+ break;
-+ case 1: /* multi streams not supported */
-+ *num_audio = 1;
-+ break;
-+ default:
-+ DC_ERR("DC: unexpected audio fuse!\n");
-+ };
-+}
-+
-+bool resource_construct(
-+ unsigned int num_virtual_links,
-+ struct core_dc *dc,
-+ struct resource_pool *pool,
-+ const struct resource_create_funcs *create_funcs)
-+{
-+ struct dc_context *ctx = dc->ctx;
-+ const struct resource_caps *caps = pool->res_cap;
-+ int i;
-+ unsigned int num_audio = caps->num_audio;
-+ struct resource_straps straps = {0};
-+
-+ if (create_funcs->read_dce_straps)
-+ create_funcs->read_dce_straps(dc->ctx, &straps);
-+
-+ pool->audio_count = 0;
-+ if (create_funcs->create_audio) {
-+ /* 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).
-+ */
-+ update_num_audio(&straps, &num_audio, &pool->audio_support);
-+ for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
-+ struct audio *aud = create_funcs->create_audio(ctx, i);
-+
-+ if (aud == NULL) {
-+ DC_ERR("DC: failed to create audio!\n");
-+ return false;
-+ }
-+
-+ if (!aud->funcs->endpoint_valid(aud)) {
-+ aud->funcs->destroy(&aud);
-+ break;
-+ }
-+
-+ pool->audios[i] = aud;
-+ pool->audio_count++;
-+ }
-+ }
-+
-+ pool->stream_enc_count = 0;
-+ if (create_funcs->create_stream_encoder) {
-+ for (i = 0; i < caps->num_stream_encoder; i++) {
-+ pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
-+ if (pool->stream_enc[i] == NULL)
-+ DC_ERR("DC: failed to create stream_encoder!\n");
-+ pool->stream_enc_count++;
-+ }
-+ }
-+
-+ for (i = 0; i < num_virtual_links; i++) {
-+ pool->stream_enc[pool->stream_enc_count] =
-+ virtual_stream_encoder_create(
-+ ctx, ctx->dc_bios);
-+ if (pool->stream_enc[pool->stream_enc_count] == NULL) {
-+ DC_ERR("DC: failed to create stream_encoder!\n");
-+ return false;
-+ }
-+ pool->stream_enc_count++;
-+ }
-+
-+ dc->hwseq = create_funcs->create_hwseq(ctx);
-+
-+ return true;
-+}
-+
-+
-+void resource_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)
-+ continue;
-+
-+ res_ctx->clock_source_ref_count[i]--;
-+
-+ if (res_ctx->clock_source_ref_count[i] == 0)
-+ clock_source->funcs->cs_power_down(clock_source);
-+
-+ break;
-+ }
-+
-+ if (res_ctx->pool->dp_clock_source == clock_source) {
-+ res_ctx->dp_clock_source_ref_count--;
-+
-+ if (res_ctx->dp_clock_source_ref_count == 0)
-+ clock_source->funcs->cs_power_down(clock_source);
-+ }
-+}
-+
-+void resource_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)
-+ continue;
-+
-+ res_ctx->clock_source_ref_count[i]++;
-+ break;
-+ }
-+
-+ if (res_ctx->pool->dp_clock_source == clock_source)
-+ res_ctx->dp_clock_source_ref_count++;
-+}
-+
-+bool resource_are_streams_timing_synchronizable(
-+ const struct core_stream *stream1,
-+ const struct core_stream *stream2)
-+{
-+ if (stream1->public.timing.h_total != stream2->public.timing.h_total)
-+ return false;
-+
-+ if (stream1->public.timing.v_total != stream2->public.timing.v_total)
-+ return false;
-+
-+ if (stream1->public.timing.h_addressable
-+ != stream2->public.timing.h_addressable)
-+ return false;
-+
-+ if (stream1->public.timing.v_addressable
-+ != stream2->public.timing.v_addressable)
-+ return false;
-+
-+ if (stream1->public.timing.pix_clk_khz
-+ != stream2->public.timing.pix_clk_khz)
-+ return false;
-+
-+ if (stream1->phy_pix_clk != stream2->phy_pix_clk
-+ && !dc_is_dp_signal(stream1->signal)
-+ && !dc_is_dp_signal(stream2->signal))
-+ return false;
-+
-+ return true;
-+}
-+
-+static bool is_sharable_clk_src(
-+ const struct pipe_ctx *pipe_with_clk_src,
-+ const struct pipe_ctx *pipe)
-+{
-+ if (pipe_with_clk_src->clock_source == NULL)
-+ return false;
-+
-+ if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
-+ return false;
-+
-+ if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
-+ return false;
-+
-+ if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
-+ && dc_is_dvi_signal(pipe->stream->signal))
-+ return false;
-+
-+ if (dc_is_hdmi_signal(pipe->stream->signal)
-+ && dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
-+ return false;
-+
-+ if (!resource_are_streams_timing_synchronizable(
-+ pipe_with_clk_src->stream, pipe->stream))
-+ return false;
-+
-+ return true;
-+}
-+
-+struct clock_source *resource_find_used_clk_src_for_sharing(
-+ struct resource_context *res_ctx,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
-+ return res_ctx->pipe_ctx[i].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_ABGR16161616F:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
-+ 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_GRPH_ARGB16161616:
-+ default:
-+ dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
-+ break;
-+ }
-+ return dal_pixel_format;
-+}
-+
-+static void rect_swap_helper(struct rect *rect)
-+{
-+ uint32_t temp = 0;
-+
-+ temp = rect->height;
-+ rect->height = rect->width;
-+ rect->width = temp;
-+
-+ temp = rect->x;
-+ rect->x = rect->y;
-+ rect->y = temp;
-+}
-+
-+static void calculate_viewport(
-+ const struct dc_surface *surface,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ struct rect stream_src = pipe_ctx->stream->public.src;
-+ struct rect src = surface->src_rect;
-+ struct rect dst = surface->dst_rect;
-+ struct rect surface_clip = surface->clip_rect;
-+ struct rect clip = {0};
-+
-+
-+ if (surface->rotation == ROTATION_ANGLE_90 ||
-+ surface->rotation == ROTATION_ANGLE_270) {
-+ rect_swap_helper(&src);
-+ rect_swap_helper(&dst);
-+ rect_swap_helper(&surface_clip);
-+ rect_swap_helper(&stream_src);
-+ }
-+
-+ /* The actual clip is an intersection between stream
-+ * source and surface clip
-+ */
-+ clip.x = stream_src.x > surface_clip.x ?
-+ stream_src.x : surface_clip.x;
-+
-+ clip.width = stream_src.x + stream_src.width <
-+ surface_clip.x + surface_clip.width ?
-+ stream_src.x + stream_src.width - clip.x :
-+ surface_clip.x + surface_clip.width - clip.x ;
-+
-+ clip.y = stream_src.y > surface_clip.y ?
-+ stream_src.y : surface_clip.y;
-+
-+ clip.height = stream_src.y + stream_src.height <
-+ surface_clip.y + surface_clip.height ?
-+ stream_src.y + stream_src.height - clip.y :
-+ surface_clip.y + surface_clip.height - clip.y ;
-+
-+ /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
-+ * num_pixels = clip.num_pix * scl_ratio
-+ */
-+ pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) *
-+ src.width / dst.width;
-+ pipe_ctx->scl_data.viewport.width = clip.width *
-+ src.width / dst.width;
-+
-+ pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) *
-+ src.height / dst.height;
-+ pipe_ctx->scl_data.viewport.height = clip.height *
-+ src.height / dst.height;
-+
-+ /* Minimum viewport such that 420/422 chroma vp is non 0 */
-+ if (pipe_ctx->scl_data.viewport.width < 2)
-+ pipe_ctx->scl_data.viewport.width = 2;
-+ if (pipe_ctx->scl_data.viewport.height < 2)
-+ pipe_ctx->scl_data.viewport.height = 2;
-+}
-+
-+static void calculate_recout(
-+ const struct dc_surface *surface,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct rect clip = surface->clip_rect;
-+
-+ pipe_ctx->scl_data.recout.x = stream->public.dst.x;
-+ if (stream->public.src.x < clip.x)
-+ pipe_ctx->scl_data.recout.x += (clip.x
-+ - stream->public.src.x) * stream->public.dst.width
-+ / stream->public.src.width;
-+
-+ pipe_ctx->scl_data.recout.width = clip.width *
-+ stream->public.dst.width / stream->public.src.width;
-+ if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
-+ stream->public.dst.x + stream->public.dst.width)
-+ pipe_ctx->scl_data.recout.width =
-+ stream->public.dst.x + stream->public.dst.width
-+ - pipe_ctx->scl_data.recout.x;
-+
-+ pipe_ctx->scl_data.recout.y = stream->public.dst.y;
-+ if (stream->public.src.y < clip.y)
-+ pipe_ctx->scl_data.recout.y += (clip.y
-+ - stream->public.src.y) * stream->public.dst.height
-+ / stream->public.src.height;
-+
-+ pipe_ctx->scl_data.recout.height = clip.height *
-+ stream->public.dst.height / stream->public.src.height;
-+ if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
-+ stream->public.dst.y + stream->public.dst.height)
-+ pipe_ctx->scl_data.recout.height =
-+ stream->public.dst.y + stream->public.dst.height
-+ - pipe_ctx->scl_data.recout.y;
-+}
-+
-+static void calculate_scaling_ratios(
-+ const struct dc_surface *surface,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->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;
-+
-+ pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
-+ surface->src_rect.width,
-+ surface->dst_rect.width);
-+ pipe_ctx->scl_data.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)
-+ pipe_ctx->scl_data.ratios.horz.value *= 2;
-+ else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
-+ pipe_ctx->scl_data.ratios.vert.value *= 2;
-+
-+ pipe_ctx->scl_data.ratios.vert.value = div64_s64(
-+ pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
-+ pipe_ctx->scl_data.ratios.horz.value = div64_s64(
-+ pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
-+
-+ pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
-+ pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
-+
-+ if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
-+ pipe_ctx->scl_data.ratios.horz_c.value /= 2;
-+ pipe_ctx->scl_data.ratios.vert_c.value /= 2;
-+ }
-+}
-+
-+bool resource_build_scaling_params(
-+ const struct dc_surface *surface,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ bool res;
-+ struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
-+ /* Important: scaling ratio calculation requires pixel format,
-+ * lb depth calculation requires recout and taps require scaling ratios.
-+ */
-+ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
-+
-+ calculate_viewport(surface, pipe_ctx);
-+
-+ if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
-+ return false;
-+
-+ calculate_scaling_ratios(surface, pipe_ctx);
-+
-+ calculate_recout(surface, pipe_ctx);
-+
-+ /**
-+ * Setting line buffer pixel depth to 24bpp yields banding
-+ * on certain displays, such as the Sharp 4k
-+ */
-+ pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
-+
-+ pipe_ctx->scl_data.h_active = timing->h_addressable;
-+ pipe_ctx->scl_data.v_active = timing->v_addressable;
-+
-+ /* Taps calculations */
-+ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
-+ pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
-+
-+ if (!res) {
-+ /* Try 24 bpp linebuffer */
-+ pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
-+
-+ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
-+ pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
-+ }
-+
-+ dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
-+ "%s: Viewport:\nheight:%d width:%d x:%d "
-+ "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
-+ "y:%d\n",
-+ __func__,
-+ pipe_ctx->scl_data.viewport.height,
-+ pipe_ctx->scl_data.viewport.width,
-+ pipe_ctx->scl_data.viewport.x,
-+ pipe_ctx->scl_data.viewport.y,
-+ surface->dst_rect.height,
-+ surface->dst_rect.width,
-+ surface->dst_rect.x,
-+ surface->dst_rect.y);
-+
-+ return res;
-+}
-+
-+
-+enum dc_status resource_build_scaling_params_for_context(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (context->res_ctx.pipe_ctx[i].surface != NULL &&
-+ context->res_ctx.pipe_ctx[i].stream != NULL)
-+ if (!resource_build_scaling_params(
-+ &context->res_ctx.pipe_ctx[i].surface->public,
-+ &context->res_ctx.pipe_ctx[i]))
-+ return DC_FAIL_BANDWIDTH_VALIDATE;
-+ }
-+
-+ return DC_OK;
-+}
-+
-+static void detach_surfaces_for_target(
-+ struct validate_context *context,
-+ const struct dc_target *dc_target)
-+{
-+ int i;
-+ struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
-+
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
-+ if (cur_pipe->stream == stream) {
-+ cur_pipe->surface = NULL;
-+ cur_pipe->top_pipe = NULL;
-+ cur_pipe->bottom_pipe = NULL;
-+ }
-+ }
-+}
-+
-+struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
-+{
-+ int i;
-+ struct pipe_ctx *secondary_pipe = NULL;
-+
-+ /*
-+ * search backwards for the second pipe to keep pipe
-+ * assignment more consistent
-+ */
-+
-+ for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
-+ if (res_ctx->pipe_ctx[i].stream == NULL) {
-+ secondary_pipe = &res_ctx->pipe_ctx[i];
-+ secondary_pipe->pipe_idx = i;
-+ break;
-+ }
-+ }
-+
-+
-+ return secondary_pipe;
-+}
-+
-+struct pipe_ctx *resource_get_head_pipe_for_stream(
-+ struct resource_context *res_ctx,
-+ const struct core_stream *stream)
-+{
-+ int i;
-+ for (i = 0; i < res_ctx->pool->pipe_count; i++) {
-+ if (res_ctx->pipe_ctx[i].stream == stream &&
-+ !res_ctx->pipe_ctx[i].top_pipe) {
-+ return &res_ctx->pipe_ctx[i];
-+ break;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * A free_pipe for a target is defined here as a pipe with a stream that belongs
-+ * to the target but has no surface attached yet
-+ */
-+static struct pipe_ctx *acquire_free_pipe_for_target(
-+ struct resource_context *res_ctx,
-+ const struct dc_target *dc_target)
-+{
-+ int i;
-+ struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
-+
-+ struct pipe_ctx *head_pipe = NULL;
-+
-+ /* Find head pipe, which has the back end set up*/
-+
-+ head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
-+
-+ if (!head_pipe)
-+ ASSERT(0);
-+
-+ if (!head_pipe->surface)
-+ return head_pipe;
-+
-+ /* Re-use pipe already acquired for this stream if available*/
-+ for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
-+ if (res_ctx->pipe_ctx[i].stream == stream &&
-+ !res_ctx->pipe_ctx[i].surface) {
-+ return &res_ctx->pipe_ctx[i];
-+ }
-+ }
-+
-+ /*
-+ * At this point we have no re-useable pipe for this stream and we need
-+ * to acquire an idle one to satisfy the request
-+ */
-+
-+ if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
-+ return NULL;
-+
-+ return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream);
-+
-+}
-+
-+static void release_free_pipes_for_target(
-+ struct resource_context *res_ctx,
-+ const struct dc_target *dc_target)
-+{
-+ int i;
-+ struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
-+
-+ for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
-+ if (res_ctx->pipe_ctx[i].stream == stream &&
-+ !res_ctx->pipe_ctx[i].surface) {
-+ res_ctx->pipe_ctx[i].stream = NULL;
-+ }
-+ }
-+}
-+
-+bool resource_attach_surfaces_to_context(
-+ const struct dc_surface * const *surfaces,
-+ int surface_count,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context)
-+{
-+ int i;
-+ struct pipe_ctx *tail_pipe;
-+ struct dc_target_status *target_status = NULL;
-+
-+
-+ 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 < context->target_count; i++)
-+ if (&context->targets[i]->public == dc_target) {
-+ target_status = &context->target_status[i];
-+ break;
-+ }
-+ if (target_status == NULL) {
-+ dm_error("Existing target not found; failed to attach surfaces\n");
-+ return false;
-+ }
-+
-+ /* retain new surfaces */
-+ for (i = 0; i < surface_count; i++)
-+ dc_surface_retain(surfaces[i]);
-+
-+ detach_surfaces_for_target(context, dc_target);
-+
-+ /* release existing surfaces*/
-+ for (i = 0; i < target_status->surface_count; i++)
-+ dc_surface_release(target_status->surfaces[i]);
-+
-+ for (i = surface_count; i < target_status->surface_count; i++)
-+ target_status->surfaces[i] = NULL;
-+
-+ target_status->surface_count = 0;
-+
-+ if (surface_count == 0)
-+ return true;
-+
-+ tail_pipe = NULL;
-+ for (i = 0; i < surface_count; i++) {
-+ struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
-+ struct pipe_ctx *free_pipe = acquire_free_pipe_for_target(
-+ &context->res_ctx, dc_target);
-+
-+ if (!free_pipe) {
-+ target_status->surfaces[i] = NULL;
-+ return false;
-+ }
-+
-+ free_pipe->surface = surface;
-+
-+ if (tail_pipe) {
-+ free_pipe->top_pipe = tail_pipe;
-+ tail_pipe->bottom_pipe = free_pipe;
-+ }
-+
-+ tail_pipe = free_pipe;
-+ }
-+
-+ release_free_pipes_for_target(&context->res_ctx, dc_target);
-+
-+ /* assign new surfaces*/
-+ for (i = 0; i < surface_count; i++)
-+ target_status->surfaces[i] = surfaces[i];
-+
-+ target_status->surface_count = surface_count;
-+
-+ return true;
-+}
-+
-+
-+static bool is_timing_changed(const struct core_stream *cur_stream,
-+ const 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;
-+
-+ /* If output color space is changed, need to reprogram info frames */
-+ if (cur_stream->public.output_color_space !=
-+ new_stream->public.output_color_space)
-+ return true;
-+
-+ return memcmp(
-+ &cur_stream->public.timing,
-+ &new_stream->public.timing,
-+ sizeof(struct dc_crtc_timing)) != 0;
-+}
-+
-+static bool are_stream_backends_same(
-+ const struct core_stream *stream_a, const struct core_stream *stream_b)
-+{
-+ if (stream_a == stream_b)
-+ return true;
-+
-+ if (stream_a == NULL || stream_b == NULL)
-+ return false;
-+
-+ if (is_timing_changed(stream_a, stream_b))
-+ return false;
-+
-+ return true;
-+}
-+
-+bool is_target_unchanged(
-+ const struct core_target *old_target, const struct core_target *target)
-+{
-+ int i;
-+
-+ if (old_target == target)
-+ return true;
-+ if (old_target->public.stream_count != target->public.stream_count)
-+ return false;
-+
-+ for (i = 0; i < old_target->public.stream_count; i++) {
-+ const struct core_stream *old_stream = DC_STREAM_TO_CORE(
-+ old_target->public.streams[i]);
-+ const struct core_stream *stream = DC_STREAM_TO_CORE(
-+ target->public.streams[i]);
-+
-+ if (!are_stream_backends_same(old_stream, stream))
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+bool resource_validate_attach_surfaces(
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ const struct validate_context *old_context,
-+ struct validate_context *context)
-+{
-+ int i, j;
-+
-+ for (i = 0; i < set_count; i++) {
-+ for (j = 0; j < old_context->target_count; j++)
-+ if (is_target_unchanged(
-+ old_context->targets[j],
-+ context->targets[i])) {
-+ if (!resource_attach_surfaces_to_context(
-+ old_context->target_status[j].surfaces,
-+ old_context->target_status[j].surface_count,
-+ &context->targets[i]->public,
-+ context))
-+ return false;
-+ context->target_status[i] = old_context->target_status[j];
-+ }
-+ if (set[i].surface_count != 0)
-+ if (!resource_attach_surfaces_to_context(
-+ set[i].surfaces,
-+ set[i].surface_count,
-+ &context->targets[i]->public,
-+ context))
-+ return false;
-+
-+ }
-+
-+ return true;
-+}
-+
-+/* Maximum TMDS single link pixel clock 165MHz */
-+#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
-+
-+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 int acquire_first_free_pipe(
-+ struct resource_context *res_ctx,
-+ struct core_stream *stream)
-+{
-+ int i;
-+
-+ for (i = 0; i < res_ctx->pool->pipe_count; i++) {
-+ if (!res_ctx->pipe_ctx[i].stream) {
-+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-+
-+ pipe_ctx->tg = res_ctx->pool->timing_generators[i];
-+ pipe_ctx->mi = res_ctx->pool->mis[i];
-+ pipe_ctx->ipp = res_ctx->pool->ipps[i];
-+ pipe_ctx->xfm = res_ctx->pool->transforms[i];
-+ pipe_ctx->opp = res_ctx->pool->opps[i];
-+ pipe_ctx->dis_clk = res_ctx->pool->display_clock;
-+ pipe_ctx->pipe_idx = i;
-+
-+ pipe_ctx->stream = stream;
-+ return i;
-+ }
-+ }
-+ return -1;
-+}
-+
-+static struct stream_encoder *find_first_free_match_stream_enc_for_link(
-+ struct resource_context *res_ctx,
-+ struct core_stream *stream)
-+{
-+ int i;
-+ int j = -1;
-+ struct core_link *link = stream->sink->link;
-+
-+ 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.
-+ */
-+
-+ if (j >= 0 && dc_is_dp_signal(stream->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 void update_stream_signal(struct core_stream *stream)
-+{
-+ const struct dc_sink *dc_sink = stream->public.sink;
-+
-+ stream->signal = dc_sink->sink_signal;
-+ /* 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)
-+ stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
-+ else
-+ stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
-+ }
-+}
-+
-+bool resource_is_stream_unchanged(
-+ const struct validate_context *old_context, struct core_stream *stream)
-+{
-+ int i, j;
-+
-+ for (i = 0; i < old_context->target_count; i++) {
-+ struct core_target *old_target = old_context->targets[i];
-+
-+ for (j = 0; j < old_target->public.stream_count; j++) {
-+ struct core_stream *old_stream =
-+ DC_STREAM_TO_CORE(old_target->public.streams[j]);
-+
-+ if (are_stream_backends_same(old_stream, stream))
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+static void copy_pipe_ctx(
-+ const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
-+{
-+ struct core_surface *surface = to_pipe_ctx->surface;
-+ struct core_stream *stream = to_pipe_ctx->stream;
-+
-+ *to_pipe_ctx = *from_pipe_ctx;
-+ to_pipe_ctx->stream = stream;
-+ if (surface != NULL)
-+ to_pipe_ctx->surface = surface;
-+}
-+
-+static struct core_stream *find_pll_sharable_stream(
-+ const struct core_stream *stream_needs_pll,
-+ struct validate_context *context)
-+{
-+ int 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 *stream_has_pll =
-+ DC_STREAM_TO_CORE(target->public.streams[j]);
-+
-+ /* We are looking for non dp, non virtual stream */
-+ if (resource_are_streams_timing_synchronizable(
-+ stream_needs_pll, stream_has_pll)
-+ && !dc_is_dp_signal(stream_has_pll->signal)
-+ && stream_has_pll->sink->link->public.connector_signal
-+ != SIGNAL_TYPE_VIRTUAL)
-+ return stream_has_pll;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
-+{
-+ uint32_t pix_clk = timing->pix_clk_khz;
-+ uint32_t normalized_pix_clk = pix_clk;
-+
-+ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-+ pix_clk /= 2;
-+
-+ switch (timing->display_color_depth) {
-+ case COLOR_DEPTH_888:
-+ normalized_pix_clk = pix_clk;
-+ break;
-+ case COLOR_DEPTH_101010:
-+ normalized_pix_clk = (pix_clk * 30) / 24;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ normalized_pix_clk = (pix_clk * 36) / 24;
-+ break;
-+ case COLOR_DEPTH_161616:
-+ normalized_pix_clk = (pix_clk * 48) / 24;
-+ break;
-+ default:
-+ ASSERT(0);
-+ break;
-+ }
-+
-+ return normalized_pix_clk;
-+}
-+
-+static void calculate_phy_pix_clks(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ int 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 *stream =
-+ DC_STREAM_TO_CORE(target->public.streams[j]);
-+
-+ update_stream_signal(stream);
-+
-+ /* update actual pixel clock on all streams */
-+ if (dc_is_hdmi_signal(stream->signal))
-+ stream->phy_pix_clk = get_norm_pix_clk(
-+ &stream->public.timing);
-+ else
-+ stream->phy_pix_clk =
-+ stream->public.timing.pix_clk_khz;
-+ }
-+ }
-+}
-+
-+enum dc_status resource_map_pool_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ int i, j, k;
-+
-+ calculate_phy_pix_clks(dc, context);
-+
-+ 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]);
-+
-+ if (!resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ /* mark resources used for stream that is already active */
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+ const struct pipe_ctx *old_pipe_ctx =
-+ &dc->current_context->res_ctx.pipe_ctx[k];
-+
-+ if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
-+ continue;
-+
-+ pipe_ctx->stream = stream;
-+ copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
-+
-+ set_stream_engine_in_use(
-+ &context->res_ctx,
-+ pipe_ctx->stream_enc);
-+
-+ /* Switch to dp clock source only if there is
-+ * no non dp stream that shares the same timing
-+ * with the dp stream.
-+ */
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
-+ !find_pll_sharable_stream(stream, context))
-+ pipe_ctx->clock_source =
-+ context->res_ctx.pool->dp_clock_source;
-+
-+ resource_reference_clock_source(
-+ &context->res_ctx,
-+ pipe_ctx->clock_source);
-+
-+ set_audio_in_use(&context->res_ctx,
-+ pipe_ctx->audio);
-+ }
-+ }
-+ }
-+
-+ 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 pipe_ctx *pipe_ctx = NULL;
-+ int pipe_idx = -1;
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+ /* acquire new resources */
-+ pipe_idx = acquire_first_free_pipe(
-+ &context->res_ctx, stream);
-+ if (pipe_idx < 0)
-+ return DC_NO_CONTROLLER_RESOURCE;
-+
-+
-+ pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
-+
-+ pipe_ctx->stream_enc =
-+ find_first_free_match_stream_enc_for_link(
-+ &context->res_ctx, stream);
-+
-+ if (!pipe_ctx->stream_enc)
-+ return DC_NO_STREAM_ENG_RESOURCE;
-+
-+ set_stream_engine_in_use(
-+ &context->res_ctx,
-+ pipe_ctx->stream_enc);
-+
-+ /* TODO: Add check if ASIC support and EDID audio */
-+ if (!stream->sink->converter_disable_audio &&
-+ dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
-+ stream->public.audio_info.mode_count) {
-+ pipe_ctx->audio = find_first_free_audio(
-+ &context->res_ctx);
-+
-+ /*
-+ * Audio assigned in order first come first get.
-+ * There are asics which has number of audio
-+ * resources less then number of pipes
-+ */
-+ if (pipe_ctx->audio)
-+ set_audio_in_use(
-+ &context->res_ctx,
-+ pipe_ctx->audio);
-+ }
-+
-+ if (j == 0) {
-+ context->target_status[i].primary_otg_inst =
-+ pipe_ctx->tg->inst;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+/* first target in the context is used to populate the rest */
-+void validate_guaranteed_copy_target(
-+ struct validate_context *context,
-+ int max_targets)
-+{
-+ int i;
-+
-+ for (i = 1; i < max_targets; i++) {
-+ context->targets[i] = context->targets[0];
-+
-+ copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
-+ &context->res_ctx.pipe_ctx[i]);
-+ context->res_ctx.pipe_ctx[i].stream =
-+ context->res_ctx.pipe_ctx[0].stream;
-+
-+ dc_target_retain(&context->targets[i]->public);
-+ context->target_count++;
-+ }
-+}
-+
-+static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
-+ struct encoder_info_frame *encoder_info_frame)
-+{
-+ 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;
-+
-+ 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) {
-+ memmove(
-+ &encoder_info_frame->avi,
-+ &hw_info_frame->avi_info_packet,
-+ sizeof(struct hw_info_packet));
-+ }
-+
-+ if (hw_info_frame->vendor_info_packet.valid) {
-+ memmove(
-+ &encoder_info_frame->vendor,
-+ &hw_info_frame->vendor_info_packet,
-+ sizeof(struct hw_info_packet));
-+ }
-+
-+ if (hw_info_frame->spd_packet.valid) {
-+ memmove(
-+ &encoder_info_frame->spd,
-+ &hw_info_frame->spd_packet,
-+ sizeof(struct hw_info_packet));
-+ }
-+
-+ if (hw_info_frame->vsc_packet.valid) {
-+ 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 pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ enum dc_color_space color_space = 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 = pipe_ctx->stream->public.output_color_space;
-+
-+ /* 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)
-+ */
-+
-+ 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_YCBCR420:
-+ pixel_encoding = 3;
-+ 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 == COLOR_SPACE_YCBCR709)
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
-+ COLORIMETRY_ITU709;
-+ else if (color_space == 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 : We should handle YCC quantization */
-+ /* but we do not have matrix calculation */
-+ if (color_space == COLOR_SPACE_SRGB) {
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
-+ RGB_QUANTIZATION_FULL_RANGE;
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
-+ YYC_QUANTIZATION_FULL_RANGE;
-+ } else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
-+ RGB_QUANTIZATION_LIMITED_RANGE;
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
-+ YYC_QUANTIZATION_LIMITED_RANGE;
-+ } else {
-+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
-+ RGB_QUANTIZATION_DEFAULT_RANGE;
-+ 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;
-+}
-+
-+static void set_spd_info_packet(struct core_stream *stream,
-+ struct hw_info_packet *info_packet)
-+{
-+ /* SPD info packet for FreeSync */
-+
-+ unsigned char checksum = 0;
-+ unsigned int idx, payload_size = 0;
-+
-+ /* Check if Freesync is supported. Return if false. If true,
-+ * set the corresponding bit in the info packet
-+ */
-+ if (stream->public.freesync_ctx.supported == false)
-+ return;
-+
-+ if (dc_is_hdmi_signal(stream->signal)) {
-+
-+ /* HEADER */
-+
-+ /* HB0 = Packet Type = 0x83 (Source Product
-+ * Descriptor InfoFrame)
-+ */
-+ info_packet->hb0 = 0x83;
-+
-+ /* HB1 = Version = 0x01 */
-+ info_packet->hb1 = 0x01;
-+
-+ /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
-+ info_packet->hb2 = 0x08;
-+
-+ payload_size = 0x08;
-+
-+ } else if (dc_is_dp_signal(stream->signal)) {
-+
-+ /* HEADER */
-+
-+ /* HB0 = Secondary-data Packet ID = 0 - Only non-zero
-+ * when used to associate audio related info packets
-+ */
-+ info_packet->hb0 = 0x00;
-+
-+ /* HB1 = Packet Type = 0x83 (Source Product
-+ * Descriptor InfoFrame)
-+ */
-+ info_packet->hb1 = 0x83;
-+
-+ /* HB2 = [Bits 7:0 = Least significant eight bits -
-+ * For INFOFRAME, the value must be 1Bh]
-+ */
-+ info_packet->hb2 = 0x1B;
-+
-+ /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
-+ * [Bits 1:0 = Most significant two bits = 0x00]
-+ */
-+ info_packet->hb3 = 0x04;
-+
-+ payload_size = 0x1B;
-+ }
-+
-+ /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
-+ info_packet->sb[1] = 0x1A;
-+
-+ /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
-+ info_packet->sb[2] = 0x00;
-+
-+ /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
-+ info_packet->sb[3] = 0x00;
-+
-+ /* PB4 = Reserved */
-+ info_packet->sb[4] = 0x00;
-+
-+ /* PB5 = Reserved */
-+ info_packet->sb[5] = 0x00;
-+
-+ /* PB6 = [Bits 7:3 = Reserved] */
-+ info_packet->sb[6] = 0x00;
-+
-+ if (stream->public.freesync_ctx.supported == true)
-+ /* PB6 = [Bit 0 = FreeSync Supported] */
-+ info_packet->sb[6] |= 0x01;
-+
-+ if (stream->public.freesync_ctx.enabled == true)
-+ /* PB6 = [Bit 1 = FreeSync Enabled] */
-+ info_packet->sb[6] |= 0x02;
-+
-+ if (stream->public.freesync_ctx.active == true)
-+ /* PB6 = [Bit 2 = FreeSync Active] */
-+ info_packet->sb[6] |= 0x04;
-+
-+ /* PB7 = FreeSync Minimum refresh rate (Hz) */
-+ info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
-+ min_refresh_in_micro_hz / 1000000);
-+
-+ /* PB8 = FreeSync Maximum refresh rate (Hz)
-+ *
-+ * Note: We do not use the maximum capable refresh rate
-+ * of the panel, because we should never go above the field
-+ * rate of the mode timing set.
-+ */
-+ info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
-+ nominal_refresh_in_micro_hz / 1000000);
-+
-+ /* PB9 - PB27 = Reserved */
-+ for (idx = 9; idx <= 27; idx++)
-+ info_packet->sb[idx] = 0x00;
-+
-+ /* Calculate checksum */
-+ checksum += info_packet->hb0;
-+ checksum += info_packet->hb1;
-+ checksum += info_packet->hb2;
-+ checksum += info_packet->hb3;
-+
-+ for (idx = 1; idx <= payload_size; idx++)
-+ checksum += info_packet->sb[idx];
-+
-+ /* PB0 = Checksum (one byte complement) */
-+ info_packet->sb[0] = (unsigned char) (0x100 - checksum);
-+
-+ info_packet->valid = true;
-+}
-+
-+static void set_vsc_info_packet(struct core_stream *stream,
-+ struct hw_info_packet *info_packet)
-+{
-+ unsigned int vscPacketRevision = 0;
-+ unsigned int i;
-+
-+ if (stream->sink->link->public.psr_caps.psr_version != 0) {
-+ vscPacketRevision = 2;
-+ }
-+
-+ /* VSC packet not needed based on the features
-+ * supported by this DP display
-+ */
-+ if (vscPacketRevision == 0)
-+ return;
-+
-+ if (vscPacketRevision == 0x2) {
-+ /* Secondary-data Packet ID = 0*/
-+ info_packet->hb0 = 0x00;
-+ /* 07h - Packet Type Value indicating Video
-+ * Stream Configuration packet
-+ */
-+ info_packet->hb1 = 0x07;
-+ /* 02h = VSC SDP supporting 3D stereo and PSR
-+ * (applies to eDP v1.3 or higher).
-+ */
-+ info_packet->hb2 = 0x02;
-+ /* 08h = VSC packet supporting 3D stereo + PSR
-+ * (HB2 = 02h).
-+ */
-+ info_packet->hb3 = 0x08;
-+
-+ for (i = 0; i < 28; i++)
-+ info_packet->sb[i] = 0;
-+
-+ info_packet->valid = true;
-+ }
-+
-+ /*TODO: stereo 3D support and extend pixel encoding colorimetry*/
-+}
-+
-+void resource_validate_ctx_destruct(struct validate_context *context)
-+{
-+ int i, j;
-+
-+ for (i = 0; i < context->target_count; i++) {
-+ for (j = 0; j < context->target_status[i].surface_count; j++)
-+ dc_surface_release(
-+ context->target_status[i].surfaces[j]);
-+
-+ context->target_status[i].surface_count = 0;
-+ dc_target_release(&context->targets[i]->public);
-+ }
-+}
-+
-+/*
-+ * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced
-+ * by the src_ctx
-+ */
-+void resource_validate_ctx_copy_construct(
-+ const struct validate_context *src_ctx,
-+ struct validate_context *dst_ctx)
-+{
-+ int i, j;
-+
-+ *dst_ctx = *src_ctx;
-+
-+ for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
-+
-+ if (cur_pipe->top_pipe)
-+ cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
-+
-+ if (cur_pipe->bottom_pipe)
-+ cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
-+
-+ }
-+
-+ for (i = 0; i < dst_ctx->target_count; i++) {
-+ dc_target_retain(&dst_ctx->targets[i]->public);
-+ for (j = 0; j < dst_ctx->target_status[i].surface_count; j++)
-+ dc_surface_retain(
-+ dst_ctx->target_status[i].surfaces[j]);
-+ }
-+}
-+
-+struct clock_source *dc_resource_find_first_free_pll(
-+ struct resource_context *res_ctx)
-+{
-+ int i;
-+
-+ for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
-+ if (res_ctx->clock_source_ref_count[i] == 0)
-+ return res_ctx->pool->clock_sources[i];
-+ }
-+
-+ return NULL;
-+}
-+
-+void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
-+{
-+ 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 = pipe_ctx->stream->signal;
-+
-+ /* HDMi and DP have different info packets*/
-+ if (dc_is_hdmi_signal(signal)) {
-+ set_avi_info_frame(
-+ &info_frame.avi_info_packet, pipe_ctx);
-+ set_vendor_info_packet(
-+ pipe_ctx->stream, &info_frame.vendor_info_packet);
-+ set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
-+ }
-+
-+ else if (dc_is_dp_signal(signal))
-+ set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet);
-+ set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
-+
-+ translate_info_frame(&info_frame,
-+ &pipe_ctx->encoder_info_frame);
-+}
-+
-+enum dc_status resource_map_clock_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ int i, j, k;
-+
-+ /* acquire new resources */
-+ 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]);
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal)
-+ || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
-+ pipe_ctx->clock_source =
-+ context->res_ctx.pool->dp_clock_source;
-+ else {
-+ pipe_ctx->clock_source = NULL;
-+
-+ if (!dc->public.config.disable_disp_pll_sharing)
-+ resource_find_used_clk_src_for_sharing(
-+ &context->res_ctx,
-+ pipe_ctx);
-+
-+ if (pipe_ctx->clock_source == NULL)
-+ pipe_ctx->clock_source =
-+ dc_resource_find_first_free_pll(&context->res_ctx);
-+ }
-+
-+ if (pipe_ctx->clock_source == NULL)
-+ return DC_NO_CLOCK_SOURCE_RESOURCE;
-+
-+ resource_reference_clock_source(
-+ &context->res_ctx,
-+ pipe_ctx->clock_source);
-+
-+ /* only one cs per stream regardless of mpo */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+/*
-+ * Note: We need to disable output if clock sources change,
-+ * since bios does optimization and doesn't apply if changing
-+ * PHY when not already disabled.
-+ */
-+bool pipe_need_reprogram(
-+ struct pipe_ctx *pipe_ctx_old,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
-+ return true;
-+
-+ if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
-+ return true;
-+
-+ if (pipe_ctx_old->audio != pipe_ctx->audio)
-+ return true;
-+
-+ if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
-+ && pipe_ctx_old->stream != pipe_ctx->stream)
-+ return true;
-+
-+ if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
-+ return true;
-+
-+ if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
-+ return true;
-+
-+
-+ return false;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c
-new file mode 100644
-index 0000000..67ae799
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c
-@@ -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
-+ *
-+ */
-+
-+#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 sink *sink = DC_SINK_TO_SINK(dc_sink);
-+
-+ --sink->ref_count;
-+
-+ if (sink->ref_count == 0) {
-+ destruct(sink);
-+ dm_free(sink);
-+ }
-+}
-+
-+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
-+{
-+ struct sink *sink = dm_alloc(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(sink);
-+
-+alloc_fail:
-+ return NULL;
-+}
-+
-+/*******************************************************************************
-+ * Protected functions - visible only inside of DC (not visible in DM)
-+ ******************************************************************************/
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
-new file mode 100644
-index 0000000..8d6aa60
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
-@@ -0,0 +1,141 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 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);
-+
-+ /* 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;
-+ 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;
-+
-+ stream->status.link = &stream->sink->link->public;
-+
-+ return true;
-+}
-+
-+static void destruct(struct core_stream *stream)
-+{
-+ dc_sink_release(&stream->sink->public);
-+}
-+
-+void dc_stream_retain(const struct dc_stream *dc_stream)
-+{
-+ struct stream *stream = DC_STREAM_TO_STREAM(dc_stream);
-+ stream->ref_count++;
-+}
-+
-+void dc_stream_release(const struct dc_stream *public)
-+{
-+ struct stream *stream = DC_STREAM_TO_STREAM(public);
-+ struct core_stream *protected = DC_STREAM_TO_CORE(public);
-+
-+ if (public != NULL) {
-+ stream->ref_count--;
-+
-+ if (stream->ref_count == 0) {
-+ destruct(protected);
-+ dm_free(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(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(stream);
-+
-+alloc_fail:
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
-new file mode 100644
-index 0000000..045005e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
-@@ -0,0 +1,214 @@
-+/*
-+ * 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 "transform.h"
-+
-+/*******************************************************************************
-+ * Private structures
-+ ******************************************************************************/
-+struct surface {
-+ struct core_surface protected;
-+ enum dc_irq_source irq_source;
-+ int ref_count;
-+};
-+
-+struct gamma {
-+ struct core_gamma protected;
-+ 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)
-+
-+#define DC_GAMMA_TO_GAMMA(dc_gamma) \
-+ container_of(dc_gamma, struct gamma, protected.public)
-+#define CORE_GAMMA_TO_GAMMA(core_gamma) \
-+ container_of(core_gamma, struct gamma, protected)
-+
-+/*******************************************************************************
-+ * Private functions
-+ ******************************************************************************/
-+static bool construct(struct dc_context *ctx, struct surface *surface)
-+{
-+ 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 core_dc *core_dc = DC_TO_CORE(dc);
-+
-+ struct surface *surface = dm_alloc(sizeof(*surface));
-+
-+ if (NULL == surface)
-+ goto alloc_fail;
-+
-+ if (false == construct(core_dc->ctx, surface))
-+ goto construct_fail;
-+
-+ dc_surface_retain(&surface->protected.public);
-+
-+ return &surface->protected.public;
-+
-+construct_fail:
-+ dm_free(surface);
-+
-+alloc_fail:
-+ return NULL;
-+}
-+
-+const struct dc_surface_status *dc_surface_get_status(
-+ const struct dc_surface *dc_surface)
-+{
-+ struct dc_surface_status *surface_status;
-+ struct core_surface *core_surface;
-+ struct core_dc *core_dc;
-+ int i;
-+
-+ if (dc_surface == NULL)
-+ return NULL;
-+
-+ core_surface = DC_SURFACE_TO_CORE(dc_surface);
-+
-+ if (core_surface == NULL || core_surface->ctx == NULL)
-+ return NULL;
-+
-+ surface_status = &core_surface->status;
-+
-+ if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL)
-+ return NULL;
-+
-+ core_dc = DC_TO_CORE(core_surface->ctx->dc);
-+
-+
-+ if (core_dc->current_context == NULL)
-+ return NULL;
-+
-+ for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count;
-+ i++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &core_dc->current_context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->surface !=
-+ DC_SURFACE_TO_CORE(dc_surface))
-+ continue;
-+
-+ core_dc->hwss.update_pending_status(pipe_ctx);
-+ }
-+
-+ return surface_status;
-+}
-+
-+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);
-+ }
-+}
-+
-+static bool construct_gamma(struct dc_context *ctx, struct gamma *gamma)
-+{
-+ return true;
-+}
-+
-+static void destruct_gamma(struct gamma *gamma)
-+{
-+
-+}
-+
-+void dc_gamma_retain(const struct dc_gamma *dc_gamma)
-+{
-+ struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
-+
-+ ++gamma->ref_count;
-+}
-+
-+void dc_gamma_release(const struct dc_gamma *dc_gamma)
-+{
-+ struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
-+ --gamma->ref_count;
-+
-+ if (gamma->ref_count == 0) {
-+ destruct_gamma(gamma);
-+ dm_free(gamma);
-+ }
-+}
-+
-+struct dc_gamma *dc_create_gamma(const struct dc *dc)
-+{
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct gamma *gamma = dm_alloc(sizeof(*gamma));
-+
-+ if (gamma == NULL)
-+ goto alloc_fail;
-+
-+ if (false == construct_gamma(core_dc->ctx, gamma))
-+ goto construct_fail;
-+
-+ dc_gamma_retain(&gamma->protected.public);
-+
-+ return &gamma->protected.public;
-+
-+construct_fail:
-+ dm_free(gamma);
-+
-+alloc_fail:
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c
-new file mode 100644
-index 0000000..48eb7b0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c
-@@ -0,0 +1,334 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+
-+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->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(const struct dc_target *dc_target)
-+{
-+ struct target *target = DC_TARGET_TO_TARGET(dc_target);
-+
-+ target->ref_count++;
-+}
-+
-+void dc_target_release(const 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(target);
-+ }
-+}
-+
-+const struct dc_target_status *dc_target_get_status(
-+ const struct dc_target* dc_target)
-+{
-+ uint8_t i;
-+ struct core_target* target = DC_TARGET_TO_CORE(dc_target);
-+ struct core_dc *dc = DC_TO_CORE(target->ctx->dc);
-+
-+ for (i = 0; i < dc->current_context->target_count; i++)
-+ if (target == dc->current_context->targets[i])
-+ return &dc->current_context->target_status[i];
-+
-+ return NULL;
-+}
-+
-+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(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;
-+}
-+
-+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;
-+}
-+
-+/**
-+ * 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)
-+{
-+ uint8_t i, j;
-+ struct core_target *target;
-+ struct core_dc *core_dc;
-+ struct resource_context *res_ctx;
-+
-+ if (NULL == dc_target) {
-+ dm_error("DC: dc_target is NULL!\n");
-+ return false;
-+
-+ }
-+ if (NULL == attributes) {
-+ dm_error("DC: attributes is NULL!\n");
-+ return false;
-+
-+ }
-+
-+ target = DC_TARGET_TO_CORE(dc_target);
-+ core_dc = DC_TO_CORE(target->ctx->dc);
-+ res_ctx = &core_dc->current_context->res_ctx;
-+
-+ for (i = 0; i < target->public.stream_count; i++) {
-+ for (j = 0; j < MAX_PIPES; j++) {
-+ struct input_pixel_processor *ipp =
-+ res_ctx->pipe_ctx[j].ipp;
-+
-+ if (res_ctx->pipe_ctx[j].stream !=
-+ DC_STREAM_TO_CORE(target->public.streams[i]))
-+ continue;
-+
-+ /* As of writing of this code cursor is on the top
-+ * plane so we only need to set it on first pipe we
-+ * find. May need to make this code dce specific later.
-+ */
-+ if (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)
-+{
-+ uint8_t i, j;
-+ struct core_target *target;
-+ struct core_dc *core_dc;
-+ struct resource_context *res_ctx;
-+
-+ 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;
-+ }
-+
-+ target = DC_TARGET_TO_CORE(dc_target);
-+ core_dc = DC_TO_CORE(target->ctx->dc);
-+ res_ctx = &core_dc->current_context->res_ctx;
-+
-+ for (i = 0; i < target->public.stream_count; i++) {
-+ for (j = 0; j < MAX_PIPES; j++) {
-+ struct input_pixel_processor *ipp =
-+ res_ctx->pipe_ctx[j].ipp;
-+
-+ if (res_ctx->pipe_ctx[j].stream !=
-+ DC_STREAM_TO_CORE(target->public.streams[i]))
-+ continue;
-+
-+ /* As of writing of this code cursor is on the top
-+ * plane so we only need to set it on first pipe we
-+ * find. May need to make this code dce specific later.
-+ */
-+ ipp->funcs->ipp_cursor_set_position(ipp, position);
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
-+{
-+ uint8_t i, j;
-+ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
-+ struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc);
-+ struct resource_context *res_ctx =
-+ &core_dc->current_context->res_ctx;
-+
-+ for (i = 0; i < target->public.stream_count; i++) {
-+ for (j = 0; j < MAX_PIPES; j++) {
-+ struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
-+
-+ if (res_ctx->pipe_ctx[j].stream !=
-+ DC_STREAM_TO_CORE(target->public.streams[i]))
-+ continue;
-+
-+ return tg->funcs->get_frame_count(tg);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+uint32_t dc_target_get_scanoutpos(
-+ const struct dc_target *dc_target,
-+ uint32_t *vbl,
-+ uint32_t *position)
-+{
-+ uint8_t i, j;
-+ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
-+ struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc);
-+ struct resource_context *res_ctx =
-+ &core_dc->current_context->res_ctx;
-+
-+ for (i = 0; i < target->public.stream_count; i++) {
-+ for (j = 0; j < MAX_PIPES; j++) {
-+ struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
-+
-+ if (res_ctx->pipe_ctx[j].stream !=
-+ DC_STREAM_TO_CORE(target->public.streams[i]))
-+ continue;
-+
-+ return tg->funcs->get_scanoutpos(tg, vbl, position);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void dc_target_log(
-+ const struct dc_target *dc_target,
-+ struct dal_logger *dm_logger,
-+ enum dc_log_type log_type)
-+{
-+ int i;
-+
-+ const struct core_target *core_target =
-+ CONST_DC_TARGET_TO_CORE(dc_target);
-+
-+ dm_logger_write(dm_logger,
-+ log_type,
-+ "core_target 0x%x: stream_count=%d\n",
-+ core_target,
-+ 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]);
-+
-+ dm_logger_write(dm_logger,
-+ log_type,
-+ "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);
-+ dm_logger_write(dm_logger,
-+ log_type,
-+ "\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);
-+ dm_logger_write(dm_logger,
-+ log_type,
-+ "\tsink name: %s, serial: %d\n",
-+ core_stream->sink->public.edid_caps.display_name,
-+ core_stream->sink->public.edid_caps.serial_number);
-+ dm_logger_write(dm_logger,
-+ log_type,
-+ "\tlink: %d\n",
-+ core_stream->sink->link->public.link_index);
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
-new file mode 100644
-index 0000000..6bb3aeb
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc.h
-@@ -0,0 +1,780 @@
-+/*
-+ * 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 "dpcd_defs.h"
-+#include "grph_object_defs.h"
-+#include "logger_types.h"
-+#include "gpio_types.h"
-+#include "link_service_types.h"
-+
-+#define MAX_TARGETS 6
-+#define MAX_SURFACES 6
-+#define MAX_SINKS_PER_LINK 4
-+
-+/*******************************************************************************
-+ * Display Core Interfaces
-+ ******************************************************************************/
-+
-+struct dc_caps {
-+ uint32_t max_targets;
-+ uint32_t max_links;
-+ uint32_t max_audios;
-+ uint32_t max_slave_planes;
-+ uint32_t max_downscale_ratio;
-+ uint32_t i2c_speed_in_khz;
-+};
-+
-+
-+struct dc_dcc_surface_param {
-+ enum surface_pixel_format format;
-+ struct dc_size surface_size;
-+ enum dc_scan_direction scan;
-+};
-+
-+struct dc_dcc_setting {
-+ unsigned int max_compressed_blk_size;
-+ unsigned int max_uncompressed_blk_size;
-+ bool independent_64b_blks;
-+};
-+
-+struct dc_surface_dcc_cap {
-+ bool capable;
-+ bool const_color_support;
-+
-+ union {
-+ struct {
-+ struct dc_dcc_setting rgb;
-+ } grph;
-+
-+ struct {
-+ struct dc_dcc_setting luma;
-+ struct dc_dcc_setting chroma;
-+ } video;
-+ };
-+};
-+
-+/* Forward declaration*/
-+struct dc;
-+struct dc_surface;
-+struct validate_context;
-+
-+struct dc_cap_funcs {
-+ int i;
-+};
-+
-+struct dc_stream_funcs {
-+ bool (*adjust_vmin_vmax)(struct dc *dc,
-+ const struct dc_stream **stream,
-+ int num_streams,
-+ int vmin,
-+ int vmax);
-+
-+ void (*stream_update_scaling)(const struct dc *dc,
-+ const struct dc_stream *dc_stream,
-+ const struct rect *src,
-+ const struct rect *dst);
-+ bool (*set_gamut_remap)(struct dc *dc,
-+ const struct dc_stream **stream, int num_streams);
-+ bool (*set_backlight)(struct dc *dc, unsigned int backlight_level,
-+ unsigned int frame_ramp, const struct dc_stream *stream);
-+ bool (*init_dmcu_backlight_settings)(struct dc *dc);
-+ bool (*set_abm_level)(struct dc *dc, unsigned int abm_level);
-+ bool (*set_psr_enable)(struct dc *dc, bool enable);
-+ bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream);
-+};
-+
-+struct link_training_settings;
-+
-+struct dc_link_funcs {
-+ void (*set_drive_settings)(struct dc *dc,
-+ struct link_training_settings *lt_settings);
-+ void (*perform_link_training)(struct dc *dc,
-+ struct dc_link_settings *link_setting,
-+ bool skip_video_pattern);
-+ void (*set_preferred_link_settings)(struct dc *dc,
-+ struct dc_link_settings *link_setting);
-+ void (*enable_hpd)(const struct dc_link *link);
-+ void (*disable_hpd)(const struct dc_link *link);
-+ void (*set_test_pattern)(
-+ const struct dc_link *link,
-+ enum dp_test_pattern test_pattern,
-+ const struct link_training_settings *p_link_settings,
-+ const unsigned char *p_custom_pattern,
-+ unsigned int cust_pattern_size);
-+};
-+
-+/* Structure to hold configuration flags set by dm at dc creation. */
-+struct dc_config {
-+ bool gpu_vm_support;
-+ bool disable_disp_pll_sharing;
-+};
-+
-+struct dc_debug {
-+ bool surface_visual_confirm;
-+ bool max_disp_clk;
-+ bool target_trace;
-+ bool surface_trace;
-+ bool validation_trace;
-+ bool disable_stutter;
-+ bool disable_dcc;
-+ bool disable_dfs_bypass;
-+ bool disable_power_gate;
-+ bool disable_clock_gate;
-+};
-+
-+struct dc {
-+ struct dc_caps caps;
-+ struct dc_cap_funcs cap_funcs;
-+ struct dc_stream_funcs stream_funcs;
-+ struct dc_link_funcs link_funcs;
-+ struct dc_config config;
-+ struct dc_debug debug;
-+};
-+
-+enum frame_buffer_mode {
-+ FRAME_BUFFER_MODE_LOCAL_ONLY = 0,
-+ FRAME_BUFFER_MODE_ZFB_ONLY,
-+ FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL,
-+} ;
-+
-+struct dchub_init_data {
-+ bool dchub_initialzied;
-+ bool dchub_info_valid;
-+ int64_t zfb_phys_addr_base;
-+ int64_t zfb_mc_base_addr;
-+ uint64_t zfb_size_in_byte;
-+ enum frame_buffer_mode fb_mode;
-+};
-+
-+struct dc_init_data {
-+ struct hw_asic_id asic_id;
-+ void *driver; /* ctx */
-+ struct cgs_device *cgs_device;
-+
-+ int 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 dc_config flags;
-+};
-+
-+struct dc *dc_create(const struct dc_init_data *init_params);
-+
-+void dc_destroy(struct dc **dc);
-+
-+bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data);
-+
-+/*******************************************************************************
-+ * Surface Interfaces
-+ ******************************************************************************/
-+
-+enum {
-+ RGB_256X3X16 = 256,
-+ FLOAT_GAMMA_RAMP_MAX = 1025
-+};
-+
-+enum dc_gamma_ramp_type {
-+ GAMMA_RAMP_RBG256X3X16,
-+ GAMMA_RAMP_FLOAT,
-+};
-+
-+struct float_rgb {
-+ struct fixed32_32 red;
-+ struct fixed32_32 green;
-+ struct fixed32_32 blue;
-+};
-+
-+struct dc_gamma_ramp_float {
-+ struct float_rgb scale;
-+ struct float_rgb offset;
-+ struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX];
-+};
-+
-+struct dc_gamma_ramp_rgb256x3x16 {
-+ uint16_t red[RGB_256X3X16];
-+ uint16_t green[RGB_256X3X16];
-+ uint16_t blue[RGB_256X3X16];
-+};
-+
-+struct dc_gamma {
-+ enum dc_gamma_ramp_type type;
-+ union {
-+ struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
-+ struct dc_gamma_ramp_float gamma_ramp_float;
-+ };
-+ uint32_t size;
-+};
-+
-+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;
-+ union dc_tiling_info tiling_info;
-+ struct dc_plane_dcc_param dcc;
-+ enum dc_color_space color_space;
-+
-+ enum surface_pixel_format format;
-+ enum dc_rotation_angle rotation;
-+ bool horizontal_mirror;
-+ enum plane_stereo_format stereo_format;
-+
-+ const struct dc_gamma *gamma_correction;
-+};
-+
-+struct dc_plane_info {
-+ union plane_size plane_size;
-+ union dc_tiling_info tiling_info;
-+ enum surface_pixel_format format;
-+ enum dc_rotation_angle rotation;
-+ bool horizontal_mirror;
-+ enum plane_stereo_format stereo_format;
-+ enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/
-+ bool visible;
-+};
-+
-+struct dc_scaling_info {
-+ struct rect src_rect;
-+ struct rect dst_rect;
-+ struct rect clip_rect;
-+ struct scaling_taps scaling_quality;
-+};
-+
-+struct dc_surface_update {
-+ const struct dc_surface *surface;
-+
-+ /* isr safe update parameters. null means no updates */
-+ struct dc_flip_addrs *flip_addr;
-+ struct dc_plane_info *plane_info;
-+ struct dc_scaling_info *scaling_info;
-+ /* following updates require alloc/sleep/spin that is not isr safe,
-+ * null means no updates
-+ */
-+ struct dc_gamma *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;
-+ bool is_flip_pending;
-+};
-+
-+/*
-+ * 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(
-+ const 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);
-+
-+void dc_gamma_release(const struct dc_gamma *dc_gamma);
-+struct dc_gamma *dc_create_gamma(const struct dc *dc);
-+
-+/*
-+ * 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,
-+ const struct dc_surface **dc_surfaces,
-+ uint8_t surface_count,
-+ struct dc_target *dc_target);
-+
-+bool dc_pre_update_surfaces_to_target(
-+ struct dc *dc,
-+ const struct dc_surface *const *new_surfaces,
-+ uint8_t new_surface_count,
-+ struct dc_target *dc_target);
-+
-+bool dc_post_update_surfaces_to_target(
-+ struct dc *dc);
-+
-+void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates,
-+ int 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 {
-+ int primary_otg_inst;
-+ int cur_frame_count;
-+ int surface_count;
-+ const struct dc_surface *surfaces[MAX_SURFACE_NUM];
-+};
-+
-+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(const struct dc_target *dc_target);
-+void dc_target_release(const struct dc_target *dc_target);
-+void dc_target_log(
-+ const struct dc_target *dc_target,
-+ struct dal_logger *dc_logger,
-+ enum dc_log_type log_type);
-+
-+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);
-+
-+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
-+
-+/* TODO: Return parsed values rather than direct register read
-+ * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
-+ * being refactored properly to be dce-specific
-+ */
-+uint32_t dc_target_get_scanoutpos(
-+ const struct dc_target *dc_target,
-+ uint32_t *vbl,
-+ uint32_t *position);
-+
-+/*
-+ * Structure to store surface/target associations for validation
-+ */
-+struct dc_validation_set {
-+ const struct dc_target *target;
-+ const struct dc_surface *surfaces[MAX_SURFACES];
-+ 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);
-+
-+/*
-+ * This function takes a target and checks if it is guaranteed to be supported.
-+ * Guaranteed means that MAX_COFUNC*target is supported.
-+ *
-+ * After this call:
-+ * No hardware is programmed for call. Only validation is done.
-+ */
-+
-+bool dc_validate_guaranteed(
-+ const struct dc *dc,
-+ const struct dc_target *dc_target);
-+
-+/*
-+ * 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;
-+
-+ enum dc_color_space output_color_space;
-+
-+ struct rect src; /* viewport in target space*/
-+ struct rect dst; /* stream addressable area */
-+
-+ struct audio_info audio_info;
-+
-+ bool ignore_msa_timing_param;
-+
-+ struct freesync_context freesync_ctx;
-+
-+ /* TODO: dithering */
-+ /* TODO: transfer function (CSC/regamma/gamut remap) */
-+ struct colorspace_transform gamut_remap_matrix;
-+ struct csc_transform csc_color_matrix;
-+ /* TODO: custom INFO packets */
-+ /* 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(const struct dc_stream *dc_stream);
-+void dc_stream_release(const struct dc_stream *dc_stream);
-+
-+struct dc_stream_status {
-+ /*
-+ * link this stream passes through
-+ */
-+ const struct dc_link *link;
-+};
-+
-+const struct dc_stream_status *dc_stream_get_status(
-+ const struct dc_stream *dc_stream);
-+
-+/*******************************************************************************
-+ * 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 */
-+ /* caps is the same as reported_link_cap. link_traing use
-+ * reported_link_cap. Will clean up. TODO
-+ */
-+ struct dc_link_settings reported_link_cap;
-+ struct dc_link_settings verified_link_cap;
-+ struct dc_link_settings max_link_setting;
-+ struct dc_link_settings cur_link_settings;
-+ struct dc_lane_settings cur_lane_setting;
-+
-+ uint8_t ddc_hw_inst;
-+ uint8_t link_enc_hw_inst;
-+
-+ struct psr_caps psr_caps;
-+ bool test_pattern_enabled;
-+ union compliance_test_state compliance_test_state;
-+};
-+
-+struct dpcd_caps {
-+ union dpcd_rev dpcd_rev;
-+ union max_lane_count max_ln_count;
-+ union max_down_spread max_down_spread;
-+
-+ /* 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];
-+ int8_t branch_hw_revision;
-+};
-+
-+struct dc_link_status {
-+ struct dpcd_caps *dpcd_caps;
-+};
-+
-+const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
-+
-+/*
-+ * 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(const 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,
-+ uint32_t frame_ramp, const struct dc_stream *stream);
-+
-+bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link);
-+
-+bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level);
-+
-+bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable);
-+
-+bool dc_link_setup_psr(const struct dc_link *dc_link,
-+ const struct dc_stream *stream);
-+
-+/* 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);
-+
-+struct dc_sink_init_data;
-+
-+struct dc_sink *dc_link_add_remote_sink(
-+ const struct dc_link *dc_link,
-+ const uint8_t *edid,
-+ int len,
-+ struct dc_sink_init_data *init_data);
-+
-+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);
-+
-+void dc_link_dp_set_drive_settings(
-+ struct dc_link *link,
-+ struct link_training_settings *lt_settings);
-+
-+bool dc_link_dp_perform_link_training(
-+ struct dc_link *link,
-+ const struct dc_link_settings *link_setting,
-+ bool skip_video_pattern);
-+
-+void dc_link_dp_enable_hpd(const struct dc_link *link);
-+
-+void dc_link_dp_disable_hpd(const struct dc_link *link);
-+
-+bool dc_link_dp_set_test_pattern(
-+ const struct dc_link *link,
-+ enum dp_test_pattern test_pattern,
-+ const struct link_training_settings *p_link_settings,
-+ const unsigned char *p_custom_pattern,
-+ unsigned int cust_pattern_size);
-+
-+/*******************************************************************************
-+ * 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);
-+enum dc_irq_source dc_get_hpd_irq_source_at_index(
-+ struct dc *dc, uint32_t link_index);
-+
-+/*******************************************************************************
-+ * 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);
-+
-+#endif /* DC_INTERFACE_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
-new file mode 100644
-index 0000000..790c5bd
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
-@@ -0,0 +1,224 @@
-+/*
-+ * 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);
-+
-+ 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_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_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 (*get_gpio_pin_info)(
-+ struct dc_bios *bios,
-+ uint32_t gpio_id,
-+ struct gpio_pin_info *info);
-+ enum bp_result (*get_encoder_cap_info)(
-+ struct dc_bios *bios,
-+ struct graphics_object_id object_id,
-+ struct bp_encoder_cap_info *info);
-+
-+ 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 (*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_critical_state)(
-+ struct dc_bios *bios,
-+ bool state);
-+ 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);
-+ unsigned int (*get_smu_clock_info)(
-+ struct dc_bios *bios);
-+ 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 (*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 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_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);
-+
-+ void (*bios_parser_destroy)(struct dc_bios **dcb);
-+};
-+
-+struct bios_registers {
-+ uint32_t BIOS_SCRATCH_6;
-+};
-+
-+struct dc_bios {
-+ const struct dc_vbios_funcs *funcs;
-+
-+ uint8_t *bios;
-+ uint32_t bios_size;
-+
-+ uint8_t *bios_local_image;
-+
-+ struct dc_context *ctx;
-+ const struct bios_registers *regs;
-+ struct integrated_info *integrated_info;
-+};
-+
-+#endif /* DC_BIOS_TYPES_H */
-diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h
-new file mode 100644
-index 0000000..b143fe8
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h
-@@ -0,0 +1,115 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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;
-+ uint32_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 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 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/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
-new file mode 100644
-index 0000000..befc498
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
-@@ -0,0 +1,105 @@
-+/*
-+ * 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_DP_TYPES_H
-+#define DC_DP_TYPES_H
-+
-+enum dc_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
-+ * 810MBps for 8.10GHz
-+ */
-+enum dc_link_rate {
-+ LINK_RATE_UNKNOWN = 0,
-+ LINK_RATE_LOW = 0x06,
-+ LINK_RATE_HIGH = 0x0A,
-+ LINK_RATE_RBR2 = 0x0C,
-+ LINK_RATE_HIGH2 = 0x14,
-+ LINK_RATE_HIGH3 = 0x1E
-+};
-+
-+enum dc_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
-+};
-+
-+enum dc_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 dc_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
-+};
-+/* Post Cursor 2 is optional for transmitter
-+ * and it applies only to the main link operating at HBR2
-+ */
-+enum dc_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,
-+};
-+
-+struct dc_link_settings {
-+ enum dc_lane_count lane_count;
-+ enum dc_link_rate link_rate;
-+ enum dc_link_spread link_spread;
-+};
-+
-+struct dc_lane_settings {
-+ enum dc_voltage_swing VOLTAGE_SWING;
-+ enum dc_pre_emphasis PRE_EMPHASIS;
-+ enum dc_post_cursor2 POST_CURSOR2;
-+};
-+
-+struct dc_link_training_settings {
-+ struct dc_link_settings link;
-+ struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
-+};
-+
-+#endif /* DC_DP_TYPES_H */
-diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
-new file mode 100644
-index 0000000..3a80b0c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
-@@ -0,0 +1,144 @@
-+/*
-+ * dc_helper.c
-+ *
-+ * Created on: Aug 30, 2016
-+ * Author: agrodzov
-+ */
-+#include "dm_services.h"
-+#include <stdarg.h>
-+
-+uint32_t generic_reg_update_ex(const struct dc_context *ctx,
-+ uint32_t addr, uint32_t reg_val, int n,
-+ uint8_t shift1, uint32_t mask1, uint32_t field_value1,
-+ ...)
-+{
-+ uint32_t shift, mask, field_value;
-+ int i = 1;
-+
-+ va_list ap;
-+ va_start(ap, field_value1);
-+
-+ reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
-+
-+ while (i < n) {
-+ shift = va_arg(ap, uint32_t);
-+ mask = va_arg(ap, uint32_t);
-+ field_value = va_arg(ap, uint32_t);
-+
-+ reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
-+ i++;
-+ }
-+
-+ dm_write_reg(ctx, addr, reg_val);
-+ va_end(ap);
-+
-+ return reg_val;
-+}
-+
-+uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift, uint32_t mask, uint32_t *field_value)
-+{
-+ uint32_t reg_val = dm_read_reg(ctx, addr);
-+ *field_value = get_reg_field_value_ex(reg_val, mask, shift);
-+ return reg_val;
-+}
-+
-+uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2)
-+{
-+ uint32_t reg_val = dm_read_reg(ctx, addr);
-+ *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
-+ *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
-+ return reg_val;
-+}
-+
-+uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
-+ uint8_t shift3, uint32_t mask3, uint32_t *field_value3)
-+{
-+ uint32_t reg_val = dm_read_reg(ctx, addr);
-+ *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
-+ *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
-+ *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
-+ return reg_val;
-+}
-+
-+uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
-+ uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
-+ uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
-+ uint8_t shift5, uint32_t mask5, uint32_t *field_value5)
-+{
-+ uint32_t reg_val = dm_read_reg(ctx, addr);
-+ *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
-+ *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
-+ *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
-+ *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
-+ *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
-+ return reg_val;
-+}
-+
-+/* note: va version of this is pretty bad idea, since there is a output parameter pass by pointer
-+ * compiler won't be able to check for size match and is prone to stack corruption type of bugs
-+
-+uint32_t generic_reg_get(const struct dc_context *ctx,
-+ uint32_t addr, int n, ...)
-+{
-+ uint32_t shift, mask;
-+ uint32_t *field_value;
-+ uint32_t reg_val;
-+ int i = 0;
-+
-+ reg_val = dm_read_reg(ctx, addr);
-+
-+ va_list ap;
-+ va_start(ap, n);
-+
-+ while (i < n) {
-+ shift = va_arg(ap, uint32_t);
-+ mask = va_arg(ap, uint32_t);
-+ field_value = va_arg(ap, uint32_t *);
-+
-+ *field_value = get_reg_field_value_ex(reg_val, mask, shift);
-+ i++;
-+ }
-+
-+ va_end(ap);
-+
-+ return reg_val;
-+}
-+*/
-+
-+uint32_t generic_reg_wait(const struct dc_context *ctx,
-+ uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value,
-+ unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
-+ const char *func_name)
-+{
-+ uint32_t field_value;
-+ uint32_t reg_val;
-+ int i;
-+
-+ for (i = 0; i <= time_out_num_tries; i++) {
-+ if (i) {
-+ if (0 < delay_between_poll_us && delay_between_poll_us < 1000)
-+ udelay(delay_between_poll_us);
-+
-+ if (delay_between_poll_us > 1000)
-+ msleep(delay_between_poll_us/1000);
-+ }
-+
-+ reg_val = dm_read_reg(ctx, addr);
-+
-+ field_value = get_reg_field_value_ex(reg_val, mask, shift);
-+
-+ if (field_value == condition_value)
-+ return reg_val;
-+ }
-+
-+ DC_ERR("REG_WAIT timeout %dus * %d tries - %s",
-+ delay_between_poll_us, time_out_num_tries, func_name);
-+ return reg_val;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
-new file mode 100644
-index 0000000..5605a5c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
-@@ -0,0 +1,588 @@
-+/*
-+ * 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_HW_TYPES_H
-+#define DC_HW_TYPES_H
-+
-+#include "os_types.h"
-+
-+/******************************************************************************
-+ * Data types for Virtual HW Layer of DAL3.
-+ * (see DAL3 design documents for HW Layer definition)
-+ *
-+ * The intended uses are:
-+ * 1. Generation pseudocode sequences for HW programming.
-+ * 2. Implementation of real HW programming by HW Sequencer of DAL3.
-+ *
-+ * Note: do *not* add any types which are *not* used for HW programming - this
-+ * will ensure separation of Logic layer from HW layer.
-+ ******************************************************************************/
-+
-+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_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;
-+ PHYSICAL_ADDRESS_LOC meta_addr;
-+ union large_integer dcc_const_color;
-+ } grph;
-+
-+ /*stereo*/
-+ struct {
-+ PHYSICAL_ADDRESS_LOC left_addr;
-+ PHYSICAL_ADDRESS_LOC left_meta_addr;
-+ union large_integer left_dcc_const_color;
-+
-+ PHYSICAL_ADDRESS_LOC right_addr;
-+ PHYSICAL_ADDRESS_LOC right_meta_addr;
-+ union large_integer right_dcc_const_color;
-+
-+ } grph_stereo;
-+
-+ /*video progressive*/
-+ struct {
-+ PHYSICAL_ADDRESS_LOC luma_addr;
-+ PHYSICAL_ADDRESS_LOC luma_meta_addr;
-+ union large_integer luma_dcc_const_color;
-+
-+ PHYSICAL_ADDRESS_LOC chroma_addr;
-+ PHYSICAL_ADDRESS_LOC chroma_meta_addr;
-+ union large_integer chroma_dcc_const_color;
-+ } video_progressive;
-+ };
-+};
-+
-+struct dc_size {
-+ uint32_t width;
-+ uint32_t height;
-+};
-+
-+struct rect {
-+ int x;
-+ int y;
-+ uint32_t width;
-+ uint32_t height;
-+};
-+
-+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;
-+
-+ uint32_t meta_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;
-+ uint32_t meta_luma_pitch;
-+
-+ struct rect chroma_size;
-+ /* Graphic surface pitch in pixels.
-+ * In LINEAR_GENERAL mode, pitch is
-+ * 32 pixel aligned.
-+ */
-+ uint32_t chroma_pitch;
-+ uint32_t meta_chroma_pitch;
-+ } video;
-+};
-+
-+struct dc_plane_dcc_param {
-+ bool enable;
-+
-+ union {
-+ struct {
-+ uint32_t meta_pitch;
-+ bool independent_64b_blks;
-+ } grph;
-+
-+ struct {
-+ uint32_t meta_pitch_l;
-+ bool independent_64b_blks_l;
-+
-+ uint32_t meta_pitch_c;
-+ bool independent_64b_blks_c;
-+ } video;
-+ };
-+};
-+
-+/*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,
-+ /*float*/
-+ SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F,
-+ /*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_INVALID
-+
-+ /*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,
-+ /*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_420BPP12,
-+ PIXEL_FORMAT_UNKNOWN
-+};
-+
-+enum tile_split_values {
-+ DC_DISPLAY_MICRO_TILING = 0x0,
-+ DC_THIN_MICRO_TILING = 0x1,
-+ DC_DEPTH_MICRO_TILING = 0x2,
-+ DC_ROTATED_MICRO_TILING = 0x3,
-+};
-+
-+/* TODO: These values come from hardware spec. We need to readdress this
-+ * if they ever change.
-+ */
-+enum array_mode_values {
-+ DC_ARRAY_LINEAR_GENERAL = 0,
-+ DC_ARRAY_LINEAR_ALLIGNED,
-+ DC_ARRAY_1D_TILED_THIN1,
-+ DC_ARRAY_1D_TILED_THICK,
-+ DC_ARRAY_2D_TILED_THIN1,
-+ DC_ARRAY_PRT_TILED_THIN1,
-+ DC_ARRAY_PRT_2D_TILED_THIN1,
-+ DC_ARRAY_2D_TILED_THICK,
-+ DC_ARRAY_2D_TILED_X_THICK,
-+ DC_ARRAY_PRT_TILED_THICK,
-+ DC_ARRAY_PRT_2D_TILED_THICK,
-+ DC_ARRAY_PRT_3D_TILED_THIN1,
-+ DC_ARRAY_3D_TILED_THIN1,
-+ DC_ARRAY_3D_TILED_THICK,
-+ DC_ARRAY_3D_TILED_X_THICK,
-+ DC_ARRAY_PRT_3D_TILED_THICK,
-+};
-+
-+enum tile_mode_values {
-+ DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
-+ DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
-+};
-+
-+union dc_tiling_info {
-+
-+ struct {
-+ /* 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;
-+ unsigned int bank_width_c;
-+ /* 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;
-+ unsigned int bank_height_c;
-+ /* Specifies the macro tile aspect ratio. Only applies
-+ * to 2D and 3D tiling modes.
-+ */
-+ unsigned int tile_aspect;
-+ unsigned int tile_aspect_c;
-+ /* 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;
-+ enum tile_split_values tile_split_c;
-+ /* 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;
-+ enum tile_mode_values tile_mode_c;
-+ /* 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;
-+ } gfx8;
-+
-+};
-+
-+/* Rotation angle */
-+enum dc_rotation_angle {
-+ ROTATION_ANGLE_0 = 0,
-+ ROTATION_ANGLE_90,
-+ ROTATION_ANGLE_180,
-+ ROTATION_ANGLE_270,
-+ ROTATION_ANGLE_COUNT
-+};
-+
-+enum dc_scan_direction {
-+ SCAN_DIRECTION_UNKNOWN = 0,
-+ SCAN_DIRECTION_HORIZONTAL = 1, /* 0, 180 rotation */
-+ SCAN_DIRECTION_VERTICAL = 2, /* 90, 270 rotation */
-+};
-+
-+struct dc_cursor_position {
-+ uint32_t x;
-+ uint32_t y;
-+
-+ uint32_t x_hotspot;
-+ uint32_t y_hotspot;
-+
-+ /*
-+ * 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;
-+};
-+
-+/* IPP related types */
-+
-+/* Used by both ipp amd opp functions*/
-+/* TODO: to be consolidated with enum color_space */
-+
-+/*
-+ * 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
-+};
-+
-+/*
-+ * 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.
-+ */
-+
-+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 INVERT_PIXEL_DATA:1;
-+ uint32_t ZERO_EXPANSION:1;
-+ uint32_t MIN_MAX_INVERT:1;
-+ uint32_t RESERVED:25;
-+ } bits;
-+ uint32_t value;
-+};
-+
-+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;
-+};
-+
-+/* OPP */
-+
-+enum dc_color_space {
-+ COLOR_SPACE_UNKNOWN,
-+ COLOR_SPACE_SRGB,
-+ COLOR_SPACE_SRGB_LIMITED,
-+ COLOR_SPACE_YPBPR601,
-+ COLOR_SPACE_YPBPR709,
-+ COLOR_SPACE_YCBCR601,
-+ COLOR_SPACE_YCBCR709,
-+ COLOR_SPACE_YCBCR601_LIMITED,
-+ COLOR_SPACE_YCBCR709_LIMITED
-+};
-+
-+enum dc_quantization_range {
-+ QUANTIZATION_RANGE_UNKNOWN,
-+ QUANTIZATION_RANGE_FULL,
-+ QUANTIZATION_RANGE_LIMITED
-+};
-+
-+/* XFM */
-+
-+/* used in struct dc_surface */
-+struct scaling_taps {
-+ uint32_t v_taps;
-+ uint32_t h_taps;
-+ uint32_t v_taps_c;
-+ uint32_t h_taps_c;
-+};
-+
-+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_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_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_pixel_encoding {
-+ PIXEL_ENCODING_UNDEFINED,
-+ PIXEL_ENCODING_RGB,
-+ PIXEL_ENCODING_YCBCR422,
-+ PIXEL_ENCODING_YCBCR444,
-+ PIXEL_ENCODING_YCBCR420,
-+ PIXEL_ENCODING_COUNT
-+};
-+
-+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 scanning_type {
-+ SCANNING_TYPE_NODATA = 0,
-+ SCANNING_TYPE_OVERSCAN,
-+ SCANNING_TYPE_UNDERSCAN,
-+ SCANNING_TYPE_FUTURE,
-+ SCANNING_TYPE_UNDEFINED
-+};
-+
-+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;
-+
-+};
-+
-+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_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;
-+};
-+
-+#endif /* DC_HW_TYPES_H */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
-new file mode 100644
-index 0000000..ae9fcca
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
-@@ -0,0 +1,493 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "fixed32_32.h"
-+#include "fixed31_32.h"
-+#include "irq_types.h"
-+#include "dc_dp_types.h"
-+#include "dc_hw_types.h"
-+#include "dal_types.h"
-+
-+/* forward declarations */
-+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))
-+
-+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;
-+ uint32_t fake_paths_num;
-+ void *atombios_base_address;
-+};
-+
-+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;
-+ struct hw_asic_id asic_id;
-+
-+ /* todo: below should probably move to dc. to facilitate removal
-+ * of AS we will store these here
-+ */
-+ enum dce_version dce_version;
-+ struct dc_bios *dc_bios;
-+ bool created_bios;
-+ struct gpio_service *gpio_service;
-+ struct i2caux *i2caux;
-+};
-+
-+
-+#define MAX_EDID_BUFFER_SIZE 512
-+#define EDID_BLOCK_SIZE 128
-+#define MAX_SURFACE_NUM 2
-+#define NUM_PIXEL_FORMATS 10
-+
-+#include "dc_ddc_types.h"
-+
-+enum tiling_mode {
-+ TILING_MODE_INVALID,
-+ TILING_MODE_LINEAR,
-+ TILING_MODE_TILED,
-+ TILING_MODE_COUNT
-+};
-+
-+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 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
-+};
-+
-+/* TODO: Find way to calculate number of bits
-+ * Please increase if pixel_format enum increases
-+ * num from PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32
-+ */
-+
-+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,
-+};
-+
-+/* 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*/
-+ bool lte_340mcsc_scramble;
-+
-+ bool edid_hdmi;
-+};
-+
-+struct view {
-+ 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;
-+};
-+
-+
-+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;
-+};
-+
-+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
-+};
-+
-+enum dc_connection_type {
-+ dc_connection_none,
-+ dc_connection_single,
-+ dc_connection_mst_branch,
-+ dc_connection_active_dongle
-+};
-+
-+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
-+};
-+
-+/* audio*/
-+
-+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;
-+};
-+
-+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;
-+ };
-+};
-+
-+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_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 freesync_context {
-+ bool supported;
-+ bool enabled;
-+ bool active;
-+
-+ unsigned int min_refresh_in_micro_hz;
-+ unsigned int nominal_refresh_in_micro_hz;
-+};
-+
-+struct colorspace_transform {
-+ struct fixed31_32 matrix[12];
-+ bool enable_remap;
-+};
-+
-+struct csc_transform {
-+ uint16_t matrix[12];
-+ bool enable_adjustment;
-+};
-+
-+struct psr_caps {
-+ /* These parameters are from PSR capabilities reported by Sink DPCD */
-+ unsigned char psr_version;
-+ unsigned int psr_rfb_setup_time;
-+ bool psr_exit_link_training_required;
-+
-+ /* 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 set up RFB, it may take an extra frame to enter PSR state.
-+ */
-+ bool psr_frame_capture_indication_req;
-+ unsigned int psr_sdp_transmit_line_num_deadline;
-+};
-+
-+#endif /* DC_TYPES_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile
-new file mode 100644
-index 0000000..bfca381
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile
-@@ -0,0 +1,14 @@
-+#
-+# Makefile for common 'dce' logic
-+# HW object file under this folder follow similar pattern for HW programming
-+# - register offset and/or shift + mask stored in the dec_hw struct
-+# - register programming through common macros that look up register
-+# offset/shift/mask stored in dce_hw struct
-+
-+DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
-+dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o
-+
-+
-+AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_DCE)
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
-new file mode 100644
-index 0000000..dc44053
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
-@@ -0,0 +1,920 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "reg_helper.h"
-+#include "dce_audio.h"
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+#define DCE_AUD(audio)\
-+ container_of(audio, struct dce_audio, base)
-+
-+#define CTX \
-+ aud->base.ctx
-+#define REG(reg)\
-+ (aud->regs->reg)
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ aud->shifts->field_name, aud->masks->field_name
-+
-+#define IX_REG(reg)\
-+ ix ## reg
-+
-+#define AZ_REG_READ(reg_name) \
-+ read_indirect_azalia_reg(audio, IX_REG(reg_name))
-+
-+#define AZ_REG_WRITE(reg_name, value) \
-+ write_indirect_azalia_reg(audio, IX_REG(reg_name), value)
-+
-+static void write_indirect_azalia_reg(struct audio *audio,
-+ uint32_t reg_index,
-+ uint32_t reg_data)
-+{
-+ struct dce_audio *aud = DCE_AUD(audio);
-+
-+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */
-+ REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0,
-+ AZALIA_ENDPOINT_REG_INDEX, reg_index);
-+
-+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */
-+ REG_SET(AZALIA_F0_CODEC_ENDPOINT_DATA, 0,
-+ AZALIA_ENDPOINT_REG_DATA, reg_data);
-+
-+ dm_logger_write(CTX->logger, LOG_HW_AUDIO,
-+ "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n",
-+ reg_index, reg_data);
-+}
-+
-+static uint32_t read_indirect_azalia_reg(struct audio *audio, uint32_t reg_index)
-+{
-+ struct dce_audio *aud = DCE_AUD(audio);
-+
-+ uint32_t value = 0;
-+
-+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */
-+ REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0,
-+ AZALIA_ENDPOINT_REG_INDEX, reg_index);
-+
-+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */
-+ value = REG_READ(AZALIA_F0_CODEC_ENDPOINT_DATA);
-+
-+ dm_logger_write(CTX->logger, LOG_HW_AUDIO,
-+ "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n",
-+ reg_index, value);
-+
-+ return value;
-+}
-+
-+static bool is_audio_format_supported(
-+ 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;
-+}
-+
-+/*For HDMI, calculate if specified sample rates can fit into a given timing */
-+static void check_audio_bandwidth_hdmi(
-+ 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 */
-+static void check_audio_bandwidth_dpsst(
-+ 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 */
-+static void check_audio_bandwidth_dpmst(
-+ const struct audio_crtc_info *crtc_info,
-+ uint32_t channel_count,
-+ union audio_sample_rates *sample_rates)
-+{
-+ /* do nothing */
-+}
-+
-+static void check_audio_bandwidth(
-+ 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:
-+ check_audio_bandwidth_hdmi(
-+ crtc_info, channel_count, sample_rates);
-+ break;
-+ case SIGNAL_TYPE_EDP:
-+ case SIGNAL_TYPE_DISPLAY_PORT:
-+ check_audio_bandwidth_dpsst(
-+ crtc_info, channel_count, sample_rates);
-+ break;
-+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
-+ check_audio_bandwidth_dpmst(
-+ crtc_info, channel_count, sample_rates);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/* expose/not expose HBR capability to Audio driver */
-+static void set_high_bit_rate_capable(
-+ struct audio *audio,
-+ bool capable)
-+{
-+ uint32_t value = 0;
-+
-+ /* set high bit rate audio capable*/
-+ value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR);
-+
-+ set_reg_field_value(value, capable,
-+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
-+ HBR_CAPABLE);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value);
-+}
-+
-+/* set video latency in in ms/2+1 */
-+static void set_video_latency(
-+ struct audio *audio,
-+ int latency_in_ms)
-+{
-+ uint32_t value = 0;
-+
-+ if ((latency_in_ms < 0) || (latency_in_ms > 255))
-+ return;
-+
-+ value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
-+
-+ set_reg_field_value(value, latency_in_ms,
-+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
-+ VIDEO_LIPSYNC);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
-+ value);
-+}
-+
-+/* set audio latency in in ms/2+1 */
-+static void set_audio_latency(
-+ struct audio *audio,
-+ 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 = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
-+
-+ set_reg_field_value(value, latency_in_ms,
-+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
-+ AUDIO_LIPSYNC);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
-+ value);
-+}
-+
-+void dce_aud_az_enable(struct audio *audio)
-+{
-+ uint32_t value = AZ_REG_READ(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
-+}
-+
-+void dce_aud_az_disable(struct audio *audio)
-+{
-+ uint32_t value;
-+
-+ value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
-+
-+ set_reg_field_value(value, 0,
-+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
-+ AUDIO_ENABLED);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
-+}
-+
-+void dce_aud_az_configure(
-+ struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_info *audio_info)
-+{
-+ struct dce_audio *aud = DCE_AUD(audio);
-+
-+ 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;
-+ union audio_sample_rates sample_rate;
-+ uint32_t strlen = 0;
-+
-+ /* Speaker Allocation */
-+ /*
-+ uint32_t value;
-+ uint32_t field = 0;*/
-+ value = AZ_REG_READ(AZALIA_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);
-+ /* todo: according to reg spec LFE_PLAYBACK_LEVEL is read only.
-+ * why are we writing to it? DCE8 does not write this */
-+
-+
-+ 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_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_TO_DEBUGGER();
-+ break;
-+ }
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, 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 */
-+ if (is_audio_format_supported(
-+ audio_info, audio_format_code, &index)) {
-+ 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: {
-+ check_audio_bandwidth(
-+ 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 */
-+
-+ AZ_REG_WRITE(
-+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + format_index,
-+ value);
-+ } /* for */
-+
-+ if (is_ac3_supported)
-+ /* todo: this reg global. why program global register? */
-+ REG_WRITE(AZALIA_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;
-+
-+ check_audio_bandwidth(
-+ crtc_info,
-+ 8,
-+ signal,
-+ &sample_rate);
-+
-+ set_high_bit_rate_capable(audio, sample_rate.rate.RATE_192);
-+
-+ /* Audio and Video Lipsync */
-+ set_video_latency(audio, audio_info->video_latency);
-+ set_audio_latency(audio, 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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_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);
-+
-+ AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, value);
-+}
-+
-+/*
-+* todo: wall clk related functionality probably belong to clock_src.
-+*/
-+
-+/* search pixel clock value for Azalia HDMI Audio */
-+static bool get_azalia_clock_info_hdmi(
-+ 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;
-+}
-+
-+static bool get_azalia_clock_info_dp(
-+ 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;
-+}
-+
-+void dce_aud_wall_dto_setup(
-+ struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_pll_info *pll_info)
-+{
-+ struct dce_audio *aud = DCE_AUD(audio);
-+
-+ struct azalia_clock_info clock_info = { 0 };
-+
-+ if (dc_is_hdmi_signal(signal)) {
-+ uint32_t src_sel;
-+
-+ /*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(
-+ 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 */
-+ src_sel = pll_info->dto_source - DTO_SOURCE_ID0;
-+ REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE,
-+ DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel,
-+ DCCG_AUDIO_DTO_SEL, 0);
-+
-+ /* module */
-+ REG_UPDATE(DCCG_AUDIO_DTO0_MODULE,
-+ DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module);
-+
-+ /* phase */
-+ REG_UPDATE(DCCG_AUDIO_DTO0_PHASE,
-+ DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase);
-+ } 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(
-+ crtc_info->requested_pixel_clock,
-+ pll_info,
-+ &clock_info);
-+
-+ /* Program DTO select before programming DTO modulo and DTO
-+ phase. default to use DTO1 */
-+
-+ REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
-+ DCCG_AUDIO_DTO_SEL, 1);
-+
-+ REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
-+ DCCG_AUDIO_DTO_SEL, 1);
-+ /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1)
-+ * Select 512fs for DP TODO: web register definition
-+ * does not match register header file
-+ * DCE11 version it's commented out while DCE8 it's set to 1
-+ */
-+
-+ /* module */
-+ REG_UPDATE(DCCG_AUDIO_DTO1_MODULE,
-+ DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module);
-+
-+ /* phase */
-+ REG_UPDATE(DCCG_AUDIO_DTO1_PHASE,
-+ DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase);
-+
-+ /* 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);*/
-+ }
-+}
-+
-+bool dce_aud_endpoint_valid(
-+ struct audio *audio)
-+{
-+ uint32_t value;
-+ uint32_t port_connectivity;
-+
-+ value = AZ_REG_READ(
-+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT);
-+
-+ port_connectivity = get_reg_field_value(value,
-+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
-+ PORT_CONNECTIVITY);
-+
-+ return !(port_connectivity == 1);
-+}
-+
-+/* initialize HW state */
-+void dce_aud_hw_init(
-+ struct audio *audio)
-+{
-+ struct dce_audio *aud = DCE_AUD(audio);
-+
-+ /* we only need to program the following registers once, so we only do
-+ it for the inst 0*/
-+ if (audio->inst != 0)
-+ return;
-+
-+ /* Suport R5 - 32khz
-+ * Suport R6 - 44.1khz
-+ * Suport R7 - 48khz
-+ */
-+ REG_UPDATE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
-+ AUDIO_RATE_CAPABILITIES, 0x70);
-+
-+ /*Keep alive bit to verify HW block in BU. */
-+ REG_UPDATE_2(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
-+ CLKSTOP, 1,
-+ EPSS, 1);
-+}
-+
-+static const struct audio_funcs funcs = {
-+ .endpoint_valid = dce_aud_endpoint_valid,
-+ .hw_init = dce_aud_hw_init,
-+ .wall_dto_setup = dce_aud_wall_dto_setup,
-+ .az_enable = dce_aud_az_enable,
-+ .az_disable = dce_aud_az_disable,
-+ .az_configure = dce_aud_az_configure,
-+ .destroy = dce_aud_destroy,
-+};
-+
-+void dce_aud_destroy(struct audio **audio)
-+{
-+ dm_free(*audio);
-+ *audio = NULL;
-+}
-+
-+struct audio *dce_audio_create(
-+ struct dc_context *ctx,
-+ unsigned int inst,
-+ const struct dce_audio_registers *reg,
-+ const struct dce_audio_shift *shifts,
-+ const struct dce_aduio_mask *masks
-+ )
-+{
-+ struct dce_audio *audio = dm_alloc(sizeof(*audio));
-+
-+ if (audio == NULL) {
-+ ASSERT_CRITICAL(audio);
-+ return NULL;
-+ }
-+
-+ audio->base.ctx = ctx;
-+ audio->base.inst = inst;
-+ audio->base.funcs = &funcs;
-+
-+ audio->regs = reg;
-+ audio->shifts = shifts;
-+ audio->masks = masks;
-+
-+ return &audio->base;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
-new file mode 100644
-index 0000000..bf97cd8
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
-@@ -0,0 +1,145 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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.h"
-+
-+#define AUD_COMMON_REG_LIST(id)\
-+ SRI(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id),\
-+ SRI(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id),\
-+ SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS),\
-+ SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES),\
-+ SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES),\
-+ SR(DCCG_AUDIO_DTO_SOURCE),\
-+ SR(DCCG_AUDIO_DTO0_MODULE),\
-+ SR(DCCG_AUDIO_DTO0_PHASE),\
-+ SR(DCCG_AUDIO_DTO1_MODULE),\
-+ SR(DCCG_AUDIO_DTO1_PHASE)
-+
-+
-+ /* set field name */
-+#define SF(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+
-+#define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\
-+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
-+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
-+ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
-+ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
-+ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
-+ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
-+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
-+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
-+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh)
-+
-+#define AUD_COMMON_MASK_SH_LIST(mask_sh)\
-+ AUD_COMMON_MASK_SH_LIST_BASE(mask_sh),\
-+ SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
-+ SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh)
-+
-+
-+struct dce_audio_registers {
-+ uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX;
-+ uint32_t AZALIA_F0_CODEC_ENDPOINT_DATA;
-+
-+ uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS;
-+ uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
-+ uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
-+
-+ uint32_t DCCG_AUDIO_DTO_SOURCE;
-+ uint32_t DCCG_AUDIO_DTO0_MODULE;
-+ uint32_t DCCG_AUDIO_DTO0_PHASE;
-+ uint32_t DCCG_AUDIO_DTO1_MODULE;
-+ uint32_t DCCG_AUDIO_DTO1_PHASE;
-+
-+ uint32_t AUDIO_RATE_CAPABILITIES;
-+};
-+
-+struct dce_audio_shift {
-+ uint8_t AZALIA_ENDPOINT_REG_INDEX;
-+ uint8_t AZALIA_ENDPOINT_REG_DATA;
-+
-+ uint8_t AUDIO_RATE_CAPABILITIES;
-+ uint8_t CLKSTOP;
-+ uint8_t EPSS;
-+
-+ uint8_t DCCG_AUDIO_DTO0_SOURCE_SEL;
-+ uint8_t DCCG_AUDIO_DTO_SEL;
-+ uint8_t DCCG_AUDIO_DTO0_MODULE;
-+ uint8_t DCCG_AUDIO_DTO0_PHASE;
-+ uint8_t DCCG_AUDIO_DTO1_MODULE;
-+ uint8_t DCCG_AUDIO_DTO1_PHASE;
-+};
-+
-+struct dce_aduio_mask {
-+ uint32_t AZALIA_ENDPOINT_REG_INDEX;
-+ uint32_t AZALIA_ENDPOINT_REG_DATA;
-+
-+ uint32_t AUDIO_RATE_CAPABILITIES;
-+ uint32_t CLKSTOP;
-+ uint32_t EPSS;
-+
-+ uint32_t DCCG_AUDIO_DTO0_SOURCE_SEL;
-+ uint32_t DCCG_AUDIO_DTO_SEL;
-+ uint32_t DCCG_AUDIO_DTO0_MODULE;
-+ uint32_t DCCG_AUDIO_DTO0_PHASE;
-+ uint32_t DCCG_AUDIO_DTO1_MODULE;
-+ uint32_t DCCG_AUDIO_DTO1_PHASE;
-+};
-+
-+struct dce_audio {
-+ struct audio base;
-+ const struct dce_audio_registers *regs;
-+ const struct dce_audio_shift *shifts;
-+ const struct dce_aduio_mask *masks;
-+};
-+
-+struct audio *dce_audio_create(
-+ struct dc_context *ctx,
-+ unsigned int inst,
-+ const struct dce_audio_registers *reg,
-+ const struct dce_audio_shift *shifts,
-+ const struct dce_aduio_mask *masks);
-+
-+void dce_aud_destroy(struct audio **audio);
-+
-+void dce_aud_hw_init(struct audio *audio);
-+
-+void dce_aud_az_enable(struct audio *audio);
-+void dce_aud_az_disable(struct audio *audio);
-+
-+void dce_aud_az_configure(struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_info *audio_info);
-+
-+void dce_aud_wall_dto_setup(struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_pll_info *pll_info);
-+
-+#endif /*__DAL_AUDIO_DCE_110_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
-new file mode 100644
-index 0000000..80ac5d9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
-@@ -0,0 +1,1264 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_types.h"
-+#include "core_types.h"
-+
-+#include "include/grph_object_id.h"
-+#include "include/logger_interface.h"
-+
-+#include "dce_clock_source.h"
-+
-+#include "reg_helper.h"
-+
-+#define REG(reg)\
-+ (clk_src->regs->reg)
-+
-+#define CTX \
-+ clk_src->base.ctx
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ clk_src->cs_shift->field_name, clk_src->cs_mask->field_name
-+
-+#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:
-+ case SIGNAL_TYPE_VIRTUAL:
-+ 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) {
-+ dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
-+ "%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) {
-+ dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
-+ "%s Post divider range is invalid", __func__);
-+ return MAX_PLL_CALC_ERROR;
-+ }
-+
-+ if (min_ref_divider > max_ref_divider) {
-+ dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
-+ "%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_helper (
-+ struct dce110_clk_src *clk_src,
-+ struct pll_settings *pll_settings,
-+ struct pixel_clk_params *pix_clk_params)
-+{
-+ uint32_t addr = 0;
-+ uint32_t value = 0;
-+ uint32_t field = 0;
-+ uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;
-+
-+ /* 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 */
-+ value = REG_READ(PLL_CNTL);
-+ REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field);
-+ 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. */
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR,
-+ "%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 void dce112_get_pix_clk_dividers_helper (
-+ struct dce110_clk_src *clk_src,
-+ struct pll_settings *pll_settings,
-+ struct pixel_clk_params *pix_clk_params)
-+{
-+ uint32_t actualPixelClockInKHz;
-+
-+ actualPixelClockInKHz = pix_clk_params->requested_pix_clk;
-+ /* Calculate Dividers */
-+ if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {
-+ switch (pix_clk_params->color_depth) {
-+ case COLOR_DEPTH_101010:
-+ actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2;
-+ break;
-+ case COLOR_DEPTH_161616:
-+ actualPixelClockInKHz = actualPixelClockInKHz * 2;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ pll_settings->actual_pix_clk = actualPixelClockInKHz;
-+ pll_settings->adjusted_pix_clk = actualPixelClockInKHz;
-+ pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk;
-+}
-+
-+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;
-+
-+ if (pix_clk_params == NULL || pll_settings == NULL
-+ || pix_clk_params->requested_pix_clk == 0) {
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR,
-+ "%s: Invalid parameters!!\n", __func__);
-+ return pll_calc_error;
-+ }
-+
-+ memset(pll_settings, 0, sizeof(*pll_settings));
-+
-+ if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||
-+ 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;
-+ }
-+
-+ switch (cs->ctx->dce_version) {
-+ case DCE_VERSION_8_0:
-+ case DCE_VERSION_10_0:
-+ case DCE_VERSION_11_0:
-+ pll_calc_error =
-+ dce110_get_pix_clk_dividers_helper(clk_src,
-+ pll_settings, pix_clk_params);
-+ break;
-+ case DCE_VERSION_11_2:
-+ dce112_get_pix_clk_dividers_helper(clk_src,
-+ pll_settings, pix_clk_params);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ 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;
-+
-+ 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 dce110_program_pixel_clk_resync(
-+ struct dce110_clk_src *clk_src,
-+ enum signal_type signal_type,
-+ enum dc_color_depth colordepth)
-+{
-+ uint32_t value = 0;
-+
-+ REG_UPDATE(RESYNC_CNTL,
-+ DCCG_DEEP_COLOR_CNTL1, 0);
-+ /*
-+ 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:
-+ REG_UPDATE(RESYNC_CNTL,
-+ DCCG_DEEP_COLOR_CNTL1, 0);
-+ break;
-+ case COLOR_DEPTH_101010:
-+ REG_UPDATE(RESYNC_CNTL,
-+ DCCG_DEEP_COLOR_CNTL1, 1);
-+ break;
-+ case COLOR_DEPTH_121212:
-+ REG_UPDATE(RESYNC_CNTL,
-+ DCCG_DEEP_COLOR_CNTL1, 2);
-+ break;
-+ case COLOR_DEPTH_161616:
-+ REG_UPDATE(RESYNC_CNTL,
-+ DCCG_DEEP_COLOR_CNTL1, 3);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static void dce112_program_pixel_clk_resync(
-+ struct dce110_clk_src *clk_src,
-+ enum signal_type signal_type,
-+ enum dc_color_depth colordepth,
-+ bool enable_ycbcr420)
-+{
-+ uint32_t value = 0;
-+
-+ REG_UPDATE(PIXCLK_RESYNC_CNTL,
-+ PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0);
-+ /*
-+ 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:
-+ REG_UPDATE_2(PIXCLK_RESYNC_CNTL,
-+ PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0,
-+ PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420);
-+ break;
-+ case COLOR_DEPTH_101010:
-+ REG_UPDATE_2(PIXCLK_RESYNC_CNTL,
-+ PHYPLLA_DCCG_DEEP_COLOR_CNTL, 1,
-+ PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420);
-+ break;
-+ case COLOR_DEPTH_121212:
-+ REG_UPDATE_2(PIXCLK_RESYNC_CNTL,
-+ PHYPLLA_DCCG_DEEP_COLOR_CNTL, 2,
-+ PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420);
-+ break;
-+ case COLOR_DEPTH_161616:
-+ REG_UPDATE_2(PIXCLK_RESYNC_CNTL,
-+ PHYPLLA_DCCG_DEEP_COLOR_CNTL, 3,
-+ PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+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) &&
-+ clk_src->ctx->dce_version <= DCE_VERSION_11_0)
-+ 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.encoder_object_id = pix_clk_params->encoder_object_id;
-+ bp_pc_params.signal_type = pix_clk_params->signal_type;
-+
-+ switch (clk_src->ctx->dce_version) {
-+ case DCE_VERSION_11_2:
-+ if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) {
-+ bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =
-+ pll_settings->use_external_clk;
-+ bp_pc_params.flags.SET_XTALIN_REF_SRC =
-+ !pll_settings->use_external_clk;
-+ if (pix_clk_params->flags.SUPPORT_YCBCR420) {
-+ bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2;
-+ bp_pc_params.flags.SUPPORT_YUV_420 = 1;
-+ }
-+ }
-+ if (dce110_clk_src->bios->funcs->set_pixel_clock(
-+ dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
-+ return false;
-+ /* Resync deep color DTO */
-+ if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO)
-+ dce112_program_pixel_clk_resync(dce110_clk_src,
-+ pix_clk_params->signal_type,
-+ pix_clk_params->color_depth,
-+ pix_clk_params->flags.SUPPORT_YCBCR420);
-+ break;
-+ case DCE_VERSION_8_0:
-+ case DCE_VERSION_10_0:
-+ case DCE_VERSION_11_0:
-+ 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.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 */
-+ dce110_program_pixel_clk_resync(dce110_clk_src,
-+ pix_clk_params->signal_type,
-+ pix_clk_params->color_depth);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ 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->dp_clk_src)
-+ 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 const 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) {
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
-+ "Invalid entry !!!\n");
-+ return;
-+ }
-+ if (spread_spectrum_data == NULL) {
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
-+ "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(sizeof(struct spread_spectrum_info) * (*ss_entries_num));
-+ ss_info_cur = ss_info;
-+ if (ss_info == NULL)
-+ return;
-+
-+ ss_data = dm_alloc(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) {
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
-+ "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 */
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
-+ "Invalid SS percentage ");
-+ dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC,
-+ "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(ss_info);
-+ return;
-+
-+out_free_data:
-+ dm_free(ss_data);
-+ *ss_entries_num = 0;
-+out_free_info:
-+ dm_free(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) {
-+ dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
-+ "The dec point num or precision is incorrect!");
-+ return false;
-+ }
-+ if (init_data->num_fract_fb_divider_decimal_point_precision == 0) {
-+ dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR,
-+ "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_regs *regs,
-+ const struct dce110_clk_src_shift *cs_shift,
-+ const struct dce110_clk_src_mask *cs_mask)
-+{
-+ struct firmware_info fw_info = { { 0 } };
-+ struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi;
-+ struct calc_pll_clock_source_init_data calc_pll_cs_init_data;
-+
-+ clk_src->base.ctx = ctx;
-+ clk_src->bios = bios;
-+ clk_src->base.id = id;
-+ clk_src->base.funcs = &dce110_clk_src_funcs;
-+
-+ clk_src->regs = regs;
-+ clk_src->cs_shift = cs_shift;
-+ clk_src->cs_mask = cs_mask;
-+
-+ 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;
-+
-+ switch (clk_src->base.ctx->dce_version) {
-+ case DCE_VERSION_8_0:
-+ case DCE_VERSION_10_0:
-+ case DCE_VERSION_11_0:
-+
-+ /* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
-+ calc_pll_cs_init_data.bp = bios;
-+ calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1;
-+ calc_pll_cs_init_data.max_pix_clk_pll_post_divider =
-+ clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
-+ calc_pll_cs_init_data.min_pll_ref_divider = 1;
-+ calc_pll_cs_init_data.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV;
-+ /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-+ calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz = 0;
-+ /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-+ calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz = 0;
-+ /*numberOfFractFBDividerDecimalPoints*/
-+ calc_pll_cs_init_data.num_fract_fb_divider_decimal_point =
-+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-+ /*number of decimal point to round off for fractional feedback divider value*/
-+ calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision =
-+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-+ calc_pll_cs_init_data.ctx = ctx;
-+
-+ /*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
-+ calc_pll_cs_init_data_hdmi.bp = bios;
-+ calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1;
-+ calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider =
-+ clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
-+ calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1;
-+ calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV;
-+ /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-+ calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500;
-+ /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-+ calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000;
-+ /*numberOfFractFBDividerDecimalPoints*/
-+ calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point =
-+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-+ /*number of decimal point to round off for fractional feedback divider value*/
-+ calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision =
-+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-+ calc_pll_cs_init_data_hdmi.ctx = ctx;
-+
-+ 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;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return true;
-+
-+unexpected_failure:
-+ return false;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
-new file mode 100644
-index 0000000..067e4ac
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
-@@ -0,0 +1,109 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_DCE_H__
-+#define __DC_CLOCK_SOURCE_DCE_H__
-+
-+#include "../inc/clock_source.h"
-+
-+#define TO_DCE110_CLK_SRC(clk_src)\
-+ container_of(clk_src, struct dce110_clk_src, base)
-+
-+#define CS_COMMON_REG_LIST_DCE_100_110(id) \
-+ SRI(RESYNC_CNTL, PIXCLK, id), \
-+ SRI(PLL_CNTL, BPHYC_PLL, id)
-+
-+#define CS_COMMON_REG_LIST_DCE_80(id) \
-+ SRI(RESYNC_CNTL, PIXCLK, id), \
-+ SRI(PLL_CNTL, DCCG_PLL, id)
-+
-+#define CS_COMMON_REG_LIST_DCE_112(id) \
-+ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id)
-+
-+#define CS_SF(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+#define CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
-+ CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\
-+ CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\
-+ CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\
-+ CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\
-+
-+#define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\
-+ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
-+ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\
-+
-+#define CS_REG_FIELD_LIST(type) \
-+ type PLL_REF_DIV_SRC; \
-+ type DCCG_DEEP_COLOR_CNTL1; \
-+ type PHYPLLA_DCCG_DEEP_COLOR_CNTL; \
-+ type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \
-+ type PLL_POST_DIV_PIXCLK; \
-+ type PLL_REF_DIV; \
-+
-+struct dce110_clk_src_shift {
-+ CS_REG_FIELD_LIST(uint8_t)
-+};
-+
-+struct dce110_clk_src_mask{
-+ CS_REG_FIELD_LIST(uint32_t)
-+};
-+
-+struct dce110_clk_src_regs {
-+ uint32_t RESYNC_CNTL;
-+ uint32_t PIXCLK_RESYNC_CNTL;
-+ uint32_t PLL_CNTL;
-+};
-+
-+struct dce110_clk_src {
-+ struct clock_source base;
-+ const struct dce110_clk_src_regs *regs;
-+ const struct dce110_clk_src_mask *cs_mask;
-+ const struct dce110_clk_src_shift *cs_shift;
-+ 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_regs *regs,
-+ const struct dce110_clk_src_shift *cs_shift,
-+ const struct dce110_clk_src_mask *cs_mask);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
-new file mode 100644
-index 0000000..dd1cf5e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
-@@ -0,0 +1,195 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "dce_hwseq.h"
-+#include "reg_helper.h"
-+#include "hw_sequencer.h"
-+
-+#define CTX \
-+ hws->ctx
-+#define REG(reg)\
-+ hws->regs->reg
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ hws->shifts->field_name, hws->masks->field_name
-+
-+void dce_enable_fe_clock(struct dce_hwseq *hws,
-+ unsigned int fe_inst, bool enable)
-+{
-+ REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst],
-+ DCFE_CLOCK_ENABLE, enable);
-+}
-+
-+void dce_pipe_control_lock(struct dce_hwseq *hws,
-+ unsigned int blnd_inst,
-+ enum pipe_lock_control control_mask,
-+ bool lock)
-+{
-+ uint32_t lock_val = lock ? 1 : 0;
-+ uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode;
-+
-+ uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst],
-+ BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
-+ BLND_SCL_V_UPDATE_LOCK, &scl,
-+ BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf,
-+ BLND_BLND_V_UPDATE_LOCK, &blnd,
-+ BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);
-+
-+ if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
-+ dcp_grph = lock_val;
-+
-+ if (control_mask & PIPE_LOCK_CONTROL_SCL)
-+ scl = lock_val;
-+
-+ if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
-+ dcp_grph_surf = lock_val;
-+
-+ if (control_mask & PIPE_LOCK_CONTROL_BLENDER)
-+ blnd = lock_val;
-+
-+ if (control_mask & PIPE_LOCK_CONTROL_MODE)
-+ update_lock_mode = lock_val;
-+
-+ REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val,
-+ BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
-+ BLND_SCL_V_UPDATE_LOCK, scl,
-+ BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf,
-+ BLND_BLND_V_UPDATE_LOCK, blnd,
-+ BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
-+
-+ if (hws->wa.blnd_crtc_trigger)
-+ if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) {
-+ uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]);
-+ REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value);
-+ }
-+}
-+
-+void dce_set_blender_mode(struct dce_hwseq *hws,
-+ unsigned int blnd_inst,
-+ enum blnd_mode mode)
-+{
-+ uint32_t feedthrough = 1;
-+ uint32_t blnd_mode = 0;
-+ uint32_t multiplied_mode = 0;
-+ uint32_t alpha_mode = 2;
-+
-+ switch (mode) {
-+ case BLND_MODE_OTHER_PIPE:
-+ feedthrough = 0;
-+ blnd_mode = 1;
-+ alpha_mode = 0;
-+ break;
-+ case BLND_MODE_BLENDING:
-+ feedthrough = 0;
-+ blnd_mode = 2;
-+ alpha_mode = 0;
-+ multiplied_mode = 1;
-+ break;
-+ case BLND_MODE_CURRENT_PIPE:
-+ default:
-+ if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
-+ blnd_inst == 0)
-+ feedthrough = 0;
-+ break;
-+ }
-+
-+ REG_UPDATE_4(BLND_CONTROL[blnd_inst],
-+ BLND_FEEDTHROUGH_EN, feedthrough,
-+ BLND_ALPHA_MODE, alpha_mode,
-+ BLND_MODE, blnd_mode,
-+ BLND_MULTIPLIED_MODE, multiplied_mode);
-+}
-+
-+
-+static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
-+{
-+ if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
-+ REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
-+ DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
-+}
-+
-+static void dce_underlay_clock_enable(struct dce_hwseq *hws)
-+{
-+ /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
-+ if (REG(DCFEV_CLOCK_CONTROL))
-+ REG_UPDATE(DCFEV_CLOCK_CONTROL,
-+ DCFEV_CLOCK_ENABLE, 1);
-+}
-+
-+static void enable_hw_base_light_sleep(void)
-+{
-+ /* TODO: implement */
-+}
-+
-+static void disable_sw_manual_control_light_sleep(void)
-+{
-+ /* TODO: implement */
-+}
-+
-+void dce_clock_gating_power_up(struct dce_hwseq *hws,
-+ bool enable)
-+{
-+ if (enable) {
-+ enable_hw_base_light_sleep();
-+ disable_sw_manual_control_light_sleep();
-+ } else {
-+ dce_disable_sram_shut_down(hws);
-+ dce_underlay_clock_enable(hws);
-+ }
-+}
-+
-+void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
-+ struct clock_source *clk_src,
-+ unsigned int tg_inst)
-+{
-+ if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) {
-+ REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
-+ DP_DTO0_ENABLE, 1);
-+
-+ } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
-+ uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
-+
-+ REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
-+ PHYPLL_PIXEL_RATE_SOURCE, rate_source,
-+ PIXEL_RATE_PLL_SOURCE, 0);
-+
-+ REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
-+ DP_DTO0_ENABLE, 0);
-+
-+ } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
-+ uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
-+
-+ REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
-+ PIXEL_RATE_SOURCE, rate_source,
-+ DP_DTO0_ENABLE, 0);
-+
-+ if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
-+ REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
-+ PIXEL_RATE_PLL_SOURCE, 1);
-+ } else {
-+ DC_ERR("unknown clock source");
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
-new file mode 100644
-index 0000000..4af8d56
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
-@@ -0,0 +1,250 @@
-+/*
-+ * 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 __DCE_HWSEQ_H__
-+#define __DCE_HWSEQ_H__
-+
-+#include "hw_sequencer.h"
-+
-+#define HWSEQ_DCEF_REG_LIST_DCE8() \
-+ .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \
-+ .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \
-+ .DCFE_CLOCK_CONTROL[2] = mmCRTC2_CRTC_DCFE_CLOCK_CONTROL, \
-+ .DCFE_CLOCK_CONTROL[3] = mmCRTC3_CRTC_DCFE_CLOCK_CONTROL, \
-+ .DCFE_CLOCK_CONTROL[4] = mmCRTC4_CRTC_DCFE_CLOCK_CONTROL, \
-+ .DCFE_CLOCK_CONTROL[5] = mmCRTC5_CRTC_DCFE_CLOCK_CONTROL
-+
-+#define HWSEQ_DCEF_REG_LIST() \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 3), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 4), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 5), \
-+ SR(DC_MEM_GLOBAL_PWR_REQ_CNTL)
-+
-+#define HWSEQ_BLND_REG_LIST() \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 0), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 1), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 2), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 3), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 4), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 5), \
-+ SRII(BLND_CONTROL, BLND, 0), \
-+ SRII(BLND_CONTROL, BLND, 1), \
-+ SRII(BLND_CONTROL, BLND, 2), \
-+ SRII(BLND_CONTROL, BLND, 3), \
-+ SRII(BLND_CONTROL, BLND, 4), \
-+ SRII(BLND_CONTROL, BLND, 5)
-+
-+#define HWSEQ_PIXEL_RATE_REG_LIST(blk) \
-+ SRII(PIXEL_RATE_CNTL, blk, 0), \
-+ SRII(PIXEL_RATE_CNTL, blk, 1), \
-+ SRII(PIXEL_RATE_CNTL, blk, 2), \
-+ SRII(PIXEL_RATE_CNTL, blk, 3), \
-+ SRII(PIXEL_RATE_CNTL, blk, 4), \
-+ SRII(PIXEL_RATE_CNTL, blk, 5)
-+
-+#define HWSEQ_PHYPLL_REG_LIST(blk) \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 0), \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 1), \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 2), \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 3), \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 4), \
-+ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 5)
-+
-+#define HWSEQ_DCE11_REG_LIST_BASE() \
-+ SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
-+ SR(DCFEV_CLOCK_CONTROL), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \
-+ SRII(CRTC_H_BLANK_START_END, CRTC, 0),\
-+ SRII(CRTC_H_BLANK_START_END, CRTC, 1),\
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 0),\
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 1),\
-+ SRII(BLND_CONTROL, BLND, 0),\
-+ SRII(BLND_CONTROL, BLND, 1),\
-+ SR(BLNDV_CONTROL),\
-+ HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
-+
-+#define HWSEQ_DCE8_REG_LIST() \
-+ HWSEQ_DCEF_REG_LIST_DCE8(), \
-+ HWSEQ_BLND_REG_LIST(), \
-+ HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
-+
-+#define HWSEQ_DCE10_REG_LIST() \
-+ HWSEQ_DCEF_REG_LIST(), \
-+ HWSEQ_BLND_REG_LIST(), \
-+ HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
-+
-+#define HWSEQ_ST_REG_LIST() \
-+ HWSEQ_DCE11_REG_LIST_BASE(), \
-+ .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \
-+ .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \
-+ .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \
-+ .BLND_CONTROL[2] = mmBLNDV_CONTROL,
-+
-+#define HWSEQ_CZ_REG_LIST() \
-+ HWSEQ_DCE11_REG_LIST_BASE(), \
-+ SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \
-+ SRII(CRTC_H_BLANK_START_END, CRTC, 2), \
-+ SRII(BLND_V_UPDATE_LOCK, BLND, 2), \
-+ SRII(BLND_CONTROL, BLND, 2), \
-+ .DCFE_CLOCK_CONTROL[3] = mmDCFEV_CLOCK_CONTROL, \
-+ .CRTC_H_BLANK_START_END[3] = mmCRTCV_H_BLANK_START_END, \
-+ .BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \
-+ .BLND_CONTROL[3] = mmBLNDV_CONTROL
-+
-+#define HWSEQ_DCE112_REG_LIST() \
-+ HWSEQ_DCE10_REG_LIST(), \
-+ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \
-+ HWSEQ_PHYPLL_REG_LIST(CRTC)
-+
-+struct dce_hwseq_registers {
-+ uint32_t DCFE_CLOCK_CONTROL[6];
-+ uint32_t DCFEV_CLOCK_CONTROL;
-+ uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL;
-+ uint32_t BLND_V_UPDATE_LOCK[6];
-+ uint32_t BLND_CONTROL[6];
-+ uint32_t BLNDV_CONTROL;
-+
-+ uint32_t CRTC_H_BLANK_START_END[6];
-+ uint32_t PIXEL_RATE_CNTL[6];
-+ uint32_t PHYPLL_PIXEL_RATE_CNTL[6];
-+};
-+ /* set field name */
-+#define HWS_SF(blk_name, reg_name, field_name, post_fix)\
-+ .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix
-+
-+#define HWS_SF1(blk_name, reg_name, field_name, post_fix)\
-+ .field_name = blk_name ## reg_name ## __ ## blk_name ## field_name ## post_fix
-+
-+
-+#define HWSEQ_DCEF_MASK_SH_LIST(mask_sh, blk)\
-+ HWS_SF(blk, CLOCK_CONTROL, DCFE_CLOCK_ENABLE, mask_sh),\
-+ SF(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, mask_sh)
-+
-+#define HWSEQ_BLND_MASK_SH_LIST(mask_sh, blk)\
-+ HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(blk, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(blk, V_UPDATE_LOCK, BLND_BLND_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(blk, V_UPDATE_LOCK, BLND_V_UPDATE_LOCK_MODE, mask_sh),\
-+ HWS_SF(blk, CONTROL, BLND_FEEDTHROUGH_EN, mask_sh),\
-+ HWS_SF(blk, CONTROL, BLND_ALPHA_MODE, mask_sh),\
-+ HWS_SF(blk, CONTROL, BLND_MODE, mask_sh),\
-+ HWS_SF(blk, CONTROL, BLND_MULTIPLIED_MODE, mask_sh)
-+
-+#define HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, blk)\
-+ HWS_SF1(blk, PIXEL_RATE_CNTL, PIXEL_RATE_SOURCE, mask_sh),\
-+ HWS_SF(blk, PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh)
-+
-+#define HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, blk)\
-+ HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh),\
-+ HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh)
-+
-+#define HWSEQ_DCE8_MASK_SH_LIST(mask_sh)\
-+ .DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \
-+ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
-+ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\
-+ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
-+
-+#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\
-+ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\
-+ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\
-+ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
-+
-+#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\
-+ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
-+ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
-+ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
-+
-+#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\
-+ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
-+ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_)
-+
-+#define HWSEQ_REG_FIED_LIST(type) \
-+ type DCFE_CLOCK_ENABLE; \
-+ type DCFEV_CLOCK_ENABLE; \
-+ type DC_MEM_GLOBAL_PWR_REQ_DIS; \
-+ type BLND_DCP_GRPH_V_UPDATE_LOCK; \
-+ type BLND_SCL_V_UPDATE_LOCK; \
-+ type BLND_DCP_GRPH_SURF_V_UPDATE_LOCK; \
-+ type BLND_BLND_V_UPDATE_LOCK; \
-+ type BLND_V_UPDATE_LOCK_MODE; \
-+ type BLND_FEEDTHROUGH_EN; \
-+ type BLND_ALPHA_MODE; \
-+ type BLND_MODE; \
-+ type BLND_MULTIPLIED_MODE; \
-+ type DP_DTO0_ENABLE; \
-+ type PIXEL_RATE_SOURCE; \
-+ type PHYPLL_PIXEL_RATE_SOURCE; \
-+ type PIXEL_RATE_PLL_SOURCE; \
-+
-+struct dce_hwseq_shift {
-+ HWSEQ_REG_FIED_LIST(uint8_t)
-+};
-+
-+struct dce_hwseq_mask {
-+ HWSEQ_REG_FIED_LIST(uint32_t)
-+};
-+
-+struct dce_hwseq_wa {
-+ bool blnd_crtc_trigger;
-+};
-+
-+struct dce_hwseq {
-+ struct dc_context *ctx;
-+ const struct dce_hwseq_registers *regs;
-+ const struct dce_hwseq_shift *shifts;
-+ const struct dce_hwseq_mask *masks;
-+ struct dce_hwseq_wa wa;
-+};
-+
-+enum blnd_mode {
-+ BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
-+ BLND_MODE_OTHER_PIPE, /* Data from other pipe only */
-+ BLND_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
-+};
-+
-+void dce_enable_fe_clock(struct dce_hwseq *hwss,
-+ unsigned int inst, bool enable);
-+
-+void dce_pipe_control_lock(struct dce_hwseq *hws,
-+ unsigned int blnd_inst,
-+ enum pipe_lock_control control_mask,
-+ bool lock);
-+
-+void dce_set_blender_mode(struct dce_hwseq *hws,
-+ unsigned int blnd_inst, enum blnd_mode mode);
-+
-+void dce_clock_gating_power_up(struct dce_hwseq *hws,
-+ bool enable);
-+
-+void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
-+ struct clock_source *clk_src,
-+ unsigned int tg_inst);
-+#endif /*__DCE_HWSEQ_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
-new file mode 100644
-index 0000000..86e55d0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
-@@ -0,0 +1,2176 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "reg_helper.h"
-+
-+#include "core_types.h"
-+#include "link_encoder.h"
-+#include "dce_link_encoder.h"
-+#include "stream_encoder.h"
-+#include "i2caux_interface.h"
-+#include "dc_bios_types.h"
-+
-+#include "gpio_service_interface.h"
-+
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+#include "dce/dce_11_0_enum.h"
-+
-+#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK
-+#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L
-+#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L
-+#endif
-+
-+#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT
-+#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8
-+#endif
-+
-+#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK
-+#define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L
-+#endif
-+
-+#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT
-+#define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c
-+#endif
-+
-+#define CTX \
-+ enc110->base.ctx
-+
-+#define REG(reg)\
-+ (enc110->link_regs->reg)
-+
-+#define AUX_REG(reg)\
-+ (enc110->aux_regs->reg)
-+
-+#define HPD_REG(reg)\
-+ (enc110->hpd_regs->reg)
-+
-+/* For current ASICs pixel clock - 600MHz */
-+#define MAX_ENCODER_CLK 600000
-+
-+#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 594000
-+
-+#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
-+
-+/* Set the ABM Pipe */
-+#define MCP_ABM_PIPE_SET 0x66
-+/* Set the ABM level */
-+#define MCP_ABM_LEVEL_SET 0x65
-+/* Set backlight level */
-+#define MCP_BL_SET 0x67
-+
-+/* PSR related commands */
-+#define PSR_ENABLE 0x20
-+#define PSR_EXIT 0x21
-+#define PSR_SET 0x23
-+
-+/*TODO: Used for psr wakeup for set backlight level*/
-+static unsigned int psr_crtc_offset;
-+
-+/* registers setting needs to be save and restored used at InitBacklight */
-+static struct dce110_abm_backlight_registers stored_backlight_registers;
-+
-+enum {
-+ DP_MST_UPDATE_MAX_RETRY = 50
-+};
-+
-+#define DIG_REG(reg)\
-+ (reg + enc110->offsets.dig)
-+
-+#define DP_REG(reg)\
-+ (reg + enc110->offsets.dp)
-+
-+static const 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,
-+ .set_dmcu_backlight_level =
-+ dce110_link_encoder_set_dmcu_backlight_level,
-+ .init_dmcu_backlight_settings =
-+ dce110_link_encoder_init_dmcu_backlight_settings,
-+ .set_dmcu_abm_level = dce110_link_encoder_set_dmcu_abm_level,
-+ .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable,
-+ .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr,
-+ .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,
-+ .enable_hpd = dce110_link_encoder_enable_hpd,
-+ .disable_hpd = dce110_link_encoder_disable_hpd,
-+ .destroy = dce110_link_encoder_destroy
-+};
-+
-+
-+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 = enc110->base.ctx->dc_bios;
-+
-+ 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 */
-+
-+ REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);
-+
-+}
-+
-+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 */
-+
-+ REG_UPDATE_4(DP_DPHY_CNTL,
-+ DPHY_ATEST_SEL_LANE0, disable,
-+ DPHY_ATEST_SEL_LANE1, disable,
-+ DPHY_ATEST_SEL_LANE2, disable,
-+ DPHY_ATEST_SEL_LANE3, disable);
-+}
-+
-+static void disable_prbs_mode(
-+ struct dce110_link_encoder *enc110)
-+{
-+ /* This register resides in DP back end block;
-+ * transmitter is used for the offset */
-+
-+ REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);
-+}
-+
-+static void program_pattern_symbols(
-+ struct dce110_link_encoder *enc110,
-+ uint16_t pattern_symbols[8])
-+{
-+ /* This register resides in DP back end block;
-+ * transmitter is used for the offset */
-+
-+ REG_SET_3(DP_DPHY_SYM0, 0,
-+ DPHY_SYM1, pattern_symbols[0],
-+ DPHY_SYM2, pattern_symbols[1],
-+ DPHY_SYM3, pattern_symbols[2]);
-+
-+ /* This register resides in DP back end block;
-+ * transmitter is used for the offset */
-+
-+ REG_SET_3(DP_DPHY_SYM1, 0,
-+ DPHY_SYM4, pattern_symbols[3],
-+ DPHY_SYM5, pattern_symbols[4],
-+ DPHY_SYM6, pattern_symbols[5]);
-+
-+ /* This register resides in DP back end block;
-+ * transmitter is used for the offset */
-+
-+ REG_SET_2(DP_DPHY_SYM2, 0,
-+ DPHY_SYM7, pattern_symbols[6],
-+ DPHY_SYM8, pattern_symbols[7]);
-+}
-+
-+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 */
-+
-+ REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);
-+
-+}
-+
-+void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
-+ struct link_encoder *enc,
-+ uint32_t index)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ /* Write Training Pattern */
-+
-+ REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, 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 */
-+ uint32_t value = 0x0;
-+
-+ enable_phy_bypass_mode(enc110, false);
-+
-+ /* program correct panel mode*/
-+ {
-+ ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
-+ /*DCE 120 does not have this reg*/
-+
-+ REG_WRITE(DP_DPHY_INTERNAL_CTRL, 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 */
-+ {
-+ REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
-+ DPHY_PRBS_SEL, 1,
-+ DPHY_PRBS_EN, 1);
-+ }
-+
-+ /* 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 */
-+
-+ 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 */
-+ {
-+ REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
-+ DPHY_PRBS_SEL, 0,
-+ DPHY_PRBS_EN, 1);
-+ }
-+
-+ /* 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)
-+{
-+
-+ /* 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*/
-+ {
-+ ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
-+
-+ REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0x0);
-+ }
-+
-+ /* 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 = dal_read_reg(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);
-+ */
-+ /* swap every BS with SR */
-+
-+ REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);
-+
-+ /*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 */
-+
-+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
-+
-+ /* 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)
-+{
-+ uint32_t value;
-+
-+ /* program correct panel mode */
-+ {
-+ ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
-+ value = REG_READ(DP_DPHY_INTERNAL_CTRL);
-+
-+ switch (panel_mode) {
-+ case DP_PANEL_MODE_EDP:
-+ value = 0x1;
-+ break;
-+ case DP_PANEL_MODE_SPECIAL:
-+ value = 0x11;
-+ break;
-+ default:
-+ value = 0x0;
-+ break;
-+ }
-+
-+ REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);
-+ }
-+
-+ REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);
-+
-+ /* 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 dc_link_settings *link_settings)
-+{
-+ /* set number of lanes */
-+
-+ REG_SET(DP_CONFIG, 0,
-+ DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
-+
-+ /* setup scrambler */
-+ REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
-+}
-+
-+static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
-+{
-+ bool ret;
-+ uint32_t value;
-+
-+ REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
-+ ret = value;
-+
-+ return ret == 1;
-+}
-+
-+
-+/* TODO duplicate of dc_link.c version */
-+static struct gpio *get_hpd_gpio(const struct link_encoder *enc)
-+{
-+ enum bp_result bp_result;
-+ struct dc_bios *dcb = enc->ctx->dc_bios;
-+ struct graphics_object_hpd_info hpd_info;
-+ struct gpio_pin_info pin_info;
-+
-+ if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK)
-+ 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(
-+ enc->ctx->gpio_service,
-+ pin_info.offset,
-+ pin_info.mask);
-+}
-+
-+/*
-+ * @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 graphics_object_id connector = enc110->base.connector;
-+ struct gpio *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)
-+ /* 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 */
-+ /* TODO what to do with this? */
-+ hpd = get_hpd_gpio(&enc110->base);
-+
-+ if (!hpd) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
-+
-+ /* wait until timeout or panel detected */
-+
-+ do {
-+ uint32_t detected = 0;
-+
-+ dal_gpio_get_value(hpd, &detected);
-+
-+ if (!(detected ^ power_up)) {
-+ edp_hpd_high = true;
-+ break;
-+ }
-+
-+ msleep(HPD_CHECK_INTERVAL);
-+
-+ time_elapsed += HPD_CHECK_INTERVAL;
-+ } while (time_elapsed < timeout);
-+
-+ dal_gpio_close(hpd);
-+
-+ dal_gpio_destroy_irq(&hpd);
-+
-+ if (false == edp_hpd_high) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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 */
-+
-+ dm_logger_write(ctx->logger, LOG_HW_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) {
-+
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%s: Panel Power bp_result: %d\n",
-+ __func__, bp_result);
-+ }
-+ } else {
-+ dm_logger_write(ctx->logger, LOG_HW_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)
-+{
-+ uint32_t value;
-+
-+ REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
-+
-+ return value;
-+}
-+
-+/*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)) {
-+ dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
-+ "%s: panel already powered up. Do nothing.\n",
-+ __func__);
-+ return;
-+ }
-+
-+ if (!enable && !is_panel_powered_on(enc110)) {
-+ dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
-+ "%s: panel already powered down. Do nothing.\n",
-+ __func__);
-+ return;
-+ }
-+
-+ /* Send VBIOS command to control eDP panel backlight */
-+
-+ dm_logger_write(ctx->logger, LOG_HW_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)
-+{
-+ uint32_t value;
-+
-+ REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);
-+ return value;
-+}
-+
-+static void link_encoder_disable(struct dce110_link_encoder *enc110)
-+{
-+ /* reset training pattern */
-+ REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,
-+ DPHY_TRAINING_PATTERN_SEL, 0);
-+
-+ /* reset training complete */
-+ REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);
-+
-+ /* reset panel mode */
-+ ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
-+ REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0);
-+}
-+
-+static void hpd_initialize(
-+ struct dce110_link_encoder *enc110)
-+{
-+ /* Associate HPD with DIG_BE */
-+ enum hpd_source_id hpd_source = enc110->base.hpd_source;
-+
-+ REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);
-+}
-+
-+bool dce110_link_encoder_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 dce110_link_encoder_validate_hdmi_output(
-+ const struct dce110_link_encoder *enc110,
-+ const struct dc_crtc_timing *crtc_timing,
-+ int adjusted_pix_clk_khz)
-+{
-+ enum dc_color_depth max_deep_color =
-+ enc110->base.features.max_hdmi_deep_color;
-+
-+ 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 (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
-+ return false;
-+
-+ if ((adjusted_pix_clk_khz == 0) ||
-+ (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock) ||
-+ (adjusted_pix_clk_khz > enc110->base.features.max_pixel_clock))
-+ return false;
-+
-+ /* DCE11 HW does not support 420 */
-+ if (!enc110->base.features.ycbcr420_supported &&
-+ crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-+ return false;
-+
-+ return true;
-+}
-+
-+bool dce110_link_encoder_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;
-+}
-+
-+bool dce110_link_encoder_validate_dp_output(
-+ const struct dce110_link_encoder *enc110,
-+ const struct dc_crtc_timing *crtc_timing)
-+{
-+ /* 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;
-+}
-+
-+bool dce110_link_encoder_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_hpd_registers *hpd_regs)
-+{
-+ 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.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 =
-+ MAX_ENCODER_CLK;
-+
-+ enc110->base.features.max_deep_color = COLOR_DEPTH_121212;
-+ enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212;
-+
-+ /* 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(as,
-+ 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->hpd_regs = hpd_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;
-+ }
-+
-+ dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX,
-+ "Using channel: %s [%d]\n",
-+ DECODE_CHANNEL_ID(init_data->channel),
-+ init_data->channel);
-+
-+ /* Override features with DCE-specific values */
-+ {
-+ struct bp_encoder_cap_info bp_cap_info = {0};
-+ const struct dc_vbios_funcs *bp_funcs = enc110->base.ctx->dc_bios->funcs;
-+
-+ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info(
-+ enc110->base.ctx->dc_bios, enc110->base.id,
-+ &bp_cap_info))
-+ enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
-+ bp_cap_info.DP_HBR2_CAP;
-+ }
-+ /* test pattern 3 support */
-+ enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true;
-+
-+ enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false;
-+ /*
-+ dal_adapter_service_is_feature_supported(as,
-+ FEATURE_SUPPORT_DP_Y_ONLY);
-+*/
-+ enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = true;
-+ /*
-+ dal_adapter_service_is_feature_supported(as,
-+ FEATURE_SUPPORT_DP_YUV);
-+ */
-+ return true;
-+}
-+
-+bool dce110_link_encoder_validate_output_with_stream(
-+ struct link_encoder *enc,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ bool is_valid;
-+
-+ switch (pipe_ctx->stream->signal) {
-+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
-+ case SIGNAL_TYPE_DVI_DUAL_LINK:
-+ is_valid = dce110_link_encoder_validate_dvi_output(
-+ enc110,
-+ stream->sink->link->public.connector_signal,
-+ pipe_ctx->stream->signal,
-+ &stream->public.timing);
-+ break;
-+ case SIGNAL_TYPE_HDMI_TYPE_A:
-+ is_valid = dce110_link_encoder_validate_hdmi_output(
-+ enc110,
-+ &stream->public.timing,
-+ stream->phy_pix_clk);
-+ break;
-+ case SIGNAL_TYPE_RGB:
-+ is_valid = dce110_link_encoder_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 = dce110_link_encoder_validate_dp_output(
-+ enc110, &stream->public.timing);
-+ break;
-+ case SIGNAL_TYPE_WIRELESS:
-+ is_valid = dce110_link_encoder_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) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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_destroy(struct link_encoder **enc)
-+{
-+ dm_free(TO_DCE110_LINK_ENC(*enc));
-+ *enc = NULL;
-+}
-+
-+void dce110_link_encoder_setup(
-+ struct link_encoder *enc,
-+ enum signal_type signal)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+
-+ switch (signal) {
-+ case SIGNAL_TYPE_EDP:
-+ case SIGNAL_TYPE_DISPLAY_PORT:
-+ /* DP SST */
-+ REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);
-+ break;
-+ case SIGNAL_TYPE_LVDS:
-+ /* LVDS */
-+ REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);
-+ break;
-+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
-+ case SIGNAL_TYPE_DVI_DUAL_LINK:
-+ /* TMDS-DVI */
-+ REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);
-+ break;
-+ case SIGNAL_TYPE_HDMI_TYPE_A:
-+ /* TMDS-HDMI */
-+ REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);
-+ break;
-+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
-+ /* DP MST */
-+ REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);
-+ break;
-+ default:
-+ ASSERT_CRITICAL(false);
-+ /* invalid mode ! */
-+ break;
-+ }
-+
-+}
-+
-+/* 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) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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 dc_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 = ENGINE_ID_UNKNOWN;
-+ 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) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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 dc_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 = ENGINE_ID_UNKNOWN;
-+ 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) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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)) {
-+ /* 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) {
-+ dm_logger_write(ctx->logger, LOG_ERROR,
-+ "%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:
-+ dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);
-+ break;
-+ case DP_TEST_PATTERN_TRAINING_PATTERN2:
-+ dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);
-+ break;
-+ case DP_TEST_PATTERN_TRAINING_PATTERN3:
-+ dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 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);
-+ 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 */
-+
-+ if (table->stream_count >= 1) {
-+ fill_stream_allocation_row_info(
-+ &table->stream_allocations[0],
-+ &src,
-+ &slots);
-+ } else {
-+ src = 0;
-+ slots = 0;
-+ }
-+
-+ REG_UPDATE_2(DP_MSE_SAT0,
-+ DP_MSE_SAT_SRC0, src,
-+ DP_MSE_SAT_SLOT_COUNT0, slots);
-+
-+ if (table->stream_count >= 2) {
-+ fill_stream_allocation_row_info(
-+ &table->stream_allocations[1],
-+ &src,
-+ &slots);
-+ } else {
-+ src = 0;
-+ slots = 0;
-+ }
-+
-+ REG_UPDATE_2(DP_MSE_SAT0,
-+ DP_MSE_SAT_SRC1, src,
-+ DP_MSE_SAT_SLOT_COUNT1, slots);
-+
-+ if (table->stream_count >= 3) {
-+ fill_stream_allocation_row_info(
-+ &table->stream_allocations[2],
-+ &src,
-+ &slots);
-+ } else {
-+ src = 0;
-+ slots = 0;
-+ }
-+
-+ REG_UPDATE_2(DP_MSE_SAT1,
-+ DP_MSE_SAT_SRC2, src,
-+ DP_MSE_SAT_SLOT_COUNT2, slots);
-+
-+ if (table->stream_count >= 4) {
-+ fill_stream_allocation_row_info(
-+ &table->stream_allocations[3],
-+ &src,
-+ &slots);
-+ } else {
-+ src = 0;
-+ slots = 0;
-+ }
-+
-+ REG_UPDATE_2(DP_MSE_SAT1,
-+ DP_MSE_SAT_SRC3, src,
-+ DP_MSE_SAT_SLOT_COUNT3, slots);
-+
-+ /* --- 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 */
-+
-+
-+ /* DP_MSE_SAT_UPDATE:
-+ * 0 - No Action
-+ * 1 - Update SAT with trigger
-+ * 2 - Update SAT without trigger */
-+
-+ REG_UPDATE(DP_MSE_SAT_UPDATE,
-+ DP_MSE_SAT_UPDATE, 1);
-+
-+ /* 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 {
-+ udelay(10);
-+
-+ value0 = REG_READ(DP_MSE_SAT_UPDATE);
-+
-+ REG_GET(DP_MSE_SAT_UPDATE,
-+ DP_MSE_SAT_UPDATE, &value1);
-+
-+ REG_GET(DP_MSE_SAT_UPDATE,
-+ DP_MSE_16_MTP_KEEPOUT, &value2);
-+
-+ /* bit field DP_MSE_SAT_UPDATE is set to 1 already */
-+ if (!value1 && !value2)
-+ break;
-+ ++retries;
-+ } while (retries < DP_MST_UPDATE_MAX_RETRY);
-+}
-+
-+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);
-+
-+ const uint32_t backlight_update_pending_max_retry = 1000;
-+
-+ 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;
-+ uint32_t pwm_period_bitcnt;
-+
-+ backlight_lock = REG_READ(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
-+ */
-+ {
-+ REG_GET(BL_PWM_PERIOD_CNTL,
-+ BL_PWM_PERIOD_BITCNT, &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 =
-+ REG_GET(BL_PWM_PERIOD_CNTL,
-+ BL_PWM_PERIOD, &masked_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;
-+
-+ REG_UPDATE(BL_PWM_CNTL,
-+ BL_ACTIVE_INT_FRAC_CNT, backlight_16bit);
-+
-+ /*
-+ * 3. Program register with updated value
-+ */
-+
-+ /* 3.1 Lock group 2 backlight registers */
-+
-+ REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-+ BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1);
-+
-+ REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-+ BL_PWM_GRP1_REG_LOCK, 1);
-+
-+ /* 3.3 Unlock group 2 backlight registers */
-+ REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-+ BL_PWM_GRP1_REG_LOCK, 0);
-+
-+ /* 5.4.4 Wait for pending bit to be cleared */
-+ for (i = 0; i < backlight_update_pending_max_retry; ++i) {
-+ REG_GET(BL_PWM_GRP1_REG_LOCK,
-+ BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock);
-+ if (!backlight_lock)
-+ break;
-+
-+ udelay(10);
-+ }
-+}
-+
-+void dce110_link_encoder_set_dmcu_backlight_level(
-+ struct link_encoder *enc,
-+ uint32_t level,
-+ uint32_t frame_ramp,
-+ uint32_t controller_id)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-+ unsigned int dmcu_wait_reg_ready_interval = 100;
-+ unsigned int backlight_17bit = level * 0x10101;
-+ unsigned char temp_uchar =
-+ (unsigned char)(((backlight_17bit & 0x80) >> 7) & 1);
-+ unsigned int regValue;
-+ uint32_t rampingBoundary = 0xFFFF;
-+ uint32_t s2;
-+
-+ backlight_17bit = (backlight_17bit >> 8) + temp_uchar;
-+
-+ /* set ramping boundary */
-+ REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
-+
-+ /* setDMCUParam_Pipe */
-+ REG_UPDATE_2(MASTER_COMM_CMD_REG,
-+ MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
-+ MASTER_COMM_CMD_REG_BYTE1, controller_id);
-+
-+ /* notifyDMCUMsg */
-+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-+
-+ /* waitDMCUReadyForCmd */
-+ do {
-+ dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-+ regValue = REG_READ(MASTER_COMM_CNTL_REG);
-+ dmcu_max_retry_on_wait_reg_ready--;
-+ } while
-+ /* expected value is 0, loop while not 0*/
-+ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
-+ dmcu_max_retry_on_wait_reg_ready > 0);
-+
-+ /* setDMCUParam_BL */
-+ REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit);
-+
-+ /* write ramp */
-+ REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
-+
-+ /* setDMCUParam_Cmd */
-+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
-+
-+ /* notifyDMCUMsg */
-+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-+
-+ /* UpdateRequestedBacklightLevel */
-+ s2 = REG_READ(BIOS_SCRATCH_2);
-+
-+ s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
-+ level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
-+ ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
-+ s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
-+
-+ REG_WRITE(BIOS_SCRATCH_2, s2);
-+}
-+
-+void dce110_link_encoder_init_dmcu_backlight_settings(
-+ struct link_encoder *enc)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ uint32_t bl_pwm_cntl;
-+ uint32_t pwmCntl;
-+ uint32_t pwmCntl2;
-+ uint32_t periodCntl;
-+ uint32_t s2;
-+ uint32_t value;
-+
-+ bl_pwm_cntl = REG_READ(BL_PWM_CNTL);
-+
-+ /* It must not be 0, so we have to restore them
-+ * Bios bug w/a - period resets to zero,
-+ * restoring to cache values which is always correct
-+ */
-+ REG_GET(BL_PWM_CNTL,
-+ BL_ACTIVE_INT_FRAC_CNT, &value);
-+ if (value == 0 || bl_pwm_cntl == 1) {
-+ if (stored_backlight_registers.vBL_PWM_CNTL != 0) {
-+ pwmCntl = stored_backlight_registers.vBL_PWM_CNTL;
-+ REG_WRITE(BL_PWM_CNTL, pwmCntl);
-+
-+ pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2;
-+ REG_WRITE(BL_PWM_CNTL2, pwmCntl2);
-+
-+ periodCntl =
-+ stored_backlight_registers.vBL_PWM_PERIOD_CNTL;
-+ REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl);
-+
-+ REG_UPDATE(LVTMA_PWRSEQ_REF_DIV,
-+ BL_PWM_REF_DIV,
-+ stored_backlight_registers.
-+ vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
-+ }
-+ } else {
-+ stored_backlight_registers.vBL_PWM_CNTL =
-+ REG_READ(BL_PWM_CNTL);
-+ stored_backlight_registers.vBL_PWM_CNTL2 =
-+ REG_READ(BL_PWM_CNTL2);
-+ stored_backlight_registers.vBL_PWM_PERIOD_CNTL =
-+ REG_READ(BL_PWM_PERIOD_CNTL);
-+
-+ REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
-+ &stored_backlight_registers.
-+ vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
-+ }
-+
-+ /* Have driver take backlight control
-+ * TakeBacklightControl(true)
-+ */
-+ s2 = REG_READ(BIOS_SCRATCH_2);
-+ s2 |= ATOM_S2_VRI_BRIGHT_ENABLE;
-+ REG_WRITE(BIOS_SCRATCH_2, s2);
-+
-+ /* Enable the backlight output */
-+ REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
-+
-+}
-+
-+void dce110_link_encoder_set_dmcu_abm_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;
-+
-+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-+ unsigned int dmcu_wait_reg_ready_interval = 100;
-+ unsigned int regValue;
-+
-+ /* waitDMCUReadyForCmd */
-+ do {
-+ dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-+ regValue = REG_READ(MASTER_COMM_CNTL_REG);
-+ dmcu_max_retry_on_wait_reg_ready--;
-+ } while
-+ /* expected value is 0, loop while not 0*/
-+ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
-+ dmcu_max_retry_on_wait_reg_ready > 0);
-+
-+ /* setDMCUParam_ABMLevel */
-+ REG_UPDATE_2(MASTER_COMM_CMD_REG,
-+ MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET,
-+ MASTER_COMM_CMD_REG_BYTE2, level);
-+
-+ /* notifyDMCUMsg */
-+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-+}
-+
-+static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+
-+ uint32_t count = 0;
-+ uint32_t psrStateOffset = 0xf0;
-+ uint32_t value;
-+
-+ /* Enable write access to IRAM */
-+ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1);
-+
-+ do {
-+ dm_delay_in_microseconds(ctx, 2);
-+ REG_GET(DCI_MEM_PWR_STATUS,
-+ DMCU_IRAM_MEM_PWR_STATE, &value);
-+ } while
-+ (value != 0 && count++ < 10);
-+
-+ /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */
-+ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset);
-+
-+ /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
-+ *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
-+
-+ /* Disable write access to IRAM after finished using IRAM
-+ * in order to allow dynamic sleep state
-+ */
-+ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0);
-+}
-+
-+void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc,
-+ bool enable)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+
-+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-+ unsigned int dmcu_wait_reg_ready_interval = 100;
-+
-+ unsigned int regValue;
-+
-+ unsigned int retryCount;
-+ uint32_t psr_state = 0;
-+
-+ /* waitDMCUReadyForCmd */
-+ do {
-+ dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-+ regValue = REG_READ(MASTER_COMM_CNTL_REG);
-+ dmcu_max_retry_on_wait_reg_ready--;
-+ } while
-+ /* expected value is 0, loop while not 0*/
-+ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
-+ dmcu_max_retry_on_wait_reg_ready > 0);
-+
-+ /* setDMCUParam_Cmd */
-+ if (enable)
-+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE);
-+ else
-+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT);
-+
-+ /* notifyDMCUMsg */
-+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-+
-+ for (retryCount = 0; retryCount <= 100; retryCount++) {
-+ get_dmcu_psr_state(enc, &psr_state);
-+ if (enable) {
-+ if (psr_state != 0)
-+ break;
-+ } else {
-+ if (psr_state == 0)
-+ break;
-+ }
-+ dm_delay_in_microseconds(ctx, 10);
-+ }
-+}
-+
-+void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc,
-+ struct psr_dmcu_context *psr_context)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+
-+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-+ unsigned int dmcu_wait_reg_ready_interval = 100;
-+ unsigned int regValue;
-+
-+ union dce110_dmcu_psr_config_data_reg1 masterCmdData1;
-+ union dce110_dmcu_psr_config_data_reg2 masterCmdData2;
-+ union dce110_dmcu_psr_config_data_reg3 masterCmdData3;
-+
-+ if (psr_context->psrExitLinkTrainingRequired)
-+ REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1);
-+ else {
-+ REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0);
-+ /*In DCE 11, we are able to pre-program a Force SR register
-+ * to be able to trigger SR symbol after 5 idle patterns
-+ * transmitted. Upon PSR Exit, DMCU can trigger
-+ * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
-+ * DPHY_LOAD_BS_COUNT_START and the internal counter
-+ * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
-+ * replaced by SR symbol once.
-+ */
-+
-+ REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
-+ }
-+
-+ /* Enable static screen interrupts for PSR supported display */
-+ /* Disable the interrupt coming from other displays. */
-+ REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN1_INT_TO_UC_EN, 0,
-+ STATIC_SCREEN2_INT_TO_UC_EN, 0,
-+ STATIC_SCREEN3_INT_TO_UC_EN, 0,
-+ STATIC_SCREEN4_INT_TO_UC_EN, 0);
-+
-+ switch (psr_context->controllerId) {
-+ /* Driver uses case 1 for unconfigured */
-+ case 1:
-+ psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+
-+ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN1_INT_TO_UC_EN, 1);
-+ break;
-+ case 2:
-+ psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+
-+ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN2_INT_TO_UC_EN, 1);
-+ break;
-+ case 3:
-+ psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+
-+ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN3_INT_TO_UC_EN, 1);
-+ break;
-+ case 4:
-+ psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+
-+ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN4_INT_TO_UC_EN, 1);
-+ break;
-+ case 5:
-+ psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+ /* CZ/NL only has 4 CRTC!!
-+ * really valid.
-+ * There is no interrupt enable mask for these instances.
-+ */
-+ break;
-+ case 6:
-+ psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+ /* CZ/NL only has 4 CRTC!!
-+ * These are here because they are defined in HW regspec,
-+ * but not really valid. There is no interrupt enable mask
-+ * for these instances.
-+ */
-+ break;
-+ default:
-+ psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL -
-+ mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
-+
-+ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
-+ STATIC_SCREEN1_INT_TO_UC_EN, 1);
-+ break;
-+ }
-+
-+ REG_UPDATE_2(DP_SEC_CNTL1,
-+ DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline,
-+ DP_SEC_GSP0_PRIORITY, 1);
-+
-+ if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) {
-+ REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1);
-+ }
-+
-+ /* waitDMCUReadyForCmd */
-+ do {
-+ dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-+ regValue = REG_READ(MASTER_COMM_CNTL_REG);
-+ dmcu_max_retry_on_wait_reg_ready--;
-+ } while
-+ /* expected value is 0, loop while not 0*/
-+ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
-+ dmcu_max_retry_on_wait_reg_ready > 0);
-+
-+ /* setDMCUParam_PSRHostConfigData */
-+ masterCmdData1.u32All = 0;
-+ masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames;
-+ masterCmdData1.bits.hyst_lines = psr_context->hyst_lines;
-+ masterCmdData1.bits.rfb_update_auto_en =
-+ psr_context->rfb_update_auto_en;
-+ masterCmdData1.bits.dp_port_num = psr_context->transmitterId;
-+ masterCmdData1.bits.dcp_sel = psr_context->controllerId;
-+ masterCmdData1.bits.phy_type = psr_context->phyType;
-+ masterCmdData1.bits.frame_cap_ind =
-+ psr_context->psrFrameCaptureIndicationReq;
-+ masterCmdData1.bits.aux_chan = psr_context->channel;
-+ masterCmdData1.bits.aux_repeat = psr_context->aux_repeats;
-+ dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1),
-+ masterCmdData1.u32All);
-+
-+ masterCmdData2.u32All = 0;
-+ masterCmdData2.bits.dig_fe = psr_context->engineId;
-+ masterCmdData2.bits.dig_be = psr_context->transmitterId;
-+ masterCmdData2.bits.skip_wait_for_pll_lock =
-+ psr_context->skipPsrWaitForPllLock;
-+ masterCmdData2.bits.frame_delay = psr_context->frame_delay;
-+ masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId;
-+ masterCmdData2.bits.num_of_controllers =
-+ psr_context->numberOfControllers;
-+ dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2),
-+ masterCmdData2.u32All);
-+
-+ masterCmdData3.u32All = 0;
-+ masterCmdData3.bits.psr_level = psr_context->psr_level.u32all;
-+ dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3),
-+ masterCmdData3.u32All);
-+
-+ /* setDMCUParam_Cmd */
-+ REG_UPDATE(MASTER_COMM_CMD_REG,
-+ MASTER_COMM_CMD_REG_BYTE0, PSR_SET);
-+
-+ /* notifyDMCUMsg */
-+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-+}
-+
-+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);
-+ uint32_t field;
-+
-+ if (engine != ENGINE_ID_UNKNOWN) {
-+
-+ REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field);
-+
-+ if (connect)
-+ field |= get_frontend_source(engine);
-+ else
-+ field &= ~get_frontend_source(engine);
-+
-+ REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);
-+ }
-+}
-+
-+void dce110_link_encoder_enable_hpd(struct link_encoder *enc)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+ uint32_t addr = HPD_REG(DC_HPD_CONTROL);
-+ uint32_t hpd_enable = 0;
-+ uint32_t value = dm_read_reg(ctx, addr);
-+
-+ get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN);
-+
-+ if (hpd_enable == 0)
-+ set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN);
-+}
-+
-+void dce110_link_encoder_disable_hpd(struct link_encoder *enc)
-+{
-+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-+ struct dc_context *ctx = enc110->base.ctx;
-+ uint32_t addr = HPD_REG(DC_HPD_CONTROL);
-+ uint32_t value = dm_read_reg(ctx, addr);
-+
-+ set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
-new file mode 100644
-index 0000000..1635b23
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
-@@ -0,0 +1,363 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "link_encoder.h"
-+
-+#define TO_DCE110_LINK_ENC(link_encoder)\
-+ container_of(link_encoder, struct dce110_link_encoder, base)
-+
-+#define AUX_REG_LIST(id)\
-+ SRI(AUX_CONTROL, DP_AUX, id), \
-+ SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id)
-+
-+#define HPD_REG_LIST(id)\
-+ SRI(DC_HPD_CONTROL, HPD, id)
-+
-+#define LE_COMMON_REG_LIST_BASE(id) \
-+ SR(BL_PWM_CNTL), \
-+ SR(BL_PWM_GRP1_REG_LOCK), \
-+ SR(BL_PWM_PERIOD_CNTL), \
-+ SR(LVTMA_PWRSEQ_CNTL), \
-+ SR(LVTMA_PWRSEQ_STATE), \
-+ SR(BL_PWM_CNTL2), \
-+ SR(LVTMA_PWRSEQ_REF_DIV), \
-+ SR(MASTER_COMM_DATA_REG1), \
-+ SR(MASTER_COMM_DATA_REG2), \
-+ SR(MASTER_COMM_DATA_REG3), \
-+ SR(MASTER_COMM_CMD_REG), \
-+ SR(MASTER_COMM_CNTL_REG), \
-+ SR(DMCU_RAM_ACCESS_CTRL), \
-+ SR(DMCU_IRAM_RD_CTRL), \
-+ SR(DMCU_IRAM_RD_DATA), \
-+ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
-+ SR(SMU_INTERRUPT_CONTROL), \
-+ SRI(DIG_BE_CNTL, DIG, id), \
-+ SRI(DIG_BE_EN_CNTL, DIG, id), \
-+ SRI(DP_CONFIG, DP, id), \
-+ SRI(DP_DPHY_CNTL, DP, id), \
-+ SRI(DP_DPHY_PRBS_CNTL, DP, id), \
-+ SRI(DP_DPHY_SCRAM_CNTL, DP, id),\
-+ SRI(DP_DPHY_SYM0, DP, id), \
-+ SRI(DP_DPHY_SYM1, DP, id), \
-+ SRI(DP_DPHY_SYM2, DP, id), \
-+ SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \
-+ SRI(DP_LINK_CNTL, DP, id), \
-+ SRI(DP_LINK_FRAMING_CNTL, DP, id), \
-+ SRI(DP_MSE_SAT0, DP, id), \
-+ SRI(DP_MSE_SAT1, DP, id), \
-+ SRI(DP_MSE_SAT2, DP, id), \
-+ SRI(DP_MSE_SAT_UPDATE, DP, id), \
-+ SRI(DP_SEC_CNTL, DP, id), \
-+ SRI(DP_VID_STREAM_CNTL, DP, id), \
-+ SRI(DP_DPHY_FAST_TRAINING, DP, id), \
-+ SRI(DP_SEC_CNTL1, DP, id)
-+
-+ #define LE_COMMON_REG_LIST(id)\
-+ LE_COMMON_REG_LIST_BASE(id), \
-+ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
-+ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
-+ SR(BIOS_SCRATCH_2), \
-+ SR(BL1_PWM_USER_LEVEL), \
-+ SR(DCI_MEM_PWR_STATUS)
-+
-+ #define LE_DCE110_REG_LIST(id)\
-+ LE_COMMON_REG_LIST_BASE(id), \
-+ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
-+ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
-+ SR(BIOS_SCRATCH_2), \
-+ SR(BL1_PWM_USER_LEVEL), \
-+ SR(DCI_MEM_PWR_STATUS)
-+
-+ #define LE_DCE80_REG_LIST(id)\
-+ SR(BIOS_SCRATCH_2), \
-+ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
-+ SR(BL1_PWM_USER_LEVEL), \
-+ LE_COMMON_REG_LIST_BASE(id)
-+
-+
-+struct dce110_link_enc_aux_registers {
-+ uint32_t AUX_CONTROL;
-+ uint32_t AUX_DPHY_RX_CONTROL0;
-+};
-+
-+struct dce110_link_enc_hpd_registers {
-+ uint32_t DC_HPD_CONTROL;
-+};
-+
-+struct dce110_link_enc_registers {
-+ /* 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;
-+ uint32_t BL_PWM_CNTL2;
-+ uint32_t LVTMA_PWRSEQ_REF_DIV;
-+
-+ /* DMCU registers */
-+ uint32_t BL1_PWM_USER_LEVEL;
-+ uint32_t ABM0_BL1_PWM_USER_LEVEL;
-+ uint32_t MASTER_COMM_DATA_REG1;
-+ uint32_t MASTER_COMM_DATA_REG2;
-+ uint32_t MASTER_COMM_DATA_REG3;
-+ uint32_t MASTER_COMM_CMD_REG;
-+ uint32_t MASTER_COMM_CNTL_REG;
-+ uint32_t BIOS_SCRATCH_2;
-+ uint32_t DMCU_RAM_ACCESS_CTRL;
-+ uint32_t DCI_MEM_PWR_STATUS;
-+ uint32_t DMU_MEM_PWR_CNTL;
-+ uint32_t DMCU_IRAM_RD_CTRL;
-+ uint32_t DMCU_IRAM_RD_DATA;
-+ uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
-+ uint32_t SMU_INTERRUPT_CONTROL;
-+
-+
-+ /* Common DP 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_SCRAM_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;
-+ uint32_t DP_DPHY_FAST_TRAINING;
-+ uint32_t DP_DPHY_BS_SR_SWAP_CNTL;
-+ uint32_t DP_SEC_CNTL1;
-+};
-+
-+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_hpd_registers *hpd_regs;
-+};
-+
-+/*******************************************************************
-+* MASTER_COMM_DATA_REG1 Bit position Data
-+* 7:0 hyst_frames[7:0]
-+* 14:8 hyst_lines[6:0]
-+* 15 RFB_UPDATE_AUTO_EN
-+* 18:16 phy_num[2:0]
-+* 21:19 dcp_sel[2:0]
-+* 22 phy_type
-+* 23 frame_cap_ind
-+* 26:24 aux_chan[2:0]
-+* 30:27 aux_repeat[3:0]
-+* 31:31 reserved[31:31]
-+*******************************************************************/
-+union dce110_dmcu_psr_config_data_reg1 {
-+ struct {
-+ unsigned int timehyst_frames:8; /*[7:0]*/
-+ unsigned int hyst_lines:7; /*[14:8]*/
-+ unsigned int rfb_update_auto_en:1; /*[15:15]*/
-+ unsigned int dp_port_num:3; /*[18:16]*/
-+ unsigned int dcp_sel:3; /*[21:19]*/
-+ unsigned int phy_type:1; /*[22:22]*/
-+ unsigned int frame_cap_ind:1; /*[23:23]*/
-+ unsigned int aux_chan:3; /*[26:24]*/
-+ unsigned int aux_repeat:4; /*[30:27]*/
-+ unsigned int reserved:1; /*[31:31]*/
-+ } bits;
-+ unsigned int u32All;
-+};
-+
-+/*******************************************************************
-+* MASTER_COMM_DATA_REG2
-+*******************************************************************/
-+union dce110_dmcu_psr_config_data_reg2 {
-+ struct {
-+ unsigned int dig_fe:3; /*[2:0]*/
-+ unsigned int dig_be:3; /*[5:3]*/
-+ unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/
-+ unsigned int reserved:9; /*[15:7]*/
-+ unsigned int frame_delay:8; /*[23:16]*/
-+ unsigned int smu_phy_id:4; /*[27:24]*/
-+ unsigned int num_of_controllers:4; /*[31:28]*/
-+ } bits;
-+ unsigned int u32All;
-+};
-+
-+/*******************************************************************
-+* MASTER_COMM_DATA_REG3
-+*******************************************************************/
-+union dce110_dmcu_psr_config_data_reg3 {
-+ struct {
-+ unsigned int psr_level:16; /*[15:0]*/
-+ unsigned int link_rate:4; /*[19:16]*/
-+ unsigned int reserved:12; /*[31:20]*/
-+ } bits;
-+ unsigned int u32All;
-+};
-+
-+struct dce110_abm_backlight_registers {
-+ unsigned int vBL_PWM_CNTL;
-+ unsigned int vBL_PWM_CNTL2;
-+ unsigned int vBL_PWM_PERIOD_CNTL;
-+ unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
-+};
-+
-+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_hpd_registers *hpd_regs);
-+
-+bool dce110_link_encoder_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);
-+
-+bool dce110_link_encoder_validate_rgb_output(
-+ const struct dce110_link_encoder *enc110,
-+ const struct dc_crtc_timing *crtc_timing);
-+
-+bool dce110_link_encoder_validate_dp_output(
-+ const struct dce110_link_encoder *enc110,
-+ const struct dc_crtc_timing *crtc_timing);
-+
-+bool dce110_link_encoder_validate_wireless_output(
-+ const struct dce110_link_encoder *enc110,
-+ const struct dc_crtc_timing *crtc_timing);
-+
-+bool dce110_link_encoder_validate_output_with_stream(
-+ struct link_encoder *enc,
-+ struct pipe_ctx *pipe_ctx);
-+
-+/****************** HW programming ************************/
-+
-+/* initialize HW */ /* why do we initialze aux in here? */
-+void dce110_link_encoder_hw_init(struct link_encoder *enc);
-+
-+void dce110_link_encoder_destroy(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 dc_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 dc_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_set_dmcu_backlight_level(
-+ struct link_encoder *enc,
-+ uint32_t level,
-+ uint32_t frame_ramp,
-+ uint32_t controller_id);
-+
-+void dce110_link_encoder_init_dmcu_backlight_settings(
-+ struct link_encoder *enc);
-+
-+void dce110_link_encoder_set_dmcu_abm_level(
-+ struct link_encoder *enc,
-+ uint32_t level);
-+
-+void dce110_link_encoder_set_dmcu_psr_enable(
-+ struct link_encoder *enc, bool enable);
-+
-+void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc,
-+ struct psr_dmcu_context *psr_context);
-+
-+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);
-+
-+void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
-+ struct link_encoder *enc,
-+ uint32_t index);
-+
-+void dce110_link_encoder_enable_hpd(struct link_encoder *enc);
-+
-+void dce110_link_encoder_disable_hpd(struct link_encoder *enc);
-+
-+#endif /* __DC_LINK_ENCODER__DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
-new file mode 100644
-index 0000000..654731c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
-@@ -0,0 +1,384 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "mem_input.h"
-+#include "reg_helper.h"
-+
-+#define CTX \
-+ mi->ctx
-+#define REG(reg)\
-+ mi->regs->reg
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ mi->shifts->field_name, mi->masks->field_name
-+
-+
-+static void program_urgency_watermark(struct mem_input *mi,
-+ uint32_t wm_select,
-+ uint32_t urgency_low_wm,
-+ uint32_t urgency_high_wm)
-+{
-+ REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
-+ URGENCY_WATERMARK_MASK, wm_select);
-+
-+ REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
-+ URGENCY_LOW_WATERMARK, urgency_low_wm,
-+ URGENCY_HIGH_WATERMARK, urgency_high_wm);
-+}
-+
-+static void program_nbp_watermark(struct mem_input *mi,
-+ uint32_t wm_select,
-+ uint32_t nbp_wm)
-+{
-+ if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
-+ REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
-+
-+ REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_ENABLE, 1,
-+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
-+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
-+
-+ REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
-+ }
-+}
-+
-+static void program_stutter_watermark(struct mem_input *mi,
-+ uint32_t wm_select,
-+ uint32_t stutter_mark)
-+{
-+ REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
-+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
-+
-+ REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
-+ STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
-+}
-+
-+void dce_mem_input_program_display_marks(struct mem_input *mi,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns)
-+{
-+ uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
-+
-+ program_urgency_watermark(mi, 0, /* set a */
-+ urgent.a_mark, total_dest_line_time_ns);
-+ program_urgency_watermark(mi, 1, /* set b */
-+ urgent.b_mark, total_dest_line_time_ns);
-+ program_urgency_watermark(mi, 2, /* set c */
-+ urgent.c_mark, total_dest_line_time_ns);
-+ program_urgency_watermark(mi, 3, /* set d */
-+ urgent.d_mark, total_dest_line_time_ns);
-+
-+ REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
-+ STUTTER_ENABLE, stutter_en,
-+ STUTTER_IGNORE_FBC, 1);
-+ program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */
-+ program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */
-+ program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */
-+ program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */
-+
-+ program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */
-+ program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */
-+ program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */
-+ program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */
-+}
-+
-+static void program_tiling(struct mem_input *mi,
-+ const union dc_tiling_info *info)
-+{
-+ if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
-+ REG_UPDATE_9(GRPH_CONTROL,
-+ GRPH_NUM_BANKS, info->gfx8.num_banks,
-+ GRPH_BANK_WIDTH, info->gfx8.bank_width,
-+ GRPH_BANK_HEIGHT, info->gfx8.bank_height,
-+ GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
-+ GRPH_TILE_SPLIT, info->gfx8.tile_split,
-+ GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
-+ GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
-+ GRPH_ARRAY_MODE, info->gfx8.array_mode,
-+ GRPH_COLOR_EXPANSION_MODE, 1);
-+ /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
-+ /*
-+ GRPH_Z, 0);
-+ */
-+ }
-+}
-+
-+
-+static void program_size_and_rotation(
-+ struct mem_input *mi,
-+ enum dc_rotation_angle rotation,
-+ const union plane_size *plane_size)
-+{
-+ const struct rect *in_rect = &plane_size->grph.surface_size;
-+ struct rect hw_rect = plane_size->grph.surface_size;
-+ const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
-+ [ROTATION_ANGLE_0] = 0,
-+ [ROTATION_ANGLE_90] = 1,
-+ [ROTATION_ANGLE_180] = 2,
-+ [ROTATION_ANGLE_270] = 3,
-+ };
-+
-+ if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
-+ hw_rect.x = in_rect->y;
-+ hw_rect.y = in_rect->x;
-+
-+ hw_rect.height = in_rect->width;
-+ hw_rect.width = in_rect->height;
-+ }
-+
-+ REG_SET(GRPH_X_START, 0,
-+ GRPH_X_START, hw_rect.x);
-+
-+ REG_SET(GRPH_Y_START, 0,
-+ GRPH_Y_START, hw_rect.y);
-+
-+ REG_SET(GRPH_X_END, 0,
-+ GRPH_X_END, hw_rect.width);
-+
-+ REG_SET(GRPH_Y_END, 0,
-+ GRPH_Y_END, hw_rect.height);
-+
-+ REG_SET(GRPH_PITCH, 0,
-+ GRPH_PITCH, plane_size->grph.surface_pitch);
-+
-+ REG_SET(HW_ROTATION, 0,
-+ GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
-+}
-+
-+static void program_grph_pixel_format(
-+ struct mem_input *mi,
-+ enum surface_pixel_format format)
-+{
-+ uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
-+ uint32_t grph_depth, grph_format;
-+ uint32_t sign = 0, floating = 0;
-+
-+ if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 ||
-+ /*todo: doesn't look like we handle BGRA here,
-+ * should problem swap endian*/
-+ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
-+ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
-+ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
-+ /* ABGR formats */
-+ red_xbar = 2;
-+ blue_xbar = 2;
-+ }
-+
-+ REG_SET_2(GRPH_SWAP_CNTL, 0,
-+ GRPH_RED_CROSSBAR, red_xbar,
-+ GRPH_BLUE_CROSSBAR, blue_xbar);
-+
-+ switch (format) {
-+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
-+ grph_depth = 0;
-+ grph_format = 0;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
-+ grph_depth = 1;
-+ grph_format = 0;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
-+ grph_depth = 1;
-+ grph_format = 1;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
-+ grph_depth = 2;
-+ grph_format = 0;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
-+ grph_depth = 2;
-+ grph_format = 1;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
-+ sign = 1;
-+ floating = 1;
-+ /* no break */
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
-+ grph_depth = 3;
-+ grph_format = 0;
-+ break;
-+ default:
-+ DC_ERR("unsupported grph pixel format");
-+ break;
-+ }
-+
-+ REG_UPDATE_2(GRPH_CONTROL,
-+ GRPH_DEPTH, grph_depth,
-+ GRPH_FORMAT, grph_format);
-+
-+ REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
-+ GRPH_PRESCALE_SELECT, floating,
-+ GRPH_PRESCALE_R_SIGN, sign,
-+ GRPH_PRESCALE_G_SIGN, sign,
-+ GRPH_PRESCALE_B_SIGN, sign);
-+}
-+
-+bool dce_mem_input_program_surface_config(struct mem_input *mi,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation,
-+ struct dc_plane_dcc_param *dcc,
-+ bool horizontal_mirror)
-+{
-+ REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
-+
-+ program_tiling(mi, tiling_info);
-+ program_size_and_rotation(mi, rotation, plane_size);
-+
-+ if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
-+ format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ program_grph_pixel_format(mi, format);
-+
-+ return true;
-+}
-+
-+static uint32_t get_dmif_switch_time_us(
-+ uint32_t h_total,
-+ uint32_t v_total,
-+ uint32_t pix_clk_khz)
-+{
-+ 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 (!h_total || v_total || !pix_clk_khz)
-+ return single_frame_time_multiplier * min_single_frame_time_us;
-+
-+ /*TODO: should we use pixel format normalized pixel clock here?*/
-+ pixels_per_second = pix_clk_khz * 1000;
-+ pixels_per_frame = h_total * 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 dce_mem_input_allocate_dmif(struct mem_input *mi,
-+ uint32_t h_total,
-+ uint32_t v_total,
-+ uint32_t pix_clk_khz,
-+ uint32_t total_stream_num)
-+{
-+ const uint32_t retry_delay = 10;
-+ uint32_t retry_count = get_dmif_switch_time_us(
-+ h_total,
-+ v_total,
-+ pix_clk_khz) / retry_delay;
-+
-+ uint32_t pix_dur;
-+ uint32_t buffers_allocated;
-+ uint32_t dmif_buffer_control;
-+
-+ dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
-+ DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
-+
-+ if (buffers_allocated == 2)
-+ return;
-+
-+ REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
-+ DMIF_BUFFERS_ALLOCATED, 2);
-+
-+ REG_WAIT(DMIF_BUFFER_CONTROL,
-+ DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
-+ retry_delay, retry_count);
-+
-+ if (pix_clk_khz != 0) {
-+ pix_dur = 1000000000ULL / pix_clk_khz;
-+
-+ REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
-+ PIXEL_DURATION, pix_dur);
-+ }
-+
-+ if (mi->wa.single_head_rdreq_dmif_limit) {
-+ uint32_t eanble = (total_stream_num > 1) ? 0 :
-+ mi->wa.single_head_rdreq_dmif_limit;
-+
-+ REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
-+ ENABLE, eanble);
-+ }
-+}
-+
-+void dce_mem_input_free_dmif(struct mem_input *mi,
-+ uint32_t total_stream_num)
-+{
-+ uint32_t buffers_allocated;
-+ uint32_t dmif_buffer_control;
-+
-+ dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
-+ DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
-+
-+ if (buffers_allocated == 0)
-+ return;
-+
-+ REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
-+ DMIF_BUFFERS_ALLOCATED, 0);
-+
-+ REG_WAIT(DMIF_BUFFER_CONTROL,
-+ DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
-+ 10, 0xBB8);
-+
-+ if (mi->wa.single_head_rdreq_dmif_limit) {
-+ uint32_t eanble = (total_stream_num > 1) ? 0 :
-+ mi->wa.single_head_rdreq_dmif_limit;
-+
-+ REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
-+ ENABLE, eanble);
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h
-new file mode 100644
-index 0000000..d5930a9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h
-@@ -0,0 +1,217 @@
-+/*
-+ * 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 __DCE_MEM_INPUT_H__
-+#define __DCE_MEM_INPUT_H__
-+
-+#define MI_DCE_BASE_REG_LIST(id)\
-+ SRI(GRPH_ENABLE, DCP, id),\
-+ SRI(GRPH_CONTROL, DCP, id),\
-+ SRI(GRPH_X_START, DCP, id),\
-+ SRI(GRPH_Y_START, DCP, id),\
-+ SRI(GRPH_X_END, DCP, id),\
-+ SRI(GRPH_Y_END, DCP, id),\
-+ SRI(GRPH_PITCH, DCP, id),\
-+ SRI(HW_ROTATION, DCP, id),\
-+ SRI(GRPH_SWAP_CNTL, DCP, id),\
-+ SRI(PRESCALE_GRPH_CONTROL, DCP, id),\
-+ SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\
-+ SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\
-+ SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\
-+ SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\
-+ SRI(DMIF_BUFFER_CONTROL, PIPE, id)
-+
-+#define MI_REG_LIST(id)\
-+ MI_DCE_BASE_REG_LIST(id),\
-+ SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id)
-+
-+struct dce_mem_input_registers {
-+ /* DCP */
-+ uint32_t GRPH_ENABLE;
-+ uint32_t GRPH_CONTROL;
-+ uint32_t GRPH_X_START;
-+ uint32_t GRPH_Y_START;
-+ uint32_t GRPH_X_END;
-+ uint32_t GRPH_Y_END;
-+ uint32_t GRPH_PITCH;
-+ uint32_t HW_ROTATION;
-+ uint32_t GRPH_SWAP_CNTL;
-+ uint32_t PRESCALE_GRPH_CONTROL;
-+ /* DMIF_PG */
-+ uint32_t DPG_PIPE_ARBITRATION_CONTROL1;
-+ uint32_t DPG_WATERMARK_MASK_CONTROL;
-+ uint32_t DPG_PIPE_URGENCY_CONTROL;
-+ uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
-+ uint32_t DPG_PIPE_LOW_POWER_CONTROL;
-+ uint32_t DPG_PIPE_STUTTER_CONTROL;
-+ uint32_t DPG_PIPE_STUTTER_CONTROL2;
-+ /* DCI */
-+ uint32_t DMIF_BUFFER_CONTROL;
-+ /* MC_HUB */
-+ uint32_t MC_HUB_RDREQ_DMIF_LIMIT;
-+};
-+
-+/* Set_Filed_for_Block */
-+#define SFB(blk_name, reg_name, field_name, post_fix)\
-+ .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix
-+
-+#define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\
-+ SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_MICRO_TILE_MODE, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh)
-+
-+#define MI_DCP_MASK_SH_LIST(mask_sh, blk)\
-+ SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\
-+ SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
-+ SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\
-+ SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\
-+ SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\
-+ SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\
-+ SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\
-+ SFB(blk, HW_ROTATION, GRPH_ROTATION_ANGLE, mask_sh),\
-+ SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\
-+ SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\
-+ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\
-+ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\
-+ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\
-+ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh)
-+
-+#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\
-+ SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\
-+ SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\
-+ SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\
-+ SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\
-+ SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\
-+ SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\
-+ SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\
-+ SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\
-+ SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh)
-+
-+#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\
-+ SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\
-+ SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\
-+ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\
-+ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\
-+ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\
-+ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh)
-+
-+#define MI_DCE_MASK_SH_LIST(mask_sh)\
-+ MI_DCP_MASK_SH_LIST(mask_sh,),\
-+ MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\
-+ MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\
-+ MI_GFX8_TILE_MASK_SH_LIST(mask_sh,)
-+
-+#define MI_REG_FIELD_LIST(type) \
-+ type GRPH_ENABLE; \
-+ type GRPH_X_START; \
-+ type GRPH_Y_START; \
-+ type GRPH_X_END; \
-+ type GRPH_Y_END; \
-+ type GRPH_PITCH; \
-+ type GRPH_ROTATION_ANGLE; \
-+ type GRPH_RED_CROSSBAR; \
-+ type GRPH_BLUE_CROSSBAR; \
-+ type GRPH_PRESCALE_SELECT; \
-+ type GRPH_PRESCALE_R_SIGN; \
-+ type GRPH_PRESCALE_G_SIGN; \
-+ type GRPH_PRESCALE_B_SIGN; \
-+ type GRPH_DEPTH; \
-+ type GRPH_FORMAT; \
-+ type GRPH_NUM_BANKS; \
-+ type GRPH_BANK_WIDTH;\
-+ type GRPH_BANK_HEIGHT;\
-+ type GRPH_MACRO_TILE_ASPECT;\
-+ type GRPH_TILE_SPLIT;\
-+ type GRPH_MICRO_TILE_MODE;\
-+ type GRPH_PIPE_CONFIG;\
-+ type GRPH_ARRAY_MODE;\
-+ type GRPH_COLOR_EXPANSION_MODE;\
-+ type GRPH_SW_MODE; \
-+ type GRPH_NUM_SHADER_ENGINES; \
-+ type GRPH_NUM_PIPES; \
-+ type PIXEL_DURATION; \
-+ type URGENCY_WATERMARK_MASK; \
-+ type PSTATE_CHANGE_WATERMARK_MASK; \
-+ type NB_PSTATE_CHANGE_WATERMARK_MASK; \
-+ type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \
-+ type URGENCY_LOW_WATERMARK; \
-+ type URGENCY_HIGH_WATERMARK; \
-+ type NB_PSTATE_CHANGE_ENABLE; \
-+ type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \
-+ type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
-+ type NB_PSTATE_CHANGE_WATERMARK; \
-+ type PSTATE_CHANGE_ENABLE; \
-+ type PSTATE_CHANGE_URGENT_DURING_REQUEST; \
-+ type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
-+ type PSTATE_CHANGE_WATERMARK; \
-+ type STUTTER_ENABLE; \
-+ type STUTTER_IGNORE_FBC; \
-+ type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \
-+ type DMIF_BUFFERS_ALLOCATED; \
-+ type DMIF_BUFFERS_ALLOCATION_COMPLETED; \
-+ type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\
-+
-+struct dce_mem_input_shift {
-+ MI_REG_FIELD_LIST(uint8_t)
-+};
-+
-+struct dce_mem_input_mask {
-+ MI_REG_FIELD_LIST(uint32_t)
-+};
-+
-+struct dce_mem_input_wa {
-+ uint8_t single_head_rdreq_dmif_limit;
-+};
-+
-+struct mem_input;
-+bool dce_mem_input_program_surface_config(struct mem_input *mi,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation,
-+ struct dc_plane_dcc_param *dcc,
-+ bool horizontal_mirror);
-+
-+void dce_mem_input_allocate_dmif(struct mem_input *mi,
-+ uint32_t h_total,
-+ uint32_t v_total,
-+ uint32_t pix_clk_khz,
-+ uint32_t total_stream_num);
-+
-+void dce_mem_input_free_dmif(struct mem_input *mi,
-+ uint32_t total_stream_num);
-+
-+void dce_mem_input_program_display_marks(struct mem_input *mi,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns);
-+
-+#endif /*__DCE_MEM_INPUT_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c
-new file mode 100644
-index 0000000..3aab867
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c
-@@ -0,0 +1,501 @@
-+/*
-+ * 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 "transform.h"
-+
-+const uint16_t filter_2tap_16p[18] = {
-+ 4096, 0,
-+ 3840, 256,
-+ 3584, 512,
-+ 3328, 768,
-+ 3072, 1024,
-+ 2816, 1280,
-+ 2560, 1536,
-+ 2304, 1792,
-+ 2048, 2048
-+};
-+
-+const uint16_t filter_3tap_16p_upscale[27] = {
-+ 2048, 2048, 0,
-+ 1708, 2424, 16348,
-+ 1372, 2796, 16308,
-+ 1056, 3148, 16272,
-+ 768, 3464, 16244,
-+ 512, 3728, 16236,
-+ 296, 3928, 16252,
-+ 124, 4052, 16296,
-+ 0, 4096, 0
-+};
-+
-+const uint16_t filter_3tap_16p_117[27] = {
-+ 2048, 2048, 0,
-+ 1824, 2276, 16376,
-+ 1600, 2496, 16380,
-+ 1376, 2700, 16,
-+ 1156, 2880, 52,
-+ 948, 3032, 108,
-+ 756, 3144, 192,
-+ 580, 3212, 296,
-+ 428, 3236, 428
-+};
-+
-+const uint16_t filter_3tap_16p_150[27] = {
-+ 2048, 2048, 0,
-+ 1872, 2184, 36,
-+ 1692, 2308, 88,
-+ 1516, 2420, 156,
-+ 1340, 2516, 236,
-+ 1168, 2592, 328,
-+ 1004, 2648, 440,
-+ 844, 2684, 560,
-+ 696, 2696, 696
-+};
-+
-+const uint16_t filter_3tap_16p_183[27] = {
-+ 2048, 2048, 0,
-+ 1892, 2104, 92,
-+ 1744, 2152, 196,
-+ 1592, 2196, 300,
-+ 1448, 2232, 412,
-+ 1304, 2256, 528,
-+ 1168, 2276, 648,
-+ 1032, 2288, 772,
-+ 900, 2292, 900
-+};
-+
-+const uint16_t filter_4tap_16p_upscale[36] = {
-+ 0, 4096, 0, 0,
-+ 16240, 4056, 180, 16380,
-+ 16136, 3952, 404, 16364,
-+ 16072, 3780, 664, 16344,
-+ 16040, 3556, 952, 16312,
-+ 16036, 3284, 1268, 16272,
-+ 16052, 2980, 1604, 16224,
-+ 16084, 2648, 1952, 16176,
-+ 16128, 2304, 2304, 16128
-+};
-+
-+const uint16_t filter_4tap_16p_117[36] = {
-+ 428, 3236, 428, 0,
-+ 276, 3232, 604, 16364,
-+ 148, 3184, 800, 16340,
-+ 44, 3104, 1016, 16312,
-+ 16344, 2984, 1244, 16284,
-+ 16284, 2832, 1488, 16256,
-+ 16244, 2648, 1732, 16236,
-+ 16220, 2440, 1976, 16220,
-+ 16212, 2216, 2216, 16212
-+};
-+
-+const uint16_t filter_4tap_16p_150[36] = {
-+ 696, 2700, 696, 0,
-+ 560, 2700, 848, 16364,
-+ 436, 2676, 1008, 16348,
-+ 328, 2628, 1180, 16336,
-+ 232, 2556, 1356, 16328,
-+ 152, 2460, 1536, 16328,
-+ 84, 2344, 1716, 16332,
-+ 28, 2208, 1888, 16348,
-+ 16376, 2052, 2052, 16376
-+};
-+
-+const uint16_t filter_4tap_16p_183[36] = {
-+ 940, 2208, 940, 0,
-+ 832, 2200, 1052, 4,
-+ 728, 2180, 1164, 16,
-+ 628, 2148, 1280, 36,
-+ 536, 2100, 1392, 60,
-+ 448, 2044, 1504, 92,
-+ 368, 1976, 1612, 132,
-+ 296, 1900, 1716, 176,
-+ 232, 1812, 1812, 232
-+};
-+
-+const uint16_t filter_2tap_64p[66] = {
-+ 4096, 0,
-+ 4032, 64,
-+ 3968, 128,
-+ 3904, 192,
-+ 3840, 256,
-+ 3776, 320,
-+ 3712, 384,
-+ 3648, 448,
-+ 3584, 512,
-+ 3520, 576,
-+ 3456, 640,
-+ 3392, 704,
-+ 3328, 768,
-+ 3264, 832,
-+ 3200, 896,
-+ 3136, 960,
-+ 3072, 1024,
-+ 3008, 1088,
-+ 2944, 1152,
-+ 2880, 1216,
-+ 2816, 1280,
-+ 2752, 1344,
-+ 2688, 1408,
-+ 2624, 1472,
-+ 2560, 1536,
-+ 2496, 1600,
-+ 2432, 1664,
-+ 2368, 1728,
-+ 2304, 1792,
-+ 2240, 1856,
-+ 2176, 1920,
-+ 2112, 1984,
-+ 2048, 2048 };
-+
-+const uint16_t filter_3tap_64p_upscale[99] = {
-+ 2048, 2048, 0,
-+ 1960, 2140, 16376,
-+ 1876, 2236, 16364,
-+ 1792, 2328, 16356,
-+ 1708, 2424, 16348,
-+ 1620, 2516, 16336,
-+ 1540, 2612, 16328,
-+ 1456, 2704, 16316,
-+ 1372, 2796, 16308,
-+ 1292, 2884, 16296,
-+ 1212, 2976, 16288,
-+ 1136, 3060, 16280,
-+ 1056, 3148, 16272,
-+ 984, 3228, 16264,
-+ 908, 3312, 16256,
-+ 836, 3388, 16248,
-+ 768, 3464, 16244,
-+ 700, 3536, 16240,
-+ 636, 3604, 16236,
-+ 572, 3668, 16236,
-+ 512, 3728, 16236,
-+ 456, 3784, 16236,
-+ 400, 3836, 16240,
-+ 348, 3884, 16244,
-+ 296, 3928, 16252,
-+ 252, 3964, 16260,
-+ 204, 4000, 16268,
-+ 164, 4028, 16284,
-+ 124, 4052, 16296,
-+ 88, 4072, 16316,
-+ 56, 4084, 16336,
-+ 24, 4092, 16356,
-+ 0, 4096, 0
-+};
-+
-+const uint16_t filter_3tap_64p_117[99] = {
-+ 2048, 2048, 0,
-+ 1992, 2104, 16380,
-+ 1936, 2160, 16380,
-+ 1880, 2220, 16376,
-+ 1824, 2276, 16376,
-+ 1768, 2332, 16376,
-+ 1712, 2388, 16376,
-+ 1656, 2444, 16376,
-+ 1600, 2496, 16380,
-+ 1544, 2548, 0,
-+ 1488, 2600, 4,
-+ 1432, 2652, 8,
-+ 1376, 2700, 16,
-+ 1320, 2748, 20,
-+ 1264, 2796, 32,
-+ 1212, 2840, 40,
-+ 1156, 2880, 52,
-+ 1104, 2920, 64,
-+ 1052, 2960, 80,
-+ 1000, 2996, 92,
-+ 948, 3032, 108,
-+ 900, 3060, 128,
-+ 852, 3092, 148,
-+ 804, 3120, 168,
-+ 756, 3144, 192,
-+ 712, 3164, 216,
-+ 668, 3184, 240,
-+ 624, 3200, 268,
-+ 580, 3212, 296,
-+ 540, 3220, 328,
-+ 500, 3228, 360,
-+ 464, 3232, 392,
-+ 428, 3236, 428
-+};
-+
-+const uint16_t filter_3tap_64p_150[99] = {
-+ 2048, 2048, 0,
-+ 2004, 2080, 8,
-+ 1960, 2116, 16,
-+ 1916, 2148, 28,
-+ 1872, 2184, 36,
-+ 1824, 2216, 48,
-+ 1780, 2248, 60,
-+ 1736, 2280, 76,
-+ 1692, 2308, 88,
-+ 1648, 2336, 104,
-+ 1604, 2368, 120,
-+ 1560, 2392, 136,
-+ 1516, 2420, 156,
-+ 1472, 2444, 172,
-+ 1428, 2472, 192,
-+ 1384, 2492, 212,
-+ 1340, 2516, 236,
-+ 1296, 2536, 256,
-+ 1252, 2556, 280,
-+ 1212, 2576, 304,
-+ 1168, 2592, 328,
-+ 1124, 2608, 356,
-+ 1084, 2624, 384,
-+ 1044, 2636, 412,
-+ 1004, 2648, 440,
-+ 964, 2660, 468,
-+ 924, 2668, 500,
-+ 884, 2676, 528,
-+ 844, 2684, 560,
-+ 808, 2688, 596,
-+ 768, 2692, 628,
-+ 732, 2696, 664,
-+ 696, 2696, 696
-+};
-+
-+const uint16_t filter_3tap_64p_183[99] = {
-+ 2048, 2048, 0,
-+ 2008, 2060, 20,
-+ 1968, 2076, 44,
-+ 1932, 2088, 68,
-+ 1892, 2104, 92,
-+ 1856, 2116, 120,
-+ 1816, 2128, 144,
-+ 1780, 2140, 168,
-+ 1744, 2152, 196,
-+ 1704, 2164, 220,
-+ 1668, 2176, 248,
-+ 1632, 2188, 272,
-+ 1592, 2196, 300,
-+ 1556, 2204, 328,
-+ 1520, 2216, 356,
-+ 1484, 2224, 384,
-+ 1448, 2232, 412,
-+ 1412, 2240, 440,
-+ 1376, 2244, 468,
-+ 1340, 2252, 496,
-+ 1304, 2256, 528,
-+ 1272, 2264, 556,
-+ 1236, 2268, 584,
-+ 1200, 2272, 616,
-+ 1168, 2276, 648,
-+ 1132, 2280, 676,
-+ 1100, 2284, 708,
-+ 1064, 2288, 740,
-+ 1032, 2288, 772,
-+ 996, 2292, 800,
-+ 964, 2292, 832,
-+ 932, 2292, 868,
-+ 900, 2292, 900
-+};
-+
-+const uint16_t filter_4tap_64p_upscale[132] = {
-+ 0, 4096, 0, 0,
-+ 16344, 4092, 40, 0,
-+ 16308, 4084, 84, 16380,
-+ 16272, 4072, 132, 16380,
-+ 16240, 4056, 180, 16380,
-+ 16212, 4036, 232, 16376,
-+ 16184, 4012, 288, 16372,
-+ 16160, 3984, 344, 16368,
-+ 16136, 3952, 404, 16364,
-+ 16116, 3916, 464, 16360,
-+ 16100, 3872, 528, 16356,
-+ 16084, 3828, 596, 16348,
-+ 16072, 3780, 664, 16344,
-+ 16060, 3728, 732, 16336,
-+ 16052, 3676, 804, 16328,
-+ 16044, 3616, 876, 16320,
-+ 16040, 3556, 952, 16312,
-+ 16036, 3492, 1028, 16300,
-+ 16032, 3424, 1108, 16292,
-+ 16032, 3356, 1188, 16280,
-+ 16036, 3284, 1268, 16272,
-+ 16036, 3212, 1352, 16260,
-+ 16040, 3136, 1436, 16248,
-+ 16044, 3056, 1520, 16236,
-+ 16052, 2980, 1604, 16224,
-+ 16060, 2896, 1688, 16212,
-+ 16064, 2816, 1776, 16200,
-+ 16076, 2732, 1864, 16188,
-+ 16084, 2648, 1952, 16176,
-+ 16092, 2564, 2040, 16164,
-+ 16104, 2476, 2128, 16152,
-+ 16116, 2388, 2216, 16140,
-+ 16128, 2304, 2304, 16128 };
-+
-+const uint16_t filter_4tap_64p_117[132] = {
-+ 420, 3248, 420, 0,
-+ 380, 3248, 464, 16380,
-+ 344, 3248, 508, 16372,
-+ 308, 3248, 552, 16368,
-+ 272, 3240, 596, 16364,
-+ 236, 3236, 644, 16356,
-+ 204, 3224, 692, 16352,
-+ 172, 3212, 744, 16344,
-+ 144, 3196, 796, 16340,
-+ 116, 3180, 848, 16332,
-+ 88, 3160, 900, 16324,
-+ 60, 3136, 956, 16320,
-+ 36, 3112, 1012, 16312,
-+ 16, 3084, 1068, 16304,
-+ 16380, 3056, 1124, 16296,
-+ 16360, 3024, 1184, 16292,
-+ 16340, 2992, 1244, 16284,
-+ 16324, 2956, 1304, 16276,
-+ 16308, 2920, 1364, 16268,
-+ 16292, 2880, 1424, 16264,
-+ 16280, 2836, 1484, 16256,
-+ 16268, 2792, 1548, 16252,
-+ 16256, 2748, 1608, 16244,
-+ 16248, 2700, 1668, 16240,
-+ 16240, 2652, 1732, 16232,
-+ 16232, 2604, 1792, 16228,
-+ 16228, 2552, 1856, 16224,
-+ 16220, 2500, 1916, 16220,
-+ 16216, 2444, 1980, 16216,
-+ 16216, 2388, 2040, 16216,
-+ 16212, 2332, 2100, 16212,
-+ 16212, 2276, 2160, 16212,
-+ 16212, 2220, 2220, 16212 };
-+
-+const uint16_t filter_4tap_64p_150[132] = {
-+ 696, 2700, 696, 0,
-+ 660, 2704, 732, 16380,
-+ 628, 2704, 768, 16376,
-+ 596, 2704, 804, 16372,
-+ 564, 2700, 844, 16364,
-+ 532, 2696, 884, 16360,
-+ 500, 2692, 924, 16356,
-+ 472, 2684, 964, 16352,
-+ 440, 2676, 1004, 16352,
-+ 412, 2668, 1044, 16348,
-+ 384, 2656, 1088, 16344,
-+ 360, 2644, 1128, 16340,
-+ 332, 2632, 1172, 16336,
-+ 308, 2616, 1216, 16336,
-+ 284, 2600, 1260, 16332,
-+ 260, 2580, 1304, 16332,
-+ 236, 2560, 1348, 16328,
-+ 216, 2540, 1392, 16328,
-+ 196, 2516, 1436, 16328,
-+ 176, 2492, 1480, 16324,
-+ 156, 2468, 1524, 16324,
-+ 136, 2440, 1568, 16328,
-+ 120, 2412, 1612, 16328,
-+ 104, 2384, 1656, 16328,
-+ 88, 2352, 1700, 16332,
-+ 72, 2324, 1744, 16332,
-+ 60, 2288, 1788, 16336,
-+ 48, 2256, 1828, 16340,
-+ 36, 2220, 1872, 16344,
-+ 24, 2184, 1912, 16352,
-+ 12, 2148, 1952, 16356,
-+ 4, 2112, 1996, 16364,
-+ 16380, 2072, 2036, 16372 };
-+
-+const uint16_t filter_4tap_64p_183[132] = {
-+ 944, 2204, 944, 0,
-+ 916, 2204, 972, 0,
-+ 888, 2200, 996, 0,
-+ 860, 2200, 1024, 4,
-+ 832, 2196, 1052, 4,
-+ 808, 2192, 1080, 8,
-+ 780, 2188, 1108, 12,
-+ 756, 2180, 1140, 12,
-+ 728, 2176, 1168, 16,
-+ 704, 2168, 1196, 20,
-+ 680, 2160, 1224, 24,
-+ 656, 2152, 1252, 28,
-+ 632, 2144, 1280, 36,
-+ 608, 2132, 1308, 40,
-+ 584, 2120, 1336, 48,
-+ 560, 2112, 1364, 52,
-+ 536, 2096, 1392, 60,
-+ 516, 2084, 1420, 68,
-+ 492, 2072, 1448, 76,
-+ 472, 2056, 1476, 84,
-+ 452, 2040, 1504, 92,
-+ 428, 2024, 1532, 100,
-+ 408, 2008, 1560, 112,
-+ 392, 1992, 1584, 120,
-+ 372, 1972, 1612, 132,
-+ 352, 1956, 1636, 144,
-+ 336, 1936, 1664, 156,
-+ 316, 1916, 1688, 168,
-+ 300, 1896, 1712, 180,
-+ 284, 1876, 1736, 192,
-+ 268, 1852, 1760, 208,
-+ 252, 1832, 1784, 220,
-+ 236, 1808, 1808, 236 };
-+
-+const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio)
-+{
-+ if (ratio.value < dal_fixed31_32_one.value)
-+ return filter_3tap_16p_upscale;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
-+ return filter_3tap_16p_117;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
-+ return filter_3tap_16p_150;
-+ else
-+ return filter_3tap_16p_183;
-+}
-+
-+const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio)
-+{
-+ if (ratio.value < dal_fixed31_32_one.value)
-+ return filter_3tap_64p_upscale;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
-+ return filter_3tap_64p_117;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
-+ return filter_3tap_64p_150;
-+ else
-+ return filter_3tap_64p_183;
-+}
-+
-+const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio)
-+{
-+ if (ratio.value < dal_fixed31_32_one.value)
-+ return filter_4tap_16p_upscale;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
-+ return filter_4tap_16p_117;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
-+ return filter_4tap_16p_150;
-+ else
-+ return filter_4tap_16p_183;
-+}
-+
-+const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio)
-+{
-+ if (ratio.value < dal_fixed31_32_one.value)
-+ return filter_4tap_64p_upscale;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
-+ return filter_4tap_64p_117;
-+ else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
-+ return filter_4tap_64p_150;
-+ else
-+ return filter_4tap_64p_183;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
-new file mode 100644
-index 0000000..842182c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
-@@ -0,0 +1,1302 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dc_bios_types.h"
-+#include "dce_stream_encoder.h"
-+#include "reg_helper.h"
-+
-+enum DP_PIXEL_ENCODING {
-+DP_PIXEL_ENCODING_RGB444 = 0x00000000,
-+DP_PIXEL_ENCODING_YCBCR422 = 0x00000001,
-+DP_PIXEL_ENCODING_YCBCR444 = 0x00000002,
-+DP_PIXEL_ENCODING_RGB_WIDE_GAMUT = 0x00000003,
-+DP_PIXEL_ENCODING_Y_ONLY = 0x00000004,
-+DP_PIXEL_ENCODING_YCBCR420 = 0x00000005,
-+DP_PIXEL_ENCODING_RESERVED = 0x00000006,
-+};
-+
-+
-+enum DP_COMPONENT_DEPTH {
-+DP_COMPONENT_DEPTH_6BPC = 0x00000000,
-+DP_COMPONENT_DEPTH_8BPC = 0x00000001,
-+DP_COMPONENT_DEPTH_10BPC = 0x00000002,
-+DP_COMPONENT_DEPTH_12BPC = 0x00000003,
-+DP_COMPONENT_DEPTH_16BPC = 0x00000004,
-+DP_COMPONENT_DEPTH_RESERVED = 0x00000005,
-+};
-+
-+
-+#define REG(reg)\
-+ (enc110->regs->reg)
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ enc110->se_shift->field_name, enc110->se_mask->field_name
-+
-+#define VBI_LINE_0 0
-+#define DP_BLANK_MAX_RETRY 20
-+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
-+
-+#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK
-+ #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
-+ #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
-+ #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
-+ #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
-+#endif
-+
-+enum {
-+ DP_MST_UPDATE_MAX_RETRY = 50
-+};
-+
-+#define DCE110_SE(audio)\
-+ container_of(audio, struct dce110_stream_encoder, base)
-+
-+#define CTX \
-+ enc110->base.ctx
-+
-+static void dce110_update_generic_info_packet(
-+ struct dce110_stream_encoder *enc110,
-+ uint32_t packet_index,
-+ const struct encoder_info_packet *info_packet)
-+{
-+ uint32_t regval;
-+ /* TODOFPGA Figure out a proper number for max_retries polling for lock
-+ * use 50 for now.
-+ */
-+ uint32_t max_retries = 50;
-+
-+ if (REG(AFMT_VBI_PACKET_CONTROL1)) {
-+ if (packet_index >= 8)
-+ ASSERT(0);
-+
-+ /* poll dig_update_lock is not locked -> asic internal signal
-+ * assume otg master lock will unlock it
-+ */
-+ REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS,
-+ 1, 10, max_retries);
-+
-+ /* check if HW reading GSP memory */
-+ REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT,
-+ 1, 10, max_retries);
-+
-+ /* HW does is not reading GSP memory not reading too long ->
-+ * something wrong. clear GPS memory access and notify?
-+ * hw SW is writing to GSP memory
-+ */
-+ REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1);
-+ }
-+ /* choose which generic packet to use */
-+ {
-+ regval = REG_READ(AFMT_VBI_PACKET_CONTROL);
-+ REG_UPDATE(AFMT_VBI_PACKET_CONTROL,
-+ AFMT_GENERIC_INDEX, packet_index);
-+ }
-+
-+ /* write generic packet header
-+ * (4th byte is for GENERIC0 only) */
-+ {
-+ REG_SET_4(AFMT_GENERIC_HDR, 0,
-+ AFMT_GENERIC_HB0, info_packet->hb0,
-+ AFMT_GENERIC_HB1, info_packet->hb1,
-+ AFMT_GENERIC_HB2, info_packet->hb2,
-+ AFMT_GENERIC_HB3, info_packet->hb3);
-+ }
-+
-+ /* 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];
-+
-+ REG_WRITE(AFMT_GENERIC_0, *content++);
-+ REG_WRITE(AFMT_GENERIC_1, *content++);
-+ REG_WRITE(AFMT_GENERIC_2, *content++);
-+ REG_WRITE(AFMT_GENERIC_3, *content++);
-+ REG_WRITE(AFMT_GENERIC_4, *content++);
-+ REG_WRITE(AFMT_GENERIC_5, *content++);
-+ REG_WRITE(AFMT_GENERIC_6, *content);
-+ REG_WRITE(AFMT_GENERIC_7, 0);
-+ }
-+
-+ if (!REG(AFMT_VBI_PACKET_CONTROL1)) {
-+ /* force double-buffered packet update */
-+ REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL,
-+ AFMT_GENERIC0_UPDATE, (packet_index == 0),
-+ AFMT_GENERIC2_UPDATE, (packet_index == 2));
-+ }
-+}
-+
-+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;
-+
-+ 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:
-+ REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0,
-+ HDMI_GENERIC0_CONT, cont,
-+ HDMI_GENERIC0_SEND, send,
-+ HDMI_GENERIC0_LINE, line);
-+ break;
-+ case 1:
-+ REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0,
-+ HDMI_GENERIC1_CONT, cont,
-+ HDMI_GENERIC1_SEND, send,
-+ HDMI_GENERIC1_LINE, line);
-+ break;
-+ case 2:
-+ REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1,
-+ HDMI_GENERIC0_CONT, cont,
-+ HDMI_GENERIC0_SEND, send,
-+ HDMI_GENERIC0_LINE, line);
-+ break;
-+ case 3:
-+ REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1,
-+ HDMI_GENERIC1_CONT, cont,
-+ HDMI_GENERIC1_SEND, send,
-+ HDMI_GENERIC1_LINE, line);
-+ break;
-+ default:
-+ /* invalid HW packet index */
-+ dm_logger_write(
-+ ctx->logger, LOG_WARNING,
-+ "Invalid HW packet index: %s()\n",
-+ __func__);
-+ return;
-+ }
-+}
-+
-+/* setup stream encoder in dp mode */
-+static void dce110_stream_encoder_dp_set_stream_attribute(
-+ struct stream_encoder *enc,
-+ struct dc_crtc_timing *crtc_timing,
-+ enum dc_color_space output_color_space)
-+{
-+
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ /* set pixel encoding */
-+ switch (crtc_timing->pixel_encoding) {
-+ case PIXEL_ENCODING_YCBCR422:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
-+ DP_PIXEL_ENCODING_YCBCR422);
-+ break;
-+ case PIXEL_ENCODING_YCBCR444:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
-+ DP_PIXEL_ENCODING_YCBCR444);
-+
-+ 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 */
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
-+ DP_PIXEL_ENCODING_Y_ONLY);
-+ /* 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;
-+ case PIXEL_ENCODING_YCBCR420:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
-+ DP_PIXEL_ENCODING_YCBCR420);
-+ if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN)
-+ REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1);
-+
-+ break;
-+ default:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
-+ DP_PIXEL_ENCODING_RGB444);
-+ break;
-+ }
-+
-+ /* set color depth */
-+
-+ switch (crtc_timing->display_color_depth) {
-+ case COLOR_DEPTH_666:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
-+ 0);
-+ break;
-+ case COLOR_DEPTH_888:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
-+ DP_COMPONENT_DEPTH_8BPC);
-+ break;
-+ case COLOR_DEPTH_101010:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
-+ DP_COMPONENT_DEPTH_10BPC);
-+
-+ break;
-+ case COLOR_DEPTH_121212:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
-+ DP_COMPONENT_DEPTH_12BPC);
-+ break;
-+ default:
-+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
-+ DP_COMPONENT_DEPTH_6BPC);
-+ break;
-+ }
-+
-+ /* set dynamic range and YCbCr range */
-+ if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE)
-+ REG_UPDATE_2(
-+ DP_PIXEL_FORMAT,
-+ DP_DYN_RANGE, 0,
-+ DP_YCBCR_RANGE, 0);
-+
-+}
-+
-+static void dce110_stream_encoder_set_stream_attribute_helper(
-+ struct dce110_stream_encoder *enc110,
-+ struct dc_crtc_timing *crtc_timing)
-+{
-+ if (enc110->regs->TMDS_CNTL) {
-+ switch (crtc_timing->pixel_encoding) {
-+ case PIXEL_ENCODING_YCBCR422:
-+ REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 1);
-+ break;
-+ default:
-+ REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 0);
-+ break;
-+ }
-+ REG_UPDATE(TMDS_CNTL, TMDS_COLOR_FORMAT, 0);
-+ } else if (enc110->regs->DIG_FE_CNTL) {
-+ switch (crtc_timing->pixel_encoding) {
-+ case PIXEL_ENCODING_YCBCR422:
-+ REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1);
-+ break;
-+ default:
-+ REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0);
-+ break;
-+ }
-+ REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0);
-+ }
-+
-+}
-+
-+/* setup stream encoder in hdmi mode */
-+static void dce110_stream_encoder_hdmi_set_stream_attribute(
-+ struct stream_encoder *enc,
-+ struct dc_crtc_timing *crtc_timing,
-+ int actual_pix_clk_khz,
-+ bool enable_audio)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+ 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 = actual_pix_clk_khz;
-+ cntl.lanes_number = LANE_COUNT_FOUR;
-+
-+ if (enc110->base.bp->funcs->encoder_control(
-+ enc110->base.bp, &cntl) != BP_RESULT_OK)
-+ return;
-+
-+ dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing);
-+
-+ /* setup HDMI engine */
-+ if (!enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) {
-+ REG_UPDATE_3(HDMI_CONTROL,
-+ HDMI_PACKET_GEN_VERSION, 1,
-+ HDMI_KEEPOUT_MODE, 1,
-+ HDMI_DEEP_COLOR_ENABLE, 0);
-+ } else if (enc110->regs->DIG_FE_CNTL) {
-+ REG_UPDATE_5(HDMI_CONTROL,
-+ HDMI_PACKET_GEN_VERSION, 1,
-+ HDMI_KEEPOUT_MODE, 1,
-+ HDMI_DEEP_COLOR_ENABLE, 0,
-+ HDMI_DATA_SCRAMBLE_EN, 0,
-+ HDMI_CLOCK_CHANNEL_RATE, 0);
-+ }
-+
-+ switch (crtc_timing->display_color_depth) {
-+ case COLOR_DEPTH_888:
-+ REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
-+ break;
-+ case COLOR_DEPTH_101010:
-+ REG_UPDATE_2(HDMI_CONTROL,
-+ HDMI_DEEP_COLOR_DEPTH, 1,
-+ HDMI_DEEP_COLOR_ENABLE, 1);
-+ break;
-+ case COLOR_DEPTH_121212:
-+ REG_UPDATE_2(HDMI_CONTROL,
-+ HDMI_DEEP_COLOR_DEPTH, 2,
-+ HDMI_DEEP_COLOR_ENABLE, 1);
-+ break;
-+ case COLOR_DEPTH_161616:
-+ REG_UPDATE_2(HDMI_CONTROL,
-+ HDMI_DEEP_COLOR_DEPTH, 3,
-+ HDMI_DEEP_COLOR_ENABLE, 1);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) {
-+ if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
-+ /* enable HDMI data scrambler
-+ * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
-+ * Clock channel frequency is 1/4 of character rate.
-+ */
-+ REG_UPDATE_2(HDMI_CONTROL,
-+ HDMI_DATA_SCRAMBLE_EN, 1,
-+ HDMI_CLOCK_CHANNEL_RATE, 1);
-+ } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
-+
-+ /* TODO: New feature for DCE11, still need to implement */
-+
-+ /* enable HDMI data scrambler
-+ * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
-+ * Clock channel frequency is the same
-+ * as character rate
-+ */
-+ REG_UPDATE_2(HDMI_CONTROL,
-+ HDMI_DATA_SCRAMBLE_EN, 1,
-+ HDMI_CLOCK_CHANNEL_RATE, 0);
-+ }
-+ }
-+
-+ REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
-+ HDMI_GC_CONT, 1,
-+ HDMI_GC_SEND, 1,
-+ HDMI_NULL_SEND, 1);
-+
-+ /* following belongs to audio */
-+ REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
-+
-+ REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1);
-+
-+ REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE,
-+ VBI_LINE_0 + 2);
-+
-+ REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
-+
-+}
-+
-+/* setup stream encoder in dvi mode */
-+static 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 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;
-+
-+ if (enc110->base.bp->funcs->encoder_control(
-+ enc110->base.bp, &cntl) != BP_RESULT_OK)
-+ return;
-+
-+ ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB);
-+ ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888);
-+ dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing);
-+}
-+
-+static 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);
-+ 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));
-+
-+ {
-+ REG_SET_2(DP_MSE_RATE_CNTL, 0,
-+ DP_MSE_RATE_X, x,
-+ DP_MSE_RATE_Y, y);
-+ }
-+
-+ /* 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) */
-+ REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING,
-+ 0,
-+ 10, DP_MST_UPDATE_MAX_RETRY);
-+}
-+
-+static 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);
-+
-+ if (enc110->se_mask->HDMI_AVI_INFO_CONT &&
-+ enc110->se_mask->HDMI_AVI_INFO_SEND) {
-+
-+ if (info_frame->avi.valid) {
-+ const uint32_t *content =
-+ (const uint32_t *) &info_frame->avi.sb[0];
-+
-+ REG_WRITE(AFMT_AVI_INFO0, content[0]);
-+
-+ REG_WRITE(AFMT_AVI_INFO1, content[1]);
-+
-+ REG_WRITE(AFMT_AVI_INFO2, content[2]);
-+
-+ REG_WRITE(AFMT_AVI_INFO3, content[3]);
-+
-+ REG_UPDATE(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION,
-+ info_frame->avi.hb1);
-+
-+ REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0,
-+ HDMI_AVI_INFO_SEND, 1,
-+ HDMI_AVI_INFO_CONT, 1);
-+
-+ REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE,
-+ VBI_LINE_0 + 2);
-+
-+ } else {
-+ REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0,
-+ HDMI_AVI_INFO_SEND, 0,
-+ HDMI_AVI_INFO_CONT, 0);
-+ }
-+ }
-+
-+ if (enc110->se_mask->HDMI_AVI_INFO_CONT &&
-+ enc110->se_mask->HDMI_AVI_INFO_SEND) {
-+ 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);
-+ }
-+
-+}
-+
-+static void dce110_stream_encoder_stop_hdmi_info_packets(
-+ struct stream_encoder *enc)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ /* stop generic packets 0 & 1 on HDMI */
-+ REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0,
-+ HDMI_GENERIC1_CONT, 0,
-+ HDMI_GENERIC1_LINE, 0,
-+ HDMI_GENERIC1_SEND, 0,
-+ HDMI_GENERIC0_CONT, 0,
-+ HDMI_GENERIC0_LINE, 0,
-+ HDMI_GENERIC0_SEND, 0);
-+
-+ /* stop generic packets 2 & 3 on HDMI */
-+ REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0,
-+ HDMI_GENERIC0_CONT, 0,
-+ HDMI_GENERIC0_LINE, 0,
-+ HDMI_GENERIC0_SEND, 0,
-+ HDMI_GENERIC1_CONT, 0,
-+ HDMI_GENERIC1_LINE, 0,
-+ HDMI_GENERIC1_SEND, 0);
-+
-+}
-+
-+static 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);
-+ uint32_t value = REG_READ(DP_SEC_CNTL);
-+
-+ if (info_frame->vsc.valid)
-+ dce110_update_generic_info_packet(
-+ enc110,
-+ 0, /* packetIndex */
-+ &info_frame->vsc);
-+
-+ /* enable/disable transmission of packet(s).
-+ * If enabled, packet transmission begins on the next frame
-+ */
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid);
-+
-+ /* 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)
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
-+}
-+
-+static 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);
-+ uint32_t value = REG_READ(DP_SEC_CNTL);
-+
-+ if (enc110->se_mask->DP_SEC_AVI_ENABLE) {
-+ REG_SET_7(DP_SEC_CNTL, 0,
-+ DP_SEC_GSP0_ENABLE, 0,
-+ DP_SEC_GSP1_ENABLE, 0,
-+ DP_SEC_GSP2_ENABLE, 0,
-+ DP_SEC_GSP3_ENABLE, 0,
-+ DP_SEC_AVI_ENABLE, 0,
-+ DP_SEC_MPG_ENABLE, 0,
-+ DP_SEC_STREAM_ENABLE, 0);
-+ }
-+
-+ /* 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)
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
-+
-+}
-+
-+static void dce110_stream_encoder_dp_blank(
-+ struct stream_encoder *enc)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+ 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) */
-+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2);
-+ /* 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 */
-+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
-+
-+ /* the encoder stops sending the video stream
-+ * at the start of the vertical blanking.
-+ * Poll for DP_VID_STREAM_STATUS == 0
-+ */
-+
-+ REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS,
-+ 1,
-+ 10, 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.
-+ */
-+
-+ REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true);
-+}
-+
-+/* output video stream to link encoder */
-+static 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);
-+
-+ 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 */
-+
-+ REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0);
-+
-+ /* auto measurement need 1 full 0x8000 symbol cycle to kick in,
-+ * therefore program initial value for Mvid and Nvid
-+ */
-+
-+ REG_UPDATE(DP_VID_N, DP_VID_N, n_vid);
-+
-+ REG_UPDATE(DP_VID_M, DP_VID_M, m_vid);
-+
-+ REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 1);
-+ }
-+
-+ /* set DIG_START to 0x1 to resync FIFO */
-+
-+ REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
-+
-+ /* switch DP encoder to CRTC data */
-+
-+ REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
-+
-+ /* wait 100us for DIG/DP logic to prime
-+ * (i.e. a few video lines)
-+ */
-+ udelay(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
-+ */
-+
-+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
-+}
-+
-+
-+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
-+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
-+
-+#include "include/audio_types.h"
-+
-+/**
-+* 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 {
-+ 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_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;
-+};
-+
-+/* 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}
-+};
-+
-+union audio_cea_channels speakers_to_channels(
-+ 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;
-+}
-+
-+uint32_t calc_max_audio_packets_per_line(
-+ 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;
-+}
-+
-+bool get_audio_clock_info(
-+ 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 */
-+ *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 void dce110_se_audio_setup(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *audio_info)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ uint32_t speakers = 0;
-+ uint32_t channels = 0;
-+
-+ ASSERT(audio_info);
-+ if (audio_info == NULL)
-+ /* This should not happen.it does so we don't get BSOD*/
-+ return;
-+
-+ speakers = audio_info->flags.info.ALLSPEAKERS;
-+ channels = speakers_to_channels(audio_info->flags.speaker_flags).all;
-+
-+ /* setup the audio stream source select (audio -> dig mapping) */
-+ REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst);
-+
-+ /* Channel allocation */
-+ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels);
-+}
-+
-+static void dce110_se_setup_hdmi_audio(
-+ struct stream_encoder *enc,
-+ const struct audio_crtc_info *crtc_info)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ struct audio_clock_info audio_clock_info = {0};
-+ uint32_t max_packets_per_line;
-+
-+ /* For now still do calculation, although this field is ignored when
-+ above HDMI_PACKET_GEN_VERSION set to 1 */
-+ max_packets_per_line = calc_max_audio_packets_per_line(crtc_info);
-+
-+ /* HDMI_AUDIO_PACKET_CONTROL */
-+ REG_UPDATE_2(HDMI_AUDIO_PACKET_CONTROL,
-+ HDMI_AUDIO_PACKETS_PER_LINE, max_packets_per_line,
-+ HDMI_AUDIO_DELAY_EN, 1);
-+
-+ /* AFMT_AUDIO_PACKET_CONTROL */
-+ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1);
-+
-+ /* AFMT_AUDIO_PACKET_CONTROL2 */
-+ REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2,
-+ AFMT_AUDIO_LAYOUT_OVRD, 0,
-+ AFMT_60958_OSF_OVRD, 0);
-+
-+ /* HDMI_ACR_PACKET_CONTROL */
-+ REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL,
-+ HDMI_ACR_AUTO_SEND, 1,
-+ HDMI_ACR_SOURCE, 0,
-+ HDMI_ACR_AUDIO_PRIORITY, 0);
-+
-+ /* Program audio clock sample/regeneration parameters */
-+ if (get_audio_clock_info(
-+ 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 */
-+ REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz);
-+
-+ /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
-+ REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz);
-+
-+ /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
-+ REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz);
-+
-+ /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
-+ REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz);
-+
-+ /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
-+ REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz);
-+
-+ /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
-+ REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz);
-+
-+ /* 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 */
-+ REG_UPDATE_2(AFMT_60958_0,
-+ AFMT_60958_CS_CHANNEL_NUMBER_L, 1,
-+ AFMT_60958_CS_CLOCK_ACCURACY, 0);
-+
-+ /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */
-+ REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2);
-+
-+ /*AFMT_60958_2 now keep this settings until
-+ * Programming guide comes out*/
-+ REG_UPDATE_6(AFMT_60958_2,
-+ AFMT_60958_CS_CHANNEL_NUMBER_2, 3,
-+ AFMT_60958_CS_CHANNEL_NUMBER_3, 4,
-+ AFMT_60958_CS_CHANNEL_NUMBER_4, 5,
-+ AFMT_60958_CS_CHANNEL_NUMBER_5, 6,
-+ AFMT_60958_CS_CHANNEL_NUMBER_6, 7,
-+ AFMT_60958_CS_CHANNEL_NUMBER_7, 8);
-+}
-+
-+static void dce110_se_setup_dp_audio(
-+ struct stream_encoder *enc)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ /* --- DP Audio packet configurations --- */
-+
-+ /* ATP Configuration */
-+ REG_SET(DP_SEC_AUD_N, 0,
-+ DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT);
-+
-+ /* Async/auto-calc timestamp mode */
-+ REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE,
-+ DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC);
-+
-+ /* --- The following are the registers
-+ * copied from the SetupHDMI --- */
-+
-+ /* AFMT_AUDIO_PACKET_CONTROL */
-+ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1);
-+
-+ /* AFMT_AUDIO_PACKET_CONTROL2 */
-+ /* Program the ATP and AIP next */
-+ REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2,
-+ AFMT_AUDIO_LAYOUT_OVRD, 0,
-+ AFMT_60958_OSF_OVRD, 0);
-+
-+ /* AFMT_INFOFRAME_CONTROL0 */
-+ REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1);
-+
-+ /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
-+ REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0);
-+}
-+
-+static void dce110_se_enable_audio_clock(
-+ struct stream_encoder *enc,
-+ bool enable)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ if (REG(AFMT_CNTL) == 0)
-+ return; /* DCE8/10 does not have this register */
-+
-+ REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable);
-+
-+ /* wait for AFMT clock to turn on,
-+ * expectation: this should complete in 1-2 reads
-+ *
-+ * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10);
-+ *
-+ * TODO: wait for clock_on does not work well. May need HW
-+ * program sequence. But audio seems work normally even without wait
-+ * for clock_on status change
-+ */
-+}
-+
-+static void dce110_se_enable_dp_audio(
-+ struct stream_encoder *enc)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ /* Enable Audio packets */
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1);
-+
-+ /* Program the ATP and AIP next */
-+ REG_UPDATE_2(DP_SEC_CNTL,
-+ DP_SEC_ATP_ENABLE, 1,
-+ DP_SEC_AIP_ENABLE, 1);
-+
-+ /* Program STREAM_ENABLE after all the other enables. */
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
-+}
-+
-+static void dce110_se_disable_dp_audio(
-+ struct stream_encoder *enc)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+ uint32_t value = REG_READ(DP_SEC_CNTL);
-+
-+ /* Disable Audio packets */
-+ REG_UPDATE_5(DP_SEC_CNTL,
-+ DP_SEC_ASP_ENABLE, 0,
-+ DP_SEC_ATP_ENABLE, 0,
-+ DP_SEC_AIP_ENABLE, 0,
-+ DP_SEC_ACM_ENABLE, 0,
-+ DP_SEC_STREAM_ENABLE, 0);
-+
-+ /* 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)
-+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
-+
-+}
-+
-+void dce110_se_audio_mute_control(
-+ struct stream_encoder *enc,
-+ bool mute)
-+{
-+ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-+
-+ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute);
-+}
-+
-+void dce110_se_dp_audio_setup(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info)
-+{
-+ dce110_se_audio_setup(enc, az_inst, info);
-+}
-+
-+void dce110_se_dp_audio_enable(
-+ struct stream_encoder *enc)
-+{
-+ dce110_se_enable_audio_clock(enc, true);
-+ dce110_se_setup_dp_audio(enc);
-+ dce110_se_enable_dp_audio(enc);
-+}
-+
-+void dce110_se_dp_audio_disable(
-+ struct stream_encoder *enc)
-+{
-+ dce110_se_disable_dp_audio(enc);
-+ dce110_se_enable_audio_clock(enc, false);
-+}
-+
-+void dce110_se_hdmi_audio_setup(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info,
-+ struct audio_crtc_info *audio_crtc_info)
-+{
-+ dce110_se_enable_audio_clock(enc, true);
-+ dce110_se_setup_hdmi_audio(enc, audio_crtc_info);
-+ dce110_se_audio_setup(enc, az_inst, info);
-+}
-+
-+void dce110_se_hdmi_audio_disable(
-+ struct stream_encoder *enc)
-+{
-+ dce110_se_enable_audio_clock(enc, false);
-+}
-+
-+static const 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,
-+
-+ .audio_mute_control = dce110_se_audio_mute_control,
-+
-+ .dp_audio_setup = dce110_se_dp_audio_setup,
-+ .dp_audio_enable = dce110_se_dp_audio_enable,
-+ .dp_audio_disable = dce110_se_dp_audio_disable,
-+
-+ .hdmi_audio_setup = dce110_se_hdmi_audio_setup,
-+ .hdmi_audio_disable = dce110_se_hdmi_audio_disable,
-+};
-+
-+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,
-+ const struct dce_stream_encoder_shift *se_shift,
-+ const struct dce_stream_encoder_mask *se_mask)
-+{
-+ 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;
-+ enc110->se_shift = se_shift;
-+ enc110->se_mask = se_mask;
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
-new file mode 100644
-index 0000000..458a370
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
-@@ -0,0 +1,564 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "stream_encoder.h"
-+
-+#define DCE110STRENC_FROM_STRENC(stream_encoder)\
-+ container_of(stream_encoder, struct dce110_stream_encoder, base)
-+
-+#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK
-+ #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
-+ #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
-+ #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
-+ #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
-+#endif
-+
-+
-+#define SE_COMMON_REG_LIST_DCE_BASE(id) \
-+ SE_COMMON_REG_LIST_BASE(id),\
-+ SRI(AFMT_AVI_INFO0, DIG, id), \
-+ SRI(AFMT_AVI_INFO1, DIG, id), \
-+ SRI(AFMT_AVI_INFO2, DIG, id), \
-+ SRI(AFMT_AVI_INFO3, DIG, id)
-+
-+#define SE_COMMON_REG_LIST_BASE(id) \
-+ SRI(AFMT_GENERIC_0, DIG, id), \
-+ SRI(AFMT_GENERIC_1, DIG, id), \
-+ SRI(AFMT_GENERIC_2, DIG, id), \
-+ SRI(AFMT_GENERIC_3, DIG, id), \
-+ SRI(AFMT_GENERIC_4, DIG, id), \
-+ SRI(AFMT_GENERIC_5, DIG, id), \
-+ SRI(AFMT_GENERIC_6, DIG, id), \
-+ SRI(AFMT_GENERIC_7, DIG, id), \
-+ SRI(AFMT_GENERIC_HDR, DIG, id), \
-+ SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \
-+ SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \
-+ SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \
-+ SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \
-+ SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \
-+ SRI(AFMT_60958_0, DIG, id), \
-+ SRI(AFMT_60958_1, DIG, id), \
-+ SRI(AFMT_60958_2, DIG, id), \
-+ SRI(DIG_FE_CNTL, DIG, id), \
-+ SRI(HDMI_CONTROL, DIG, id), \
-+ SRI(HDMI_GC, DIG, id), \
-+ SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
-+ SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
-+ SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \
-+ SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \
-+ SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \
-+ SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\
-+ SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\
-+ SRI(HDMI_ACR_32_0, DIG, id),\
-+ SRI(HDMI_ACR_32_1, DIG, id),\
-+ SRI(HDMI_ACR_44_0, DIG, id),\
-+ SRI(HDMI_ACR_44_1, DIG, id),\
-+ SRI(HDMI_ACR_48_0, DIG, id),\
-+ SRI(HDMI_ACR_48_1, DIG, id),\
-+ SRI(TMDS_CNTL, DIG, id), \
-+ SRI(DP_MSE_RATE_CNTL, DP, id), \
-+ SRI(DP_MSE_RATE_UPDATE, DP, id), \
-+ SRI(DP_PIXEL_FORMAT, DP, id), \
-+ SRI(DP_SEC_CNTL, DP, id), \
-+ SRI(DP_STEER_FIFO, DP, id), \
-+ SRI(DP_VID_M, DP, id), \
-+ SRI(DP_VID_N, DP, id), \
-+ SRI(DP_VID_STREAM_CNTL, DP, id), \
-+ SRI(DP_VID_TIMING, DP, id), \
-+ SRI(DP_SEC_AUD_N, DP, id), \
-+ SRI(DP_SEC_TIMESTAMP, DP, id)
-+
-+#define SE_COMMON_REG_LIST(id)\
-+ SE_COMMON_REG_LIST_DCE_BASE(id), \
-+ SRI(AFMT_CNTL, DIG, id)
-+
-+#define SE_SF(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+#define SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
-+ SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\
-+ SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\
-+ SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\
-+ SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\
-+ SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\
-+ SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\
-+ SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
-+ SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\
-+ SE_SF(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
-+ SE_SF(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
-+ SE_SF(DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\
-+ SE_SF(DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
-+ SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
-+ SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
-+ SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
-+ SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
-+ SE_SF(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\
-+ SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
-+ SE_SF(HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
-+ SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
-+ SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
-+ SE_SF(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
-+ SE_SF(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\
-+ SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\
-+ SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\
-+ SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\
-+ SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
-+ SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
-+ SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
-+ SE_SF(DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
-+ SE_SF(DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
-+ SE_SF(DP_VID_N, DP_VID_N, mask_sh),\
-+ SE_SF(DP_VID_M, DP_VID_M, mask_sh),\
-+ SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\
-+ SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\
-+ SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\
-+ SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\
-+ SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
-+ SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\
-+ SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\
-+ SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\
-+ SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
-+ SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
-+ SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
-+ SE_SF(HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
-+ SE_SF(HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
-+ SE_SF(HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
-+ SE_SF(HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
-+ SE_SF(HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
-+ SE_SF(HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
-+ SE_SF(AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\
-+ SE_SF(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\
-+ SE_SF(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\
-+ SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\
-+ SE_SF(DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
-+ SE_SF(DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
-+ SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
-+ SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh)
-+
-+#define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\
-+ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
-+
-+#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\
-+ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
-+ SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
-+ SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh)
-+
-+#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
-+ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
-+ SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
-+ SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
-+ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh)
-+
-+#define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\
-+ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
-+ SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
-+ SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
-+ SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
-+ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
-+ SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh)
-+
-+struct dce_stream_encoder_shift {
-+ uint8_t AFMT_GENERIC_INDEX;
-+ uint8_t AFMT_GENERIC0_UPDATE;
-+ uint8_t AFMT_GENERIC2_UPDATE;
-+ uint8_t AFMT_GENERIC_HB0;
-+ uint8_t AFMT_GENERIC_HB1;
-+ uint8_t AFMT_GENERIC_HB2;
-+ uint8_t AFMT_GENERIC_HB3;
-+ uint8_t AFMT_GENERIC_LOCK_STATUS;
-+ uint8_t AFMT_GENERIC_CONFLICT;
-+ uint8_t AFMT_GENERIC_CONFLICT_CLR;
-+ uint8_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
-+ uint8_t AFMT_GENERIC0_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC1_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC2_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC3_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC4_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC5_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC6_FRAME_UPDATE;
-+ uint8_t AFMT_GENERIC7_FRAME_UPDATE;
-+ uint8_t HDMI_GENERIC0_CONT;
-+ uint8_t HDMI_GENERIC0_SEND;
-+ uint8_t HDMI_GENERIC0_LINE;
-+ uint8_t HDMI_GENERIC1_CONT;
-+ uint8_t HDMI_GENERIC1_SEND;
-+ uint8_t HDMI_GENERIC1_LINE;
-+ uint8_t DP_PIXEL_ENCODING;
-+ uint8_t DP_COMPONENT_DEPTH;
-+ uint8_t DP_DYN_RANGE;
-+ uint8_t DP_YCBCR_RANGE;
-+ uint8_t HDMI_PACKET_GEN_VERSION;
-+ uint8_t HDMI_KEEPOUT_MODE;
-+ uint8_t HDMI_DEEP_COLOR_ENABLE;
-+ uint8_t HDMI_CLOCK_CHANNEL_RATE;
-+ uint8_t HDMI_DEEP_COLOR_DEPTH;
-+ uint8_t HDMI_GC_CONT;
-+ uint8_t HDMI_GC_SEND;
-+ uint8_t HDMI_NULL_SEND;
-+ uint8_t HDMI_DATA_SCRAMBLE_EN;
-+ uint8_t HDMI_AUDIO_INFO_SEND;
-+ uint8_t AFMT_AUDIO_INFO_UPDATE;
-+ uint8_t HDMI_AUDIO_INFO_LINE;
-+ uint8_t HDMI_GC_AVMUTE;
-+ uint8_t DP_MSE_RATE_X;
-+ uint8_t DP_MSE_RATE_Y;
-+ uint8_t DP_MSE_RATE_UPDATE_PENDING;
-+ uint8_t AFMT_AVI_INFO_VERSION;
-+ uint8_t HDMI_AVI_INFO_SEND;
-+ uint8_t HDMI_AVI_INFO_CONT;
-+ uint8_t HDMI_AVI_INFO_LINE;
-+ uint8_t DP_SEC_GSP0_ENABLE;
-+ uint8_t DP_SEC_STREAM_ENABLE;
-+ uint8_t DP_SEC_GSP1_ENABLE;
-+ uint8_t DP_SEC_GSP2_ENABLE;
-+ uint8_t DP_SEC_GSP3_ENABLE;
-+ uint8_t DP_SEC_GSP4_ENABLE;
-+ uint8_t DP_SEC_GSP5_ENABLE;
-+ uint8_t DP_SEC_GSP6_ENABLE;
-+ uint8_t DP_SEC_GSP7_ENABLE;
-+ uint8_t DP_SEC_AVI_ENABLE;
-+ uint8_t DP_SEC_MPG_ENABLE;
-+ uint8_t DP_VID_STREAM_DIS_DEFER;
-+ uint8_t DP_VID_STREAM_ENABLE;
-+ uint8_t DP_VID_STREAM_STATUS;
-+ uint8_t DP_STEER_FIFO_RESET;
-+ uint8_t DP_VID_M_N_GEN_EN;
-+ uint8_t DP_VID_N;
-+ uint8_t DP_VID_M;
-+ uint8_t DIG_START;
-+ uint8_t AFMT_AUDIO_SRC_SELECT;
-+ uint8_t AFMT_AUDIO_CHANNEL_ENABLE;
-+ uint8_t HDMI_AUDIO_PACKETS_PER_LINE;
-+ uint8_t HDMI_AUDIO_DELAY_EN;
-+ uint8_t AFMT_60958_CS_UPDATE;
-+ uint8_t AFMT_AUDIO_LAYOUT_OVRD;
-+ uint8_t AFMT_60958_OSF_OVRD;
-+ uint8_t HDMI_ACR_AUTO_SEND;
-+ uint8_t HDMI_ACR_SOURCE;
-+ uint8_t HDMI_ACR_AUDIO_PRIORITY;
-+ uint8_t HDMI_ACR_CTS_32;
-+ uint8_t HDMI_ACR_N_32;
-+ uint8_t HDMI_ACR_CTS_44;
-+ uint8_t HDMI_ACR_N_44;
-+ uint8_t HDMI_ACR_CTS_48;
-+ uint8_t HDMI_ACR_N_48;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_L;
-+ uint8_t AFMT_60958_CS_CLOCK_ACCURACY;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_R;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_2;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_3;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_4;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_5;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_6;
-+ uint8_t AFMT_60958_CS_CHANNEL_NUMBER_7;
-+ uint8_t DP_SEC_AUD_N;
-+ uint8_t DP_SEC_TIMESTAMP_MODE;
-+ uint8_t DP_SEC_ASP_ENABLE;
-+ uint8_t DP_SEC_ATP_ENABLE;
-+ uint8_t DP_SEC_AIP_ENABLE;
-+ uint8_t DP_SEC_ACM_ENABLE;
-+ uint8_t AFMT_AUDIO_SAMPLE_SEND;
-+ uint8_t AFMT_AUDIO_CLOCK_EN;
-+ uint8_t TMDS_PIXEL_ENCODING;
-+ uint8_t TMDS_COLOR_FORMAT;
-+ uint8_t DP_DB_DISABLE;
-+ uint8_t DP_MSA_MISC0;
-+ uint8_t DP_MSA_HTOTAL;
-+ uint8_t DP_MSA_VTOTAL;
-+ uint8_t DP_MSA_HSTART;
-+ uint8_t DP_MSA_VSTART;
-+ uint8_t DP_MSA_HSYNCWIDTH;
-+ uint8_t DP_MSA_HSYNCPOLARITY;
-+ uint8_t DP_MSA_VSYNCWIDTH;
-+ uint8_t DP_MSA_VSYNCPOLARITY;
-+ uint8_t DP_MSA_HWIDTH;
-+ uint8_t DP_MSA_VHEIGHT;
-+ uint8_t HDMI_DB_DISABLE;
-+ uint8_t DP_VID_N_MUL;
-+ uint8_t DP_VID_M_DOUBLE_VALUE_EN;
-+};
-+
-+struct dce_stream_encoder_mask {
-+ uint32_t AFMT_GENERIC_INDEX;
-+ uint32_t AFMT_GENERIC0_UPDATE;
-+ uint32_t AFMT_GENERIC2_UPDATE;
-+ uint32_t AFMT_GENERIC_HB0;
-+ uint32_t AFMT_GENERIC_HB1;
-+ uint32_t AFMT_GENERIC_HB2;
-+ uint32_t AFMT_GENERIC_HB3;
-+ uint32_t AFMT_GENERIC_LOCK_STATUS;
-+ uint32_t AFMT_GENERIC_CONFLICT;
-+ uint32_t AFMT_GENERIC_CONFLICT_CLR;
-+ uint32_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
-+ uint32_t AFMT_GENERIC0_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC1_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC2_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC3_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC4_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC5_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC6_FRAME_UPDATE;
-+ uint32_t AFMT_GENERIC7_FRAME_UPDATE;
-+ uint32_t HDMI_GENERIC0_CONT;
-+ uint32_t HDMI_GENERIC0_SEND;
-+ uint32_t HDMI_GENERIC0_LINE;
-+ uint32_t HDMI_GENERIC1_CONT;
-+ uint32_t HDMI_GENERIC1_SEND;
-+ uint32_t HDMI_GENERIC1_LINE;
-+ uint32_t DP_PIXEL_ENCODING;
-+ uint32_t DP_COMPONENT_DEPTH;
-+ uint32_t DP_DYN_RANGE;
-+ uint32_t DP_YCBCR_RANGE;
-+ uint32_t HDMI_PACKET_GEN_VERSION;
-+ uint32_t HDMI_KEEPOUT_MODE;
-+ uint32_t HDMI_DEEP_COLOR_ENABLE;
-+ uint32_t HDMI_CLOCK_CHANNEL_RATE;
-+ uint32_t HDMI_DEEP_COLOR_DEPTH;
-+ uint32_t HDMI_GC_CONT;
-+ uint32_t HDMI_GC_SEND;
-+ uint32_t HDMI_NULL_SEND;
-+ uint32_t HDMI_DATA_SCRAMBLE_EN;
-+ uint32_t HDMI_AUDIO_INFO_SEND;
-+ uint32_t AFMT_AUDIO_INFO_UPDATE;
-+ uint32_t HDMI_AUDIO_INFO_LINE;
-+ uint32_t HDMI_GC_AVMUTE;
-+ uint32_t DP_MSE_RATE_X;
-+ uint32_t DP_MSE_RATE_Y;
-+ uint32_t DP_MSE_RATE_UPDATE_PENDING;
-+ uint32_t AFMT_AVI_INFO_VERSION;
-+ uint32_t HDMI_AVI_INFO_SEND;
-+ uint32_t HDMI_AVI_INFO_CONT;
-+ uint32_t HDMI_AVI_INFO_LINE;
-+ uint32_t DP_SEC_GSP0_ENABLE;
-+ uint32_t DP_SEC_STREAM_ENABLE;
-+ uint32_t DP_SEC_GSP1_ENABLE;
-+ uint32_t DP_SEC_GSP2_ENABLE;
-+ uint32_t DP_SEC_GSP3_ENABLE;
-+ uint32_t DP_SEC_GSP4_ENABLE;
-+ uint32_t DP_SEC_GSP5_ENABLE;
-+ uint32_t DP_SEC_GSP6_ENABLE;
-+ uint32_t DP_SEC_GSP7_ENABLE;
-+ uint32_t DP_SEC_AVI_ENABLE;
-+ uint32_t DP_SEC_MPG_ENABLE;
-+ uint32_t DP_VID_STREAM_DIS_DEFER;
-+ uint32_t DP_VID_STREAM_ENABLE;
-+ uint32_t DP_VID_STREAM_STATUS;
-+ uint32_t DP_STEER_FIFO_RESET;
-+ uint32_t DP_VID_M_N_GEN_EN;
-+ uint32_t DP_VID_N;
-+ uint32_t DP_VID_M;
-+ uint32_t DIG_START;
-+ uint32_t AFMT_AUDIO_SRC_SELECT;
-+ uint32_t AFMT_AUDIO_CHANNEL_ENABLE;
-+ uint32_t HDMI_AUDIO_PACKETS_PER_LINE;
-+ uint32_t HDMI_AUDIO_DELAY_EN;
-+ uint32_t AFMT_60958_CS_UPDATE;
-+ uint32_t AFMT_AUDIO_LAYOUT_OVRD;
-+ uint32_t AFMT_60958_OSF_OVRD;
-+ uint32_t HDMI_ACR_AUTO_SEND;
-+ uint32_t HDMI_ACR_SOURCE;
-+ uint32_t HDMI_ACR_AUDIO_PRIORITY;
-+ uint32_t HDMI_ACR_CTS_32;
-+ uint32_t HDMI_ACR_N_32;
-+ uint32_t HDMI_ACR_CTS_44;
-+ uint32_t HDMI_ACR_N_44;
-+ uint32_t HDMI_ACR_CTS_48;
-+ uint32_t HDMI_ACR_N_48;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_L;
-+ uint32_t AFMT_60958_CS_CLOCK_ACCURACY;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_R;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_2;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_3;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_4;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_5;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_6;
-+ uint32_t AFMT_60958_CS_CHANNEL_NUMBER_7;
-+ uint32_t DP_SEC_AUD_N;
-+ uint32_t DP_SEC_TIMESTAMP_MODE;
-+ uint32_t DP_SEC_ASP_ENABLE;
-+ uint32_t DP_SEC_ATP_ENABLE;
-+ uint32_t DP_SEC_AIP_ENABLE;
-+ uint32_t DP_SEC_ACM_ENABLE;
-+ uint32_t AFMT_AUDIO_SAMPLE_SEND;
-+ uint32_t AFMT_AUDIO_CLOCK_EN;
-+ uint32_t TMDS_PIXEL_ENCODING;
-+ uint32_t TMDS_COLOR_FORMAT;
-+ uint32_t DP_DB_DISABLE;
-+ uint32_t DP_MSA_MISC0;
-+ uint32_t DP_MSA_HTOTAL;
-+ uint32_t DP_MSA_VTOTAL;
-+ uint32_t DP_MSA_HSTART;
-+ uint32_t DP_MSA_VSTART;
-+ uint32_t DP_MSA_HSYNCWIDTH;
-+ uint32_t DP_MSA_HSYNCPOLARITY;
-+ uint32_t DP_MSA_VSYNCWIDTH;
-+ uint32_t DP_MSA_VSYNCPOLARITY;
-+ uint32_t DP_MSA_HWIDTH;
-+ uint32_t DP_MSA_VHEIGHT;
-+ uint32_t HDMI_DB_DISABLE;
-+ uint32_t DP_VID_N_MUL;
-+ uint32_t DP_VID_M_DOUBLE_VALUE_EN;
-+};
-+
-+struct dce110_stream_enc_registers {
-+ uint32_t AFMT_CNTL;
-+ 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_1;
-+ uint32_t AFMT_GENERIC_2;
-+ uint32_t AFMT_GENERIC_3;
-+ uint32_t AFMT_GENERIC_4;
-+ uint32_t AFMT_GENERIC_5;
-+ uint32_t AFMT_GENERIC_6;
-+ uint32_t AFMT_GENERIC_7;
-+ uint32_t AFMT_GENERIC_HDR;
-+ uint32_t AFMT_INFOFRAME_CONTROL0;
-+ uint32_t AFMT_VBI_PACKET_CONTROL;
-+ uint32_t AFMT_VBI_PACKET_CONTROL1;
-+ uint32_t AFMT_AUDIO_PACKET_CONTROL;
-+ uint32_t AFMT_AUDIO_PACKET_CONTROL2;
-+ uint32_t AFMT_AUDIO_SRC_CONTROL;
-+ uint32_t AFMT_60958_0;
-+ uint32_t AFMT_60958_1;
-+ uint32_t AFMT_60958_2;
-+ 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 DP_SEC_AUD_N;
-+ uint32_t DP_SEC_TIMESTAMP;
-+ uint32_t HDMI_CONTROL;
-+ uint32_t HDMI_GC;
-+ uint32_t HDMI_GENERIC_PACKET_CONTROL0;
-+ uint32_t HDMI_GENERIC_PACKET_CONTROL1;
-+ uint32_t HDMI_GENERIC_PACKET_CONTROL2;
-+ uint32_t HDMI_GENERIC_PACKET_CONTROL3;
-+ uint32_t HDMI_INFOFRAME_CONTROL0;
-+ uint32_t HDMI_INFOFRAME_CONTROL1;
-+ uint32_t HDMI_VBI_PACKET_CONTROL;
-+ uint32_t HDMI_AUDIO_PACKET_CONTROL;
-+ uint32_t HDMI_ACR_PACKET_CONTROL;
-+ uint32_t HDMI_ACR_32_0;
-+ uint32_t HDMI_ACR_32_1;
-+ uint32_t HDMI_ACR_44_0;
-+ uint32_t HDMI_ACR_44_1;
-+ uint32_t HDMI_ACR_48_0;
-+ uint32_t HDMI_ACR_48_1;
-+ uint32_t TMDS_CNTL;
-+};
-+
-+struct dce110_stream_encoder {
-+ struct stream_encoder base;
-+ const struct dce110_stream_enc_registers *regs;
-+ const struct dce_stream_encoder_shift *se_shift;
-+ const struct dce_stream_encoder_mask *se_mask;
-+};
-+
-+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,
-+ const struct dce_stream_encoder_shift *se_shift,
-+ const struct dce_stream_encoder_mask *se_mask);
-+
-+
-+void dce110_se_audio_mute_control(
-+ struct stream_encoder *enc, bool mute);
-+
-+void dce110_se_dp_audio_setup(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info);
-+
-+void dce110_se_dp_audio_enable(
-+ struct stream_encoder *enc);
-+
-+void dce110_se_dp_audio_disable(
-+ struct stream_encoder *enc);
-+
-+void dce110_se_hdmi_audio_setup(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info,
-+ struct audio_crtc_info *audio_crtc_info);
-+
-+void dce110_se_hdmi_audio_disable(
-+ struct stream_encoder *enc);
-+
-+#endif /* __DC_STREAM_ENCODER_DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
-new file mode 100644
-index 0000000..f47b6617
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
-@@ -0,0 +1,1002 @@
-+/*
-+ * 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 "dce_transform.h"
-+#include "reg_helper.h"
-+#include "opp.h"
-+#include "basics/conversion.h"
-+
-+#define REG(reg) \
-+ (xfm_dce->regs->reg)
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name
-+
-+#define CTX \
-+ xfm_dce->base.ctx
-+
-+#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19))
-+#define GAMUT_MATRIX_SIZE 12
-+#define SCL_PHASES 16
-+
-+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 setup_scaling_configuration(
-+ struct dce_transform *xfm_dce,
-+ const struct scaler_data *data)
-+{
-+ struct dc_context *ctx = xfm_dce->base.ctx;
-+
-+ if (data->taps.h_taps + data->taps.v_taps <= 2) {
-+ /* Set bypass */
-+ REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0);
-+ return false;
-+ }
-+
-+ REG_SET_2(SCL_TAP_CONTROL, 0,
-+ SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
-+ SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
-+
-+ if (data->format <= PIXEL_FORMAT_GRPH_END)
-+ REG_UPDATE_2(SCL_MODE, SCL_MODE, 1, SCL_PSCL_EN, 1);
-+ else
-+ REG_UPDATE_2(SCL_MODE, SCL_MODE, 2, SCL_PSCL_EN, 1);
-+
-+ /* 1 - Replace out of bound pixels with edge */
-+ REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1);
-+
-+ return true;
-+}
-+
-+static void program_overscan(
-+ struct dce_transform *xfm_dce,
-+ const struct scaler_data *data)
-+{
-+ int overscan_right = data->h_active
-+ - data->recout.x - data->recout.width;
-+ int overscan_bottom = data->v_active
-+ - data->recout.y - data->recout.height;
-+
-+ if (overscan_right < 0) {
-+ BREAK_TO_DEBUGGER();
-+ overscan_right = 0;
-+ }
-+ if (overscan_bottom < 0) {
-+ BREAK_TO_DEBUGGER();
-+ overscan_bottom = 0;
-+ }
-+
-+ REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0,
-+ EXT_OVERSCAN_LEFT, data->recout.x,
-+ EXT_OVERSCAN_RIGHT, overscan_right);
-+ REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0,
-+ EXT_OVERSCAN_TOP, data->recout.y,
-+ EXT_OVERSCAN_BOTTOM, overscan_bottom);
-+}
-+
-+static void program_multi_taps_filter(
-+ struct dce_transform *xfm_dce,
-+ int taps,
-+ const uint16_t *coeffs,
-+ enum ram_filter_type filter_type)
-+{
-+ int phase, pair;
-+ int array_idx = 0;
-+ int taps_pairs = (taps + 1) / 2;
-+ int phases_to_program = SCL_PHASES / 2 + 1;
-+
-+ uint32_t power_ctl = 0;
-+
-+ if (!coeffs)
-+ return;
-+
-+ /*We need to disable power gating on coeff memory to do programming*/
-+ if (REG(DCFE_MEM_PWR_CTRL)) {
-+ power_ctl = REG_READ(DCFE_MEM_PWR_CTRL);
-+ REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1);
-+
-+ REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10);
-+ }
-+ 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*/
-+ for (pair = 0; pair < taps_pairs; pair++) {
-+ uint16_t odd_coeff = 0;
-+ uint16_t even_coeff = coeffs[array_idx];
-+
-+ REG_SET_3(SCL_COEF_RAM_SELECT, 0,
-+ SCL_C_RAM_FILTER_TYPE, filter_type,
-+ SCL_C_RAM_PHASE, phase,
-+ SCL_C_RAM_TAP_PAIR_IDX, pair);
-+
-+ if (taps % 2 && pair == taps_pairs - 1)
-+ array_idx++;
-+ else {
-+ odd_coeff = coeffs[array_idx + 1];
-+ array_idx += 2;
-+ }
-+
-+ REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
-+ SCL_C_RAM_EVEN_TAP_COEF_EN, 1,
-+ SCL_C_RAM_EVEN_TAP_COEF, even_coeff,
-+ SCL_C_RAM_ODD_TAP_COEF_EN, 1,
-+ SCL_C_RAM_ODD_TAP_COEF, odd_coeff);
-+ }
-+ }
-+
-+ /*We need to restore power gating on coeff memory to initial state*/
-+ if (REG(DCFE_MEM_PWR_CTRL))
-+ REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl);
-+}
-+
-+static void program_viewport(
-+ struct dce_transform *xfm_dce,
-+ const struct rect *view_port)
-+{
-+ REG_SET_2(VIEWPORT_START, 0,
-+ VIEWPORT_X_START, view_port->x,
-+ VIEWPORT_Y_START, view_port->y);
-+
-+ REG_SET_2(VIEWPORT_SIZE, 0,
-+ VIEWPORT_HEIGHT, view_port->height,
-+ VIEWPORT_WIDTH, view_port->width);
-+
-+ /* TODO: add stereo support */
-+}
-+
-+static void calculate_inits(
-+ struct dce_transform *xfm_dce,
-+ const struct scaler_data *data,
-+ struct scl_ratios_inits *inits)
-+{
-+ struct fixed31_32 h_init;
-+ struct fixed31_32 v_init;
-+
-+ 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;
-+}
-+
-+static void program_scl_ratios_inits(
-+ struct dce_transform *xfm_dce,
-+ struct scl_ratios_inits *inits)
-+{
-+
-+ REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
-+ SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
-+
-+ REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
-+ SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
-+
-+ REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
-+ SCL_H_INIT_INT, inits->h_init.integer,
-+ SCL_H_INIT_FRAC, inits->h_init.fraction);
-+
-+ REG_SET_2(SCL_VERT_FILTER_INIT, 0,
-+ SCL_V_INIT_INT, inits->v_init.integer,
-+ SCL_V_INIT_FRAC, inits->v_init.fraction);
-+
-+ REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
-+}
-+
-+static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio)
-+{
-+ if (taps == 4)
-+ return get_filter_4tap_16p(ratio);
-+ else if (taps == 3)
-+ return get_filter_3tap_16p(ratio);
-+ else if (taps == 2)
-+ return filter_2tap_16p;
-+ else if (taps == 1)
-+ return NULL;
-+ else {
-+ /* should never happen, bug */
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+}
-+
-+static void dce_transform_set_scaler(
-+ struct transform *xfm,
-+ const struct scaler_data *data)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ bool is_scaling_required;
-+ bool filter_updated = false;
-+ const uint16_t *coeffs_v, *coeffs_h;
-+
-+ /*Use all three pieces of memory always*/
-+ REG_SET_2(LB_MEMORY_CTRL, 0,
-+ LB_MEMORY_CONFIG, 0,
-+ LB_MEMORY_SIZE, xfm_dce->lb_memory_size);
-+
-+ /* 1. Program overscan */
-+ program_overscan(xfm_dce, data);
-+
-+ /* 2. Program taps and configuration */
-+ is_scaling_required = setup_scaling_configuration(xfm_dce, data);
-+
-+ if (is_scaling_required) {
-+ /* 3. Calculate and program ratio, filter initialization */
-+ struct scl_ratios_inits inits = { 0 };
-+
-+ calculate_inits(xfm_dce, data, &inits);
-+
-+ program_scl_ratios_inits(xfm_dce, &inits);
-+
-+ coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
-+ coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
-+
-+ if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
-+ /* 4. Program vertical filters */
-+ if (xfm_dce->filter_v == NULL)
-+ REG_SET(SCL_VERT_FILTER_CONTROL, 0,
-+ SCL_V_2TAP_HARDCODE_COEF_EN, 0);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.v_taps,
-+ coeffs_v,
-+ FILTER_TYPE_RGB_Y_VERTICAL);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.v_taps,
-+ coeffs_v,
-+ FILTER_TYPE_ALPHA_VERTICAL);
-+
-+ /* 5. Program horizontal filters */
-+ if (xfm_dce->filter_h == NULL)
-+ REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
-+ SCL_H_2TAP_HARDCODE_COEF_EN, 0);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.h_taps,
-+ coeffs_h,
-+ FILTER_TYPE_RGB_Y_HORIZONTAL);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.h_taps,
-+ coeffs_h,
-+ FILTER_TYPE_ALPHA_HORIZONTAL);
-+
-+ xfm_dce->filter_v = coeffs_v;
-+ xfm_dce->filter_h = coeffs_h;
-+ filter_updated = true;
-+ }
-+ }
-+
-+ /* 6. Program the viewport */
-+ program_viewport(xfm_dce, &data->viewport);
-+
-+ /* 7. Set bit to flip to new coefficient memory */
-+ if (filter_updated)
-+ REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1);
-+
-+ REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en);
-+}
-+
-+/*****************************************************************************
-+ * set_clamp
-+ *
-+ * @param depth : bit depth to set the clamp to (should match denorm)
-+ *
-+ * @brief
-+ * Programs clamp according to panel bit depth.
-+ *
-+ *******************************************************************************/
-+static void set_clamp(
-+ struct dce_transform *xfm_dce,
-+ enum dc_color_depth depth)
-+{
-+ int 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:
-+ clamp_max = 0x3FC0;
-+ BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */
-+ }
-+ REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0,
-+ OUT_CLAMP_MIN_B_CB, 0,
-+ OUT_CLAMP_MAX_B_CB, clamp_max);
-+
-+ REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0,
-+ OUT_CLAMP_MIN_G_Y, 0,
-+ OUT_CLAMP_MAX_G_Y, clamp_max);
-+
-+ REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0,
-+ OUT_CLAMP_MIN_R_CR, 0,
-+ OUT_CLAMP_MAX_R_CR, clamp_max);
-+}
-+
-+/*******************************************************************************
-+ * 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
-+
-+ ******************************************************************************/
-+static void set_round(
-+ struct dce_transform *xfm_dce,
-+ enum dcp_out_trunc_round_mode mode,
-+ enum dcp_out_trunc_round_depth depth)
-+{
-+ int depth_bits = 0;
-+ int mode_bit = 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:
-+ depth_bits = 4;
-+ BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */
-+ }
-+
-+ /* 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:
-+ BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */
-+ }
-+
-+ depth_bits |= mode_bit << 3;
-+
-+ REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits);
-+}
-+
-+/*****************************************************************************
-+ * 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
-+ *
-+ ******************************************************************************/
-+
-+static void set_dither(
-+ struct dce_transform *xfm_dce,
-+ 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)
-+{
-+ int dither_depth_bits = 0;
-+ int dither_mode_bits = 0;
-+
-+ 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 */
-+ BREAK_TO_DEBUGGER();
-+ }
-+
-+ 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 */
-+ BREAK_TO_DEBUGGER();
-+ }
-+
-+ /* write the register */
-+ REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0,
-+ DCP_SPATIAL_DITHER_EN, dither_enable,
-+ DCP_SPATIAL_DITHER_MODE, dither_mode_bits,
-+ DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits,
-+ DCP_FRAME_RANDOM_ENABLE, frame_random_enable,
-+ DCP_RGB_RANDOM_ENABLE, rgb_random_enable,
-+ DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable);
-+}
-+
-+/*****************************************************************************
-+ * dce_transform_bit_depth_reduction_program
-+ *
-+ * @brief
-+ * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
-+ * Dither) for dce
-+ *
-+ * @param depth : bit depth to set the clamp to (should match denorm)
-+ *
-+ ******************************************************************************/
-+static void program_bit_depth_reduction(
-+ struct dce_transform *xfm_dce,
-+ 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;
-+
-+ ASSERT(depth < COLOR_DEPTH_121212); /* Invalid clamp bit depth */
-+
-+ 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;
-+
-+ set_clamp(xfm_dce, depth);
-+
-+ switch (depth_reduction_mode) {
-+ case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER:
-+ /* Spatial Dither: Set round/truncate to bypass (12bit),
-+ * enable Dither (30bpp) */
-+ set_round(xfm_dce,
-+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
-+ DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
-+
-+ set_dither(xfm_dce, 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(xfm_dce,
-+ DCP_OUT_TRUNC_ROUND_MODE_ROUND,
-+ DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
-+
-+ set_dither(xfm_dce, 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(xfm_dce,
-+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
-+ DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
-+
-+ set_dither(xfm_dce, 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(xfm_dce,
-+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
-+ DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
-+
-+ set_dither(xfm_dce, 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 */
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+}
-+
-+static int dce_transform_get_max_num_of_supported_lines(
-+ struct dce_transform *xfm_dce,
-+ enum lb_pixel_depth depth,
-+ int pixel_width)
-+{
-+ int pixels_per_entries = 0;
-+ int max_pixels_supports = 0;
-+
-+ ASSERT(pixel_width);
-+
-+ /* 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 = xfm_dce->lb_bits_per_entry / 18;
-+ break;
-+
-+ case LB_PIXEL_DEPTH_24BPP:
-+ pixels_per_entries = xfm_dce->lb_bits_per_entry / 24;
-+ break;
-+
-+ case LB_PIXEL_DEPTH_30BPP:
-+ pixels_per_entries = xfm_dce->lb_bits_per_entry / 30;
-+ break;
-+
-+ case LB_PIXEL_DEPTH_36BPP:
-+ pixels_per_entries = xfm_dce->lb_bits_per_entry / 36;
-+ break;
-+
-+ default:
-+ dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING,
-+ "%s: Invalid LB pixel depth",
-+ __func__);
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+
-+ ASSERT(pixels_per_entries);
-+
-+ max_pixels_supports =
-+ pixels_per_entries *
-+ xfm_dce->lb_memory_size;
-+
-+ return (max_pixels_supports / pixel_width);
-+}
-+
-+static void set_denormalization(
-+ struct dce_transform *xfm_dce,
-+ enum dc_color_depth depth)
-+{
-+ int denorm_mode = 0;
-+
-+ switch (depth) {
-+ case COLOR_DEPTH_666:
-+ /* 63/64 for 6 bit output color depth */
-+ denorm_mode = 1;
-+ break;
-+ case COLOR_DEPTH_888:
-+ /* Unity for 8 bit output color depth
-+ * because prescale is disabled by default */
-+ denorm_mode = 0;
-+ break;
-+ case COLOR_DEPTH_101010:
-+ /* 1023/1024 for 10 bit output color depth */
-+ denorm_mode = 3;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ /* 4095/4096 for 12 bit output color depth */
-+ denorm_mode = 5;
-+ break;
-+ case COLOR_DEPTH_141414:
-+ case COLOR_DEPTH_161616:
-+ default:
-+ /* not valid used case! */
-+ break;
-+ }
-+
-+ REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode);
-+}
-+
-+static void dce_transform_set_pixel_storage_depth(
-+ struct transform *xfm,
-+ enum lb_pixel_depth depth,
-+ const struct bit_depth_reduction_params *bit_depth_params)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ int pixel_depth, expan_mode;
-+ enum dc_color_depth color_depth;
-+
-+ switch (depth) {
-+ case LB_PIXEL_DEPTH_18BPP:
-+ color_depth = COLOR_DEPTH_666;
-+ pixel_depth = 2;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_24BPP:
-+ color_depth = COLOR_DEPTH_888;
-+ pixel_depth = 1;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_30BPP:
-+ color_depth = COLOR_DEPTH_101010;
-+ pixel_depth = 0;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_36BPP:
-+ color_depth = COLOR_DEPTH_121212;
-+ pixel_depth = 3;
-+ expan_mode = 0;
-+ break;
-+ default:
-+ color_depth = COLOR_DEPTH_101010;
-+ pixel_depth = 0;
-+ expan_mode = 1;
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+
-+ set_denormalization(xfm_dce, color_depth);
-+ program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
-+
-+ REG_UPDATE_2(LB_DATA_FORMAT,
-+ PIXEL_DEPTH, pixel_depth,
-+ PIXEL_EXPAN_MODE, expan_mode);
-+
-+ if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
-+ /*we should use unsupported capabilities
-+ * unless it is required by w/a*/
-+ dm_logger_write(xfm->ctx->logger, LOG_WARNING,
-+ "%s: Capability not supported",
-+ __func__);
-+ }
-+}
-+
-+static void program_gamut_remap(
-+ struct dce_transform *xfm_dce,
-+ const uint16_t *reg_val)
-+{
-+ if (reg_val) {
-+ REG_SET_2(GAMUT_REMAP_C11_C12, 0,
-+ GAMUT_REMAP_C11, reg_val[0],
-+ GAMUT_REMAP_C12, reg_val[1]);
-+ REG_SET_2(GAMUT_REMAP_C13_C14, 0,
-+ GAMUT_REMAP_C13, reg_val[2],
-+ GAMUT_REMAP_C14, reg_val[3]);
-+ REG_SET_2(GAMUT_REMAP_C21_C22, 0,
-+ GAMUT_REMAP_C21, reg_val[4],
-+ GAMUT_REMAP_C22, reg_val[5]);
-+ REG_SET_2(GAMUT_REMAP_C23_C24, 0,
-+ GAMUT_REMAP_C23, reg_val[6],
-+ GAMUT_REMAP_C24, reg_val[7]);
-+ REG_SET_2(GAMUT_REMAP_C31_C32, 0,
-+ GAMUT_REMAP_C31, reg_val[8],
-+ GAMUT_REMAP_C32, reg_val[9]);
-+ REG_SET_2(GAMUT_REMAP_C33_C34, 0,
-+ GAMUT_REMAP_C33, reg_val[10],
-+ GAMUT_REMAP_C34, reg_val[11]);
-+
-+ REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1);
-+ } else
-+ REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0);
-+
-+}
-+
-+/**
-+ *****************************************************************************
-+ * Function: dal_transform_wide_gamut_set_gamut_remap
-+ *
-+ * @param [in] const struct xfm_grph_csc_adjustment *adjust
-+ *
-+ * @return
-+ * void
-+ *
-+ * @note calculate and apply color temperature adjustment to in Rgb color space
-+ *
-+ * @see
-+ *
-+ *****************************************************************************
-+ */
-+static void dce_transform_set_gamut_remap(
-+ struct transform *xfm,
-+ const struct xfm_grph_csc_adjustment *adjust)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+
-+ if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
-+ /* Bypass if type is bypass or hw */
-+ program_gamut_remap(xfm_dce, NULL);
-+ else {
-+ struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
-+ uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
-+
-+ arr_matrix[0] = adjust->temperature_matrix[0];
-+ arr_matrix[1] = adjust->temperature_matrix[1];
-+ arr_matrix[2] = adjust->temperature_matrix[2];
-+ arr_matrix[3] = dal_fixed31_32_zero;
-+
-+ arr_matrix[4] = adjust->temperature_matrix[3];
-+ arr_matrix[5] = adjust->temperature_matrix[4];
-+ arr_matrix[6] = adjust->temperature_matrix[5];
-+ arr_matrix[7] = dal_fixed31_32_zero;
-+
-+ arr_matrix[8] = adjust->temperature_matrix[6];
-+ arr_matrix[9] = adjust->temperature_matrix[7];
-+ arr_matrix[10] = adjust->temperature_matrix[8];
-+ arr_matrix[11] = dal_fixed31_32_zero;
-+
-+ convert_float_matrix(
-+ arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
-+
-+ program_gamut_remap(xfm_dce, arr_reg_val);
-+ }
-+}
-+
-+static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma)
-+{
-+ uint32_t taps;
-+
-+ if (IDENTITY_RATIO(ratio)) {
-+ return 1;
-+ } else if (in_taps != 0) {
-+ taps = in_taps;
-+ } else {
-+ taps = 4;
-+ }
-+
-+ if (chroma) {
-+ taps /= 2;
-+ if (taps < 2)
-+ taps = 2;
-+ }
-+
-+ return taps;
-+}
-+
-+
-+bool dce_transform_get_optimal_number_of_taps(
-+ struct transform *xfm,
-+ struct scaler_data *scl_data,
-+ const struct scaling_taps *in_taps)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ int pixel_width = scl_data->viewport.width;
-+ int max_num_of_lines;
-+
-+ if (xfm_dce->prescaler_on &&
-+ (scl_data->viewport.width > scl_data->recout.width))
-+ pixel_width = scl_data->recout.width;
-+
-+ max_num_of_lines = dce_transform_get_max_num_of_supported_lines(
-+ xfm_dce,
-+ scl_data->lb_params.depth,
-+ pixel_width);
-+
-+ /* Fail if in_taps are impossible */
-+ if (in_taps->v_taps >= max_num_of_lines)
-+ return false;
-+
-+ /*
-+ * Set taps according to this policy (in this order)
-+ * - Use 1 for no scaling
-+ * - Use input taps
-+ * - Use 4 and reduce as required by line buffer size
-+ * - Decide chroma taps if chroma is scaled
-+ *
-+ * Ignore input chroma taps. Decide based on non-chroma
-+ */
-+ scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false);
-+ scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false);
-+ scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true);
-+ scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true);
-+
-+ if (!IDENTITY_RATIO(scl_data->ratios.vert)) {
-+ /* reduce v_taps if needed but ensure we have at least two */
-+ if (in_taps->v_taps == 0
-+ && max_num_of_lines <= scl_data->taps.v_taps
-+ && scl_data->taps.v_taps > 1) {
-+ scl_data->taps.v_taps = max_num_of_lines - 1;
-+ }
-+
-+ if (scl_data->taps.v_taps <= 1)
-+ return false;
-+ }
-+
-+ if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) {
-+ /* reduce chroma v_taps if needed but ensure we have at least two */
-+ if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) {
-+ scl_data->taps.v_taps_c = max_num_of_lines - 1;
-+ }
-+
-+ if (scl_data->taps.v_taps_c <= 1)
-+ return false;
-+ }
-+
-+ /* we've got valid taps */
-+ return true;
-+}
-+
-+static void dce_transform_reset(struct transform *xfm)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+
-+ xfm_dce->filter_h = NULL;
-+ xfm_dce->filter_v = NULL;
-+}
-+
-+
-+static const struct transform_funcs dce_transform_funcs = {
-+ .transform_reset = dce_transform_reset,
-+ .transform_set_scaler =
-+ dce_transform_set_scaler,
-+ .transform_set_gamut_remap =
-+ dce_transform_set_gamut_remap,
-+ .transform_set_pixel_storage_depth =
-+ dce_transform_set_pixel_storage_depth,
-+ .transform_get_optimal_number_of_taps =
-+ dce_transform_get_optimal_number_of_taps
-+};
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce_transform_construct(
-+ struct dce_transform *xfm_dce,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce_transform_registers *regs,
-+ const struct dce_transform_shift *xfm_shift,
-+ const struct dce_transform_mask *xfm_mask)
-+{
-+ xfm_dce->base.ctx = ctx;
-+
-+ xfm_dce->base.inst = inst;
-+ xfm_dce->base.funcs = &dce_transform_funcs;
-+
-+ xfm_dce->regs = regs;
-+ xfm_dce->xfm_shift = xfm_shift;
-+ xfm_dce->xfm_mask = xfm_mask;
-+
-+ xfm_dce->prescaler_on = true;
-+ xfm_dce->lb_pixel_depth_supported =
-+ LB_PIXEL_DEPTH_18BPP |
-+ LB_PIXEL_DEPTH_24BPP |
-+ LB_PIXEL_DEPTH_30BPP;
-+
-+ xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
-+ xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
-new file mode 100644
-index 0000000..897645e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h
-@@ -0,0 +1,313 @@
-+/*
-+ * 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 _DCE_DCE_TRANSFORM_H_
-+#define _DCE_DCE_TRANSFORM_H_
-+
-+
-+#include "transform.h"
-+
-+#define TO_DCE_TRANSFORM(transform)\
-+ container_of(transform, struct dce_transform, base)
-+
-+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
-+#define LB_BITS_PER_ENTRY 144
-+
-+#define XFM_COMMON_REG_LIST_DCE_BASE(id) \
-+ SRI(LB_DATA_FORMAT, LB, id), \
-+ SRI(GAMUT_REMAP_CONTROL, DCP, id), \
-+ SRI(GAMUT_REMAP_C11_C12, DCP, id), \
-+ SRI(GAMUT_REMAP_C13_C14, DCP, id), \
-+ SRI(GAMUT_REMAP_C21_C22, DCP, id), \
-+ SRI(GAMUT_REMAP_C23_C24, DCP, id), \
-+ SRI(GAMUT_REMAP_C31_C32, DCP, id), \
-+ SRI(GAMUT_REMAP_C33_C34, DCP, id), \
-+ SRI(DENORM_CONTROL, DCP, id), \
-+ SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \
-+ SRI(OUT_ROUND_CONTROL, DCP, id), \
-+ SRI(OUT_CLAMP_CONTROL_R_CR, DCP, id), \
-+ SRI(OUT_CLAMP_CONTROL_G_Y, DCP, id), \
-+ SRI(OUT_CLAMP_CONTROL_B_CB, DCP, id), \
-+ SRI(SCL_MODE, SCL, id), \
-+ SRI(SCL_TAP_CONTROL, SCL, id), \
-+ SRI(SCL_CONTROL, SCL, id), \
-+ SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \
-+ SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \
-+ SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \
-+ SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \
-+ SRI(SCL_COEF_RAM_SELECT, SCL, id), \
-+ SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \
-+ SRI(VIEWPORT_START, SCL, id), \
-+ SRI(VIEWPORT_SIZE, SCL, id), \
-+ SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \
-+ SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \
-+ SRI(SCL_HORZ_FILTER_INIT, SCL, id), \
-+ SRI(SCL_VERT_FILTER_INIT, SCL, id), \
-+ SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \
-+ SRI(LB_MEMORY_CTRL, LB, id), \
-+ SRI(SCL_UPDATE, SCL, id)
-+
-+#define XFM_COMMON_REG_LIST_DCE100(id) \
-+ XFM_COMMON_REG_LIST_DCE_BASE(id), \
-+ SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \
-+ SRI(DCFE_MEM_PWR_STATUS, CRTC, id)
-+
-+#define XFM_COMMON_REG_LIST_DCE110(id) \
-+ XFM_COMMON_REG_LIST_DCE_BASE(id), \
-+ SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \
-+ SRI(DCFE_MEM_PWR_STATUS, DCFE, id)
-+
-+#define XFM_SF(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+#define XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
-+ XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \
-+ XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \
-+ XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \
-+ XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \
-+ XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \
-+ XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \
-+ XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \
-+ XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \
-+ XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \
-+ XFM_SF(LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \
-+ XFM_SF(LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \
-+ XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \
-+ XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \
-+ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
-+ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
-+ XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \
-+ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \
-+ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \
-+ XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \
-+ XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \
-+ XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \
-+ XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \
-+ XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \
-+ XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \
-+ XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \
-+ XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \
-+ XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \
-+ XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \
-+ XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \
-+ XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \
-+ XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \
-+ XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \
-+ XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \
-+ XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \
-+ XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \
-+ XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \
-+ XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh)
-+
-+#define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \
-+ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
-+ XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \
-+ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \
-+ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh)
-+
-+#define XFM_REG_FIELD_LIST(type) \
-+ type OUT_CLAMP_MIN_B_CB; \
-+ type OUT_CLAMP_MAX_B_CB; \
-+ type OUT_CLAMP_MIN_G_Y; \
-+ type OUT_CLAMP_MAX_G_Y; \
-+ type OUT_CLAMP_MIN_R_CR; \
-+ type OUT_CLAMP_MAX_R_CR; \
-+ type OUT_ROUND_TRUNC_MODE; \
-+ type DCP_SPATIAL_DITHER_EN; \
-+ type DCP_SPATIAL_DITHER_MODE; \
-+ type DCP_SPATIAL_DITHER_DEPTH; \
-+ type DCP_FRAME_RANDOM_ENABLE; \
-+ type DCP_RGB_RANDOM_ENABLE; \
-+ type DCP_HIGHPASS_RANDOM_ENABLE; \
-+ type DENORM_MODE; \
-+ type PIXEL_DEPTH; \
-+ type PIXEL_EXPAN_MODE; \
-+ type GAMUT_REMAP_C11; \
-+ type GAMUT_REMAP_C12; \
-+ type GAMUT_REMAP_C13; \
-+ type GAMUT_REMAP_C14; \
-+ type GAMUT_REMAP_C21; \
-+ type GAMUT_REMAP_C22; \
-+ type GAMUT_REMAP_C23; \
-+ type GAMUT_REMAP_C24; \
-+ type GAMUT_REMAP_C31; \
-+ type GAMUT_REMAP_C32; \
-+ type GAMUT_REMAP_C33; \
-+ type GAMUT_REMAP_C34; \
-+ type GRPH_GAMUT_REMAP_MODE; \
-+ type SCL_MODE; \
-+ type SCL_PSCL_EN; \
-+ type SCL_H_NUM_OF_TAPS; \
-+ type SCL_V_NUM_OF_TAPS; \
-+ type SCL_BOUNDARY_MODE; \
-+ type EXT_OVERSCAN_LEFT; \
-+ type EXT_OVERSCAN_RIGHT; \
-+ type EXT_OVERSCAN_TOP; \
-+ type EXT_OVERSCAN_BOTTOM; \
-+ type SCL_COEFF_MEM_PWR_DIS; \
-+ type SCL_COEFF_MEM_PWR_STATE; \
-+ type SCL_C_RAM_FILTER_TYPE; \
-+ type SCL_C_RAM_PHASE; \
-+ type SCL_C_RAM_TAP_PAIR_IDX; \
-+ type SCL_C_RAM_EVEN_TAP_COEF_EN; \
-+ type SCL_C_RAM_EVEN_TAP_COEF; \
-+ type SCL_C_RAM_ODD_TAP_COEF_EN; \
-+ type SCL_C_RAM_ODD_TAP_COEF; \
-+ type VIEWPORT_X_START; \
-+ type VIEWPORT_Y_START; \
-+ type VIEWPORT_HEIGHT; \
-+ type VIEWPORT_WIDTH; \
-+ type SCL_H_SCALE_RATIO; \
-+ type SCL_V_SCALE_RATIO; \
-+ type SCL_H_INIT_INT; \
-+ type SCL_H_INIT_FRAC; \
-+ type SCL_V_INIT_INT; \
-+ type SCL_V_INIT_FRAC; \
-+ type LB_MEMORY_CONFIG; \
-+ type LB_MEMORY_SIZE; \
-+ type SCL_V_2TAP_HARDCODE_COEF_EN; \
-+ type SCL_H_2TAP_HARDCODE_COEF_EN; \
-+ type SCL_COEF_UPDATE_COMPLETE; \
-+ type ALPHA_EN
-+
-+struct dce_transform_shift {
-+ XFM_REG_FIELD_LIST(uint8_t);
-+};
-+
-+struct dce_transform_mask {
-+ XFM_REG_FIELD_LIST(uint32_t);
-+};
-+
-+struct dce_transform_registers {
-+ uint32_t LB_DATA_FORMAT;
-+ uint32_t GAMUT_REMAP_CONTROL;
-+ uint32_t GAMUT_REMAP_C11_C12;
-+ uint32_t GAMUT_REMAP_C13_C14;
-+ uint32_t GAMUT_REMAP_C21_C22;
-+ uint32_t GAMUT_REMAP_C23_C24;
-+ uint32_t GAMUT_REMAP_C31_C32;
-+ uint32_t GAMUT_REMAP_C33_C34;
-+ uint32_t DENORM_CONTROL;
-+ uint32_t DCP_SPATIAL_DITHER_CNTL;
-+ uint32_t OUT_ROUND_CONTROL;
-+ uint32_t OUT_CLAMP_CONTROL_R_CR;
-+ uint32_t OUT_CLAMP_CONTROL_G_Y;
-+ uint32_t OUT_CLAMP_CONTROL_B_CB;
-+ uint32_t SCL_MODE;
-+ uint32_t SCL_TAP_CONTROL;
-+ uint32_t SCL_CONTROL;
-+ uint32_t EXT_OVERSCAN_LEFT_RIGHT;
-+ uint32_t EXT_OVERSCAN_TOP_BOTTOM;
-+ uint32_t SCL_VERT_FILTER_CONTROL;
-+ uint32_t SCL_HORZ_FILTER_CONTROL;
-+ uint32_t DCFE_MEM_PWR_CTRL;
-+ uint32_t DCFE_MEM_PWR_STATUS;
-+ uint32_t SCL_COEF_RAM_SELECT;
-+ uint32_t SCL_COEF_RAM_TAP_DATA;
-+ uint32_t VIEWPORT_START;
-+ uint32_t VIEWPORT_SIZE;
-+ uint32_t SCL_HORZ_FILTER_SCALE_RATIO;
-+ uint32_t SCL_VERT_FILTER_SCALE_RATIO;
-+ uint32_t SCL_HORZ_FILTER_INIT;
-+ uint32_t SCL_VERT_FILTER_INIT;
-+ uint32_t SCL_AUTOMATIC_MODE_CONTROL;
-+ uint32_t LB_MEMORY_CTRL;
-+ uint32_t SCL_UPDATE;
-+};
-+
-+struct init_int_and_frac {
-+ uint32_t integer;
-+ uint32_t fraction;
-+};
-+
-+struct scl_ratios_inits {
-+ 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;
-+};
-+
-+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. */
-+};
-+
-+struct dce_transform {
-+ struct transform base;
-+ const struct dce_transform_registers *regs;
-+ const struct dce_transform_shift *xfm_shift;
-+ const struct dce_transform_mask *xfm_mask;
-+
-+ const uint16_t *filter_v;
-+ const uint16_t *filter_h;
-+ const uint16_t *filter_v_c;
-+ const uint16_t *filter_h_c;
-+ int lb_pixel_depth_supported;
-+ int lb_memory_size;
-+ int lb_bits_per_entry;
-+ bool prescaler_on;
-+};
-+
-+bool dce_transform_construct(struct dce_transform *xfm110,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce_transform_registers *regs,
-+ const struct dce_transform_shift *xfm_shift,
-+ const struct dce_transform_mask *xfm_mask);
-+
-+bool dce_transform_get_optimal_number_of_taps(
-+ struct transform *xfm,
-+ struct scaler_data *scl_data,
-+ const struct scaling_taps *in_taps);
-+
-+
-+#endif /* _DCE_DCE_TRANSFORM_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile
-new file mode 100644
-index 0000000..ea40870
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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_DISPLAY_FILES += $(AMD_DAL_DCE100)
-+
-+
-+###############################################################################
-+# DCE 10x
-+###############################################################################
-+ifdef 0#CONFIG_DRM_AMD_DC_DCE11_0
-+TG_DCE100 = dce100_resource.o
-+
-+AMD_DAL_TG_DCE100 = $(addprefix \
-+ $(AMDDALPATH)/dc/dce100/,$(TG_DCE100))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_TG_DCE100)
-+endif
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
-new file mode 100644
-index 0000000..e2fe024
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
-@@ -0,0 +1,140 @@
-+/*
-+ * 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;
-+};
-+
-+static const struct dce100_hw_seq_reg_offsets reg_offsets[] = {
-+{
-+ .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+}
-+};
-+
-+#define HW_REG_CRTC(reg, id)\
-+ (reg + reg_offsets[id].crtc)
-+
-+/*******************************************************************************
-+ * Private definitions
-+ ******************************************************************************/
-+/***************************PIPE_CONTROL***********************************/
-+
-+static bool dce100_enable_display_power_gating(
-+ struct core_dc *dc,
-+ 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;
-+ struct dc_context *ctx = dc->ctx;
-+
-+ 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);
-+
-+ /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
-+ * by default when command table is called
-+ */
-+ dm_write_reg(ctx,
-+ HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id),
-+ 0);
-+ }
-+
-+ if (bp_result == BP_RESULT_OK)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+static void set_display_mark_for_pipe_if_needed(struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+static void set_displaymarks(
-+ const struct core_dc *dc, struct validate_context *context)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+static void set_bandwidth(struct core_dc *dc)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+
-+/**************************************************************************/
-+
-+bool dce100_hw_sequencer_construct(struct core_dc *dc)
-+{
-+ dce110_hw_sequencer_construct(dc);
-+
-+ /* TODO: dce80 is empty implementation at the moment*/
-+ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
-+ dc->hwss.set_displaymarks = set_displaymarks;
-+ dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed;
-+ dc->hwss.set_bandwidth = set_bandwidth;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h
-new file mode 100644
-index 0000000..cf497ea
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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 core_dc;
-+
-+bool dce100_hw_sequencer_construct(struct core_dc *dc);
-+
-+#endif /* __DC_HWSS_DCE100_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
-new file mode 100644
-index 0000000..16595dc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
-@@ -0,0 +1,1085 @@
-+/*
-+* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "irq/dce110/irq_service_dce110.h"
-+#include "dce/dce_link_encoder.h"
-+#include "dce/dce_stream_encoder.h"
-+#include "dce110/dce110_mem_input.h"
-+#include "dce110/dce110_mem_input_v.h"
-+#include "dce110/dce110_ipp.h"
-+#include "dce/dce_transform.h"
-+#include "dce110/dce110_opp.h"
-+#include "dce/dce_clock_source.h"
-+#include "dce/dce_audio.h"
-+#include "dce/dce_hwseq.h"
-+#include "dce100/dce100_hw_sequencer.h"
-+
-+#include "reg_helper.h"
-+
-+#include "dce/dce_10_0_d.h"
-+#include "dce/dce_10_0_sh_mask.h"
-+
-+#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
-+#include "gmc/gmc_8_2_d.h"
-+#include "gmc/gmc_8_2_sh_mask.h"
-+#endif
-+
-+#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
-+
-+#ifndef mmBIOS_SCRATCH_2
-+ #define mmBIOS_SCRATCH_2 0x05CB
-+ #define mmBIOS_SCRATCH_6 0x05CF
-+#endif
-+
-+#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
-+ #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC
-+ #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC
-+ #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC
-+ #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC
-+ #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC
-+ #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC
-+#endif
-+
-+#ifndef mmDP_DPHY_FAST_TRAINING
-+ #define mmDP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
-+ #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
-+ #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
-+ #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
-+ #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
-+ #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
-+#endif
-+
-+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_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),
-+}
-+};
-+
-+
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+
-+#define transform_regs(id)\
-+[id] = {\
-+ XFM_COMMON_REG_LIST_DCE100(id)\
-+}
-+
-+static const struct dce_transform_registers xfm_regs[] = {
-+ transform_regs(0),
-+ transform_regs(1),
-+ transform_regs(2),
-+ transform_regs(3),
-+ transform_regs(4),
-+ transform_regs(5)
-+};
-+
-+static const struct dce_transform_shift xfm_shift = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce_transform_mask xfm_mask = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_REG_LIST(id)\
-+}
-+
-+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 hpd_regs(id)\
-+[id] = {\
-+ HPD_REG_LIST(id)\
-+}
-+
-+static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
-+ hpd_regs(0),
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5)
-+};
-+
-+#define link_regs(id)\
-+[id] = {\
-+ LE_DCE110_REG_LIST(id)\
-+}
-+
-+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] = {\
-+ SE_COMMON_REG_LIST_DCE_BASE(id),\
-+ .AFMT_CNTL = 0,\
-+}
-+
-+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)
-+};
-+
-+static const struct dce_stream_encoder_shift se_shift = {
-+ SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT)
-+};
-+
-+static const struct dce_stream_encoder_mask se_mask = {
-+ SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK)
-+};
-+
-+#define audio_regs(id)\
-+[id] = {\
-+ AUD_COMMON_REG_LIST(id)\
-+}
-+
-+static const struct dce_audio_registers audio_regs[] = {
-+ audio_regs(0),
-+ audio_regs(1),
-+ audio_regs(2),
-+ audio_regs(3),
-+ audio_regs(4),
-+ audio_regs(5),
-+ audio_regs(6),
-+};
-+
-+static const struct dce_audio_shift audio_shift = {
-+ AUD_COMMON_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_aduio_mask audio_mask = {
-+ AUD_COMMON_MASK_SH_LIST(_MASK)
-+};
-+
-+#define clk_src_regs(id)\
-+[id] = {\
-+ CS_COMMON_REG_LIST_DCE_100_110(id),\
-+}
-+
-+static const struct dce110_clk_src_regs clk_src_regs[] = {
-+ clk_src_regs(0),
-+ clk_src_regs(1),
-+ clk_src_regs(2)
-+};
-+
-+static const struct dce110_clk_src_shift cs_shift = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
-+};
-+
-+static const struct dce110_clk_src_mask cs_mask = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
-+};
-+
-+
-+
-+#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 const struct bios_registers bios_regs = {
-+ .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
-+};
-+
-+static const struct resource_caps res_cap = {
-+ .num_timing_generator = 6,
-+ .num_audio = 6,
-+ .num_stream_encoder = 6,
-+ .num_pll = 3
-+};
-+
-+#define CTX ctx
-+#define REG(reg) mm ## reg
-+
-+#ifndef mmCC_DC_HDMI_STRAPS
-+#define mmCC_DC_HDMI_STRAPS 0x1918
-+#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 void read_dce_straps(
-+ struct dc_context *ctx,
-+ struct resource_straps *straps)
-+{
-+ REG_GET_2(CC_DC_HDMI_STRAPS,
-+ HDMI_DISABLE, &straps->hdmi_disable,
-+ AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
-+
-+ REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
-+}
-+
-+static struct audio *create_audio(
-+ struct dc_context *ctx, unsigned int inst)
-+{
-+ return dce_audio_create(ctx, inst,
-+ &audio_regs[inst], &audio_shift, &audio_mask);
-+}
-+
-+static struct timing_generator *dce100_timing_generator_create(
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ struct dce110_timing_generator *tg110 =
-+ dm_alloc(sizeof(struct dce110_timing_generator));
-+
-+ if (!tg110)
-+ return NULL;
-+
-+ if (dce110_timing_generator_construct(tg110, ctx, instance,
-+ offsets))
-+ return &tg110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(tg110);
-+ return NULL;
-+}
-+
-+static struct stream_encoder *dce100_stream_encoder_create(
-+ enum engine_id eng_id,
-+ struct dc_context *ctx)
-+{
-+ struct dce110_stream_encoder *enc110 =
-+ dm_alloc(sizeof(struct dce110_stream_encoder));
-+
-+ if (!enc110)
-+ return NULL;
-+
-+ if (dce110_stream_encoder_construct(
-+ enc110, ctx, ctx->dc_bios, eng_id,
-+ &stream_enc_regs[eng_id], &se_shift, &se_mask))
-+ return &enc110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+#define SRII(reg_name, block, id)\
-+ .reg_name[id] = mm ## block ## id ## _ ## reg_name
-+
-+static const struct dce_hwseq_registers hwseq_reg = {
-+ HWSEQ_DCE10_REG_LIST()
-+};
-+
-+static const struct dce_hwseq_shift hwseq_shift = {
-+ HWSEQ_DCE10_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_hwseq_mask hwseq_mask = {
-+ HWSEQ_DCE10_MASK_SH_LIST(_MASK)
-+};
-+
-+static struct dce_hwseq *dce100_hwseq_create(
-+ struct dc_context *ctx)
-+{
-+ struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
-+
-+ if (hws) {
-+ hws->ctx = ctx;
-+ hws->regs = &hwseq_reg;
-+ hws->shifts = &hwseq_shift;
-+ hws->masks = &hwseq_mask;
-+ }
-+ return hws;
-+}
-+
-+static const struct resource_create_funcs res_create_funcs = {
-+ .read_dce_straps = read_dce_straps,
-+ .create_audio = create_audio,
-+ .create_stream_encoder = dce100_stream_encoder_create,
-+ .create_hwseq = dce100_hwseq_create,
-+};
-+
-+#define mi_inst_regs(id) { \
-+ MI_REG_LIST(id), \
-+ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
-+}
-+static const struct dce_mem_input_registers mi_regs[] = {
-+ mi_inst_regs(0),
-+ mi_inst_regs(1),
-+ mi_inst_regs(2),
-+ mi_inst_regs(3),
-+ mi_inst_regs(4),
-+ mi_inst_regs(5),
-+};
-+
-+static const struct dce_mem_input_shift mi_shifts = {
-+ MI_DCE_MASK_SH_LIST(__SHIFT),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
-+};
-+
-+static const struct dce_mem_input_mask mi_masks = {
-+ MI_DCE_MASK_SH_LIST(_MASK),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
-+};
-+
-+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(sizeof(struct dce110_mem_input));
-+
-+ if (!mem_input110)
-+ return NULL;
-+
-+ if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) {
-+ struct mem_input *mi = &mem_input110->base;
-+
-+ mi->regs = &mi_regs[inst];
-+ mi->shifts = &mi_shifts;
-+ mi->masks = &mi_masks;
-+ mi->wa.single_head_rdreq_dmif_limit = 2;
-+ return mi;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(mem_input110);
-+ return NULL;
-+}
-+
-+static void dce100_transform_destroy(struct transform **xfm)
-+{
-+ dm_free(TO_DCE_TRANSFORM(*xfm));
-+ *xfm = NULL;
-+}
-+
-+static struct transform *dce100_transform_create(
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ struct dce_transform *transform =
-+ dm_alloc(sizeof(struct dce_transform));
-+
-+ if (!transform)
-+ return NULL;
-+
-+ if (dce_transform_construct(transform, ctx, inst,
-+ &xfm_regs[inst], &xfm_shift, &xfm_mask)) {
-+ return &transform->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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(sizeof(struct dce110_ipp));
-+
-+ if (!ipp)
-+ return NULL;
-+
-+ if (dce110_ipp_construct(ipp, ctx, inst, offsets))
-+ return &ipp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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(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_hpd_regs[enc_init_data->hpd_source])) {
-+
-+ enc110->base.features.ycbcr420_supported = false;
-+ enc110->base.features.max_hdmi_pixel_clock = 300000;
-+ return &enc110->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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(sizeof(struct dce110_opp));
-+
-+ if (!opp)
-+ return NULL;
-+
-+ if (dce110_opp_construct(opp,
-+ ctx, inst, offset))
-+ return &opp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(opp);
-+ return NULL;
-+}
-+
-+void dce100_opp_destroy(struct output_pixel_processor **opp)
-+{
-+ struct dce110_opp *dce110_opp;
-+
-+ if (!opp || !*opp)
-+ return;
-+
-+ dce110_opp = FROM_DCE11_OPP(*opp);
-+
-+ dm_free(dce110_opp->regamma.coeff128_dx);
-+ dm_free(dce110_opp->regamma.coeff128_oem);
-+ dm_free(dce110_opp->regamma.coeff128);
-+ dm_free(dce110_opp->regamma.axis_x_1025);
-+ dm_free(dce110_opp->regamma.axis_x_256);
-+ dm_free(dce110_opp->regamma.coordinates_x);
-+ dm_free(dce110_opp->regamma.rgb_regamma);
-+ dm_free(dce110_opp->regamma.rgb_resulted);
-+ dm_free(dce110_opp->regamma.rgb_oem);
-+ dm_free(dce110_opp->regamma.rgb_user);
-+ dm_free(dce110_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_regs *regs,
-+ bool dp_clk_src)
-+{
-+ struct dce110_clk_src *clk_src =
-+ dm_alloc(sizeof(struct dce110_clk_src));
-+
-+ if (!clk_src)
-+ return NULL;
-+
-+ if (dce110_clk_src_construct(clk_src, ctx, bios, id,
-+ regs, &cs_shift, &cs_mask)) {
-+ clk_src->base.dp_clk_src = dp_clk_src;
-+ return &clk_src->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-+void dce100_clock_source_destroy(struct clock_source **clk_src)
-+{
-+ dm_free(TO_DCE110_CLK_SRC(*clk_src));
-+ *clk_src = NULL;
-+}
-+
-+static void destruct(struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ if (pool->base.opps[i] != NULL)
-+ dce100_opp_destroy(&pool->base.opps[i]);
-+
-+ if (pool->base.transforms[i] != NULL)
-+ dce100_transform_destroy(&pool->base.transforms[i]);
-+
-+ if (pool->base.ipps[i] != NULL)
-+ dce110_ipp_destroy(&pool->base.ipps[i]);
-+
-+ if (pool->base.mis[i] != NULL) {
-+ dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
-+ pool->base.mis[i] = NULL;
-+ }
-+
-+ if (pool->base.timing_generators[i] != NULL) {
-+ dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
-+ pool->base.timing_generators[i] = NULL;
-+ }
-+ }
-+
-+ for (i = 0; i < pool->base.stream_enc_count; i++) {
-+ if (pool->base.stream_enc[i] != NULL)
-+ dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] != NULL)
-+ dce100_clock_source_destroy(&pool->base.clock_sources[i]);
-+ }
-+
-+ if (pool->base.dp_clock_source != NULL)
-+ dce100_clock_source_destroy(&pool->base.dp_clock_source);
-+
-+ for (i = 0; i < pool->base.audio_count; i++) {
-+ if (pool->base.audios[i] != NULL)
-+ dce_aud_destroy(&pool->base.audios[i]);
-+ }
-+
-+ if (pool->base.display_clock != NULL)
-+ dal_display_clock_destroy(&pool->base.display_clock);
-+
-+ if (pool->base.irqs != NULL)
-+ dal_irq_service_destroy(&pool->base.irqs);
-+}
-+
-+static enum dc_status validate_mapped_resource(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status status = DC_OK;
-+ uint8_t i, j, k;
-+
-+ 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 core_link *link = stream->sink->link;
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (!pipe_ctx->tg->funcs->validate_timing(
-+ pipe_ctx->tg, &stream->public.timing))
-+ return DC_FAIL_CONTROLLER_VALIDATE;
-+
-+ status = dce110_resource_build_pipe_hw_param(pipe_ctx);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ if (!link->link_enc->funcs->validate_output_with_stream(
-+ link->link_enc,
-+ pipe_ctx))
-+ return DC_FAIL_ENC_VALIDATE;
-+
-+ /* TODO: validate audio ASIC caps, encoder */
-+ status = dc_link_validate_mode_timing(stream,
-+ link,
-+ &stream->public.timing);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ resource_build_info_frame(pipe_ctx);
-+
-+ /* do not need to validate non root pipes */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+enum dc_status dce100_validate_bandwidth(
-+ const struct core_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 bool dce100_validate_surface_sets(
-+ const struct dc_validation_set set[],
-+ int set_count)
-+{
-+ int i;
-+
-+ for (i = 0; i < set_count; i++) {
-+ if (set[i].surface_count == 0)
-+ continue;
-+
-+ if (set[i].surface_count > 1)
-+ return false;
-+
-+ if (set[i].surfaces[0]->clip_rect.width
-+ != set[i].target->streams[0]->src.width
-+ || set[i].surfaces[0]->clip_rect.height
-+ != set[i].target->streams[0]->src.height)
-+ return false;
-+ if (set[i].surfaces[0]->format
-+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+enum dc_status dce100_validate_with_context(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context)
-+{
-+ struct dc_context *dc_ctx = dc->ctx;
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ int i;
-+
-+ if (!dce100_validate_surface_sets(set, set_count))
-+ return DC_FAIL_SURFACE_VALIDATE;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ for (i = 0; i < set_count; i++) {
-+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
-+ dc_target_retain(&context->targets[i]->public);
-+ context->target_count++;
-+ }
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (!resource_validate_attach_surfaces(
-+ set, set_count, dc->current_context, context)) {
-+ DC_ERROR("Failed to attach surface to target!\n");
-+ return DC_FAIL_ATTACH_SURFACES;
-+ }
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_build_scaling_params_for_context(dc, context);
-+
-+ if (result == DC_OK)
-+ result = dce100_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+enum dc_status dce100_validate_guaranteed(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ context->targets[0] = DC_TARGET_TO_CORE(dc_target);
-+ dc_target_retain(&context->targets[0]->public);
-+ context->target_count++;
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK) {
-+ validate_guaranteed_copy_target(
-+ context, dc->public.caps.max_targets);
-+ result = resource_build_scaling_params_for_context(dc, context);
-+ }
-+
-+ if (result == DC_OK)
-+ result = dce100_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+static void dce100_destroy_resource_pool(struct resource_pool **pool)
-+{
-+ struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
-+
-+ destruct(dce110_pool);
-+ dm_free(dce110_pool);
-+ *pool = NULL;
-+}
-+
-+static const struct resource_funcs dce100_res_pool_funcs = {
-+ .destroy = dce100_destroy_resource_pool,
-+ .link_enc_create = dce100_link_encoder_create,
-+ .validate_with_context = dce100_validate_with_context,
-+ .validate_guaranteed = dce100_validate_guaranteed,
-+ .validate_bandwidth = dce100_validate_bandwidth
-+};
-+
-+static bool construct(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+ struct dc_context *ctx = dc->ctx;
-+ struct firmware_info info;
-+ struct dc_bios *bp;
-+ struct dm_pp_static_clock_info static_clk_info = {0};
-+
-+ ctx->dc_bios->regs = &bios_regs;
-+
-+ pool->base.res_cap = &res_cap;
-+ pool->base.funcs = &dce100_res_pool_funcs;
-+ pool->base.underlay_pipe_index = -1;
-+
-+ bp = ctx->dc_bios;
-+
-+ if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
-+ info.external_clock_source_frequency_for_dp != 0) {
-+ pool->base.dp_clock_source =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
-+
-+ pool->base.clock_sources[0] =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
-+ pool->base.clock_sources[1] =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
-+ pool->base.clock_sources[2] =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
-+ pool->base.clk_src_count = 3;
-+
-+ } else {
-+ pool->base.dp_clock_source =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
-+
-+ pool->base.clock_sources[0] =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
-+ pool->base.clock_sources[1] =
-+ dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
-+ pool->base.clk_src_count = 2;
-+ }
-+
-+ if (pool->base.dp_clock_source == NULL) {
-+ dm_error("DC: failed to create dp clock source!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] == NULL) {
-+ dm_error("DC: failed to create clock sources!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ pool->base.display_clock = dal_display_clock_dce110_create(ctx);
-+ if (pool->base.display_clock == NULL) {
-+ dm_error("DC: failed to create display clock!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+
-+ /* get static clock information for PPLIB or firmware, save
-+ * max_clock_state
-+ */
-+ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) {
-+ enum clocks_state max_clocks_state =
-+ dce110_resource_convert_clock_state_pp_to_dc(
-+ static_clk_info.max_clocks_state);
-+
-+ dal_display_clock_store_max_clocks_state(
-+ pool->base.display_clock, max_clocks_state);
-+ }
-+ {
-+ struct irq_service_init_data init_data;
-+ init_data.ctx = dc->ctx;
-+ pool->base.irqs = dal_irq_service_dce110_create(&init_data);
-+ if (!pool->base.irqs)
-+ goto res_create_fail;
-+ }
-+
-+ /*************************************************
-+ * Resource + asic cap harcoding *
-+ *************************************************/
-+ pool->base.underlay_pipe_index = -1;
-+ pool->base.pipe_count = res_cap.num_timing_generator;
-+ dc->public.caps.max_downscale_ratio = 200;
-+ dc->public.caps.i2c_speed_in_khz = 40;
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ pool->base.timing_generators[i] =
-+ dce100_timing_generator_create(
-+ ctx,
-+ i,
-+ &dce100_tg_offsets[i]);
-+ if (pool->base.timing_generators[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create tg!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.mis[i] = dce100_mem_input_create(ctx, i,
-+ &dce100_mi_reg_offsets[i]);
-+ if (pool->base.mis[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create memory input!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.ipps[i] = dce100_ipp_create(ctx, i,
-+ &dce100_ipp_reg_offsets[i]);
-+ if (pool->base.ipps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create input pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.transforms[i] = dce100_transform_create(ctx, i);
-+ if (pool->base.transforms[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create transform!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]);
-+ if (pool->base.opps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create output pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ if (!resource_construct(num_virtual_links, dc, &pool->base,
-+ &res_create_funcs))
-+ goto res_create_fail;
-+
-+ /* Create hardware sequencer */
-+ if (!dce100_hw_sequencer_construct(dc))
-+ goto res_create_fail;
-+
-+ return true;
-+
-+res_create_fail:
-+ destruct(pool);
-+
-+ return false;
-+}
-+
-+struct resource_pool *dce100_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc)
-+{
-+ struct dce110_resource_pool *pool =
-+ dm_alloc(sizeof(struct dce110_resource_pool));
-+
-+ if (!pool)
-+ return NULL;
-+
-+ if (construct(num_virtual_links, dc, pool))
-+ return &pool->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h
-new file mode 100644
-index 0000000..bfd7518
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h
-@@ -0,0 +1,19 @@
-+/*
-+ * dce100_resource.h
-+ *
-+ * Created on: 2016-01-20
-+ * Author: qyang
-+ */
-+
-+#ifndef DCE100_RESOURCE_H_
-+#define DCE100_RESOURCE_H_
-+
-+struct core_dc;
-+struct resource_pool;
-+struct dc_validation_set;
-+
-+struct resource_pool *dce100_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc);
-+
-+#endif /* DCE100_RESOURCE_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile
-new file mode 100644
-index 0000000..cd7a909
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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_opp.o dce110_opp_csc.o \
-+dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \
-+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \
-+dce110_resource.o \
-+dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \
-+dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o
-+
-+AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_DCE110)
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
-new file mode 100644
-index 0000000..518150a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
-@@ -0,0 +1,859 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%s: Invalid LPT ROW_SIZE!!!",
-+ __func__);
-+ break;
-+ }
-+ } else {
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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;
-+ udelay(10);
-+ counter++;
-+ }
-+
-+ if (counter == 10) {
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%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 dc_bios *bp = ctx->dc_bios;
-+ struct embedded_panel_info panel_info;
-+
-+ compressor->base.options.bits.FBC_SUPPORT = true;
-+ compressor->base.options.bits.LPT_SUPPORT = true;
-+ /* For DCE 11 always use one DRAM channel for LPT */
-+ compressor->base.lpt_channels_num = 1;
-+ compressor->base.options.bits.DUMMY_BACKEND = false;
-+
-+ /* 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;
-+
-+ compressor->base.options.bits.CLK_GATING_DISABLED = false;
-+
-+ compressor->base.ctx = ctx;
-+ compressor->base.embedded_panel_h_size = 0;
-+ compressor->base.embedded_panel_v_size = 0;
-+ compressor->base.memory_bus_width = ctx->asic_id.vram_width;
-+ 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 (BP_RESULT_OK ==
-+ bp->funcs->get_embedded_panel_info(bp, &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 dce110_compressor *cp110 =
-+ dm_alloc(sizeof(struct dce110_compressor));
-+
-+ if (!cp110)
-+ return NULL;
-+
-+ if (dce110_compressor_construct(cp110, ctx))
-+ return &cp110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(cp110);
-+ return NULL;
-+}
-+
-+void dce110_compressor_destroy(struct compressor **compressor)
-+{
-+ dm_free(TO_DCE110_COMPRESSOR(*compressor));
-+ *compressor = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h
-new file mode 100644
-index 0000000..22af5be
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h
-@@ -0,0 +1,78 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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);
-+
-+bool dce110_compressor_construct(struct dce110_compressor *cp110,
-+ struct dc_context *ctx);
-+
-+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_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
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
-new file mode 100644
-index 0000000..1a68299
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
-@@ -0,0 +1,1978 @@
-+/*
-+ * 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 "dce110_timing_generator.h"
-+
-+#include "bios/bios_parser_helper.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 "gamma_calcs.h"
-+#include "audio.h"
-+#include "dce/dce_hwseq.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 crtc;
-+};
-+
-+static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
-+{
-+ .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTCV_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)
-+
-+#define MAX_WATERMARK 0xFFFF
-+#define SAFE_NBP_MARK 0x7FFF
-+
-+/*******************************************************************************
-+ * Private definitions
-+ ******************************************************************************/
-+/***************************PIPE_CONTROL***********************************/
-+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);
-+ }
-+}
-+/**************************************************************************/
-+
-+static void enable_display_pipe_clock_gating(
-+ struct dc_context *ctx,
-+ bool clock_gating)
-+{
-+ /*TODO*/
-+}
-+
-+static bool dce110_enable_display_power_gating(
-+ struct core_dc *dc,
-+ 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;
-+ struct dc_context *ctx = dc->ctx;
-+ unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
-+
-+ 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 (controller_id == underlay_idx)
-+ controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
-+
-+ if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
-+
-+ bp_result = dcb->funcs->enable_disp_power_gating(
-+ dcb, controller_id + 1, cntl);
-+
-+ /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
-+ * by default when command table is called
-+ *
-+ * Bios parser accepts controller_id = 6 as indicative of
-+ * underlay pipe in dce110. But we do not support more
-+ * than 3.
-+ */
-+ if (controller_id < CONTROLLER_ID_MAX - 1)
-+ dm_write_reg(ctx,
-+ HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
-+ 0);
-+ }
-+
-+ if (power_gating != PIPE_GATING_CONTROL_ENABLE)
-+ dce110_init_pte(ctx);
-+
-+ if (bp_result == BP_RESULT_OK)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+static void build_prescale_params(struct ipp_prescale_params *prescale_params,
-+ const struct core_surface *surface)
-+{
-+ prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
-+
-+ switch (surface->public.format) {
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
-+ prescale_params->scale = 0x2020;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
-+ prescale_params->scale = 0x2008;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
-+ prescale_params->scale = 0x2000;
-+ break;
-+ default:
-+ ASSERT(false);
-+ }
-+}
-+
-+static bool set_gamma_ramp(
-+ struct input_pixel_processor *ipp,
-+ struct output_pixel_processor *opp,
-+ const struct core_gamma *ramp,
-+ const struct core_surface *surface)
-+{
-+ struct ipp_prescale_params prescale_params = { 0 };
-+ struct pwl_params *regamma_params;
-+ bool result = false;
-+
-+ regamma_params = dm_alloc(sizeof(struct pwl_params));
-+ if (regamma_params == NULL)
-+ goto regamma_alloc_fail;
-+
-+ regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM;
-+
-+ opp->funcs->opp_power_on_regamma_lut(opp, true);
-+
-+ if (ipp) {
-+ build_prescale_params(&prescale_params, surface);
-+ ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
-+ }
-+
-+ if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) {
-+
-+ opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
-+ if (ipp)
-+ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
-+ opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
-+ } else {
-+ if (ipp)
-+ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
-+ opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
-+ }
-+
-+ opp->funcs->opp_power_on_regamma_lut(opp, false);
-+
-+ result = true;
-+
-+ dm_free(regamma_params);
-+
-+regamma_alloc_fail:
-+ return result;
-+}
-+
-+static enum dc_status bios_parser_crtc_source_select(
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ 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 = pipe_ctx->stream->sink;
-+
-+ crtc_source_select.engine_id = pipe_ctx->stream_enc->id;
-+ crtc_source_select.controller_id = pipe_ctx->pipe_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 = pipe_ctx->stream->signal;
-+ crtc_source_select.enable_dp_audio = false;
-+ crtc_source_select.sink_signal = pipe_ctx->stream->signal;
-+ crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
-+
-+ dcb = sink->ctx->dc_bios;
-+
-+ if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
-+ dcb,
-+ &crtc_source_select)) {
-+ return DC_ERROR_UNEXPECTED;
-+ }
-+
-+ return DC_OK;
-+}
-+
-+void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
-+{
-+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->update_hdmi_info_packets(
-+ pipe_ctx->stream_enc,
-+ &pipe_ctx->encoder_info_frame);
-+ else if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->update_dp_info_packets(
-+ pipe_ctx->stream_enc,
-+ &pipe_ctx->encoder_info_frame);
-+}
-+
-+void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
-+{
-+ enum dc_lane_count lane_count =
-+ pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count;
-+
-+ struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
-+ struct core_link *link = pipe_ctx->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 = pipe_ctx->tg;
-+
-+ /* TODOFPGA may change to hwss.update_info_frame */
-+ dce110_update_info_frame(pipe_ctx);
-+ /* 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 (pipe_ctx->audio != NULL) {
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc);
-+ }
-+
-+ /* 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,
-+ pipe_ctx->stream_enc->id, true);
-+
-+}
-+
-+void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct core_link *link = stream->sink->link;
-+
-+ if (pipe_ctx->audio) {
-+ pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio);
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dp_audio_disable(
-+ pipe_ctx->stream_enc);
-+ else
-+ pipe_ctx->stream_enc->funcs->hdmi_audio_disable(
-+ pipe_ctx->stream_enc);
-+
-+ pipe_ctx->audio = NULL;
-+
-+ /* 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);
-+ */
-+ }
-+
-+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets(
-+ pipe_ctx->stream_enc);
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->stop_dp_info_packets(
-+ pipe_ctx->stream_enc);
-+
-+ pipe_ctx->stream_enc->funcs->audio_mute_control(
-+ pipe_ctx->stream_enc, true);
-+
-+
-+ /* blank at encoder level */
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc);
-+
-+ link->link_enc->funcs->connect_dig_be_to_fe(
-+ link->link_enc,
-+ pipe_ctx->stream_enc->id,
-+ false);
-+
-+}
-+
-+void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
-+ struct dc_link_settings *link_settings)
-+{
-+ struct encoder_unblank_param params = { { 0 } };
-+
-+ /* only 3 items below are used by unblank */
-+ params.crtc_timing.pixel_clock =
-+ pipe_ctx->stream->public.timing.pix_clk_khz;
-+ params.link_settings.link_rate = link_settings->link_rate;
-+ pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, &params);
-+}
-+
-+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 pipe_ctx *pipe_ctx,
-+ struct audio_output *audio_output)
-+{
-+ const struct core_stream *stream = pipe_ctx->stream;
-+ audio_output->engine_id = pipe_ctx->stream_enc->id;
-+
-+ audio_output->signal = pipe_ctx->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 =
-+ pipe_ctx->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 =
-+ pipe_ctx->pix_clk_params.requested_pix_clk;
-+
-+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
-+ pipe_ctx->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(
-+ pipe_ctx->dis_clk);
-+ }
-+
-+ audio_output->pll_info.feed_back_divider =
-+ pipe_ctx->pll_settings.feedback_divider;
-+
-+ audio_output->pll_info.dto_source =
-+ translate_to_dto_source(
-+ pipe_ctx->pipe_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 =
-+ pipe_ctx->pll_settings.ss_percentage;
-+}
-+
-+static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
-+ struct tg_color *color)
-+{
-+ uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
-+
-+ switch (pipe_ctx->scl_data.format) {
-+ case PIXEL_FORMAT_ARGB8888:
-+ /* set boarder color to red */
-+ color->color_r_cr = color_value;
-+ break;
-+
-+ case PIXEL_FORMAT_ARGB2101010:
-+ /* set boarder color to blue */
-+ color->color_b_cb = color_value;
-+ break;
-+ case PIXEL_FORMAT_420BPP12:
-+ /* set boarder color to green */
-+ color->color_g_y = color_value;
-+ break;
-+ case PIXEL_FORMAT_FP16:
-+ /* set boarder color to white */
-+ color->color_r_cr = color_value;
-+ color->color_b_cb = color_value;
-+ color->color_g_y = color_value;
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static void program_scaler(const struct core_dc *dc,
-+ const struct pipe_ctx *pipe_ctx)
-+{
-+ struct tg_color color = {0};
-+
-+ if (dc->public.debug.surface_visual_confirm)
-+ get_surface_visual_confirm_color(pipe_ctx, &color);
-+ else
-+ color_space_to_black_color(dc,
-+ pipe_ctx->stream->public.output_color_space,
-+ &color);
-+
-+ pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth(
-+ pipe_ctx->xfm,
-+ pipe_ctx->scl_data.lb_params.depth,
-+ &pipe_ctx->stream->bit_depth_params);
-+
-+ if (pipe_ctx->tg->funcs->set_overscan_blank_color)
-+ pipe_ctx->tg->funcs->set_overscan_blank_color(
-+ pipe_ctx->tg,
-+ &color);
-+
-+ pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm,
-+ &pipe_ctx->scl_data);
-+}
-+
-+static enum dc_status prog_pixclk_crtc_otg(
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context,
-+ struct core_dc *dc)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
-+ pipe_ctx[pipe_ctx->pipe_idx];
-+ struct tg_color black_color = {0};
-+
-+ if (!pipe_ctx_old->stream) {
-+
-+ /* program blank color */
-+ color_space_to_black_color(dc,
-+ stream->public.output_color_space, &black_color);
-+ pipe_ctx->tg->funcs->set_blank_color(
-+ pipe_ctx->tg,
-+ &black_color);
-+ /*
-+ * Must blank CRTC after disabling power gating and before any
-+ * programming, otherwise CRTC will be hung in bad state
-+ */
-+ pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
-+
-+ if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
-+ pipe_ctx->clock_source,
-+ &pipe_ctx->pix_clk_params,
-+ &pipe_ctx->pll_settings)) {
-+ BREAK_TO_DEBUGGER();
-+ return DC_ERROR_UNEXPECTED;
-+ }
-+
-+ pipe_ctx->tg->funcs->program_timing(
-+ pipe_ctx->tg,
-+ &stream->public.timing,
-+ true);
-+ }
-+
-+ if (!pipe_ctx_old->stream) {
-+ if (false == pipe_ctx->tg->funcs->enable_crtc(
-+ pipe_ctx->tg)) {
-+ BREAK_TO_DEBUGGER();
-+ return DC_ERROR_UNEXPECTED;
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+static enum dc_status apply_single_controller_ctx_to_hw(
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context,
-+ struct core_dc *dc)
-+{
-+ struct core_stream *stream = pipe_ctx->stream;
-+ struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
-+ pipe_ctx[pipe_ctx->pipe_idx];
-+
-+ /* */
-+ dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
-+
-+ pipe_ctx->opp->funcs->opp_set_dyn_expansion(
-+ pipe_ctx->opp,
-+ COLOR_SPACE_YCBCR601,
-+ stream->public.timing.display_color_depth,
-+ pipe_ctx->stream->signal);
-+
-+ pipe_ctx->opp->funcs->opp_program_fmt(
-+ pipe_ctx->opp,
-+ &stream->bit_depth_params,
-+ &stream->clamping);
-+
-+ /* FPGA does not program backend */
-+ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
-+ return DC_OK;
-+
-+ /* TODO: move to stream encoder */
-+ if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
-+ if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
-+ BREAK_TO_DEBUGGER();
-+ return DC_ERROR_UNEXPECTED;
-+ }
-+
-+ if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
-+ stream->sink->link->link_enc->funcs->setup(
-+ stream->sink->link->link_enc,
-+ pipe_ctx->stream->signal);
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dp_set_stream_attribute(
-+ pipe_ctx->stream_enc,
-+ &stream->public.timing,
-+ stream->public.output_color_space);
-+
-+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute(
-+ pipe_ctx->stream_enc,
-+ &stream->public.timing,
-+ stream->phy_pix_clk,
-+ pipe_ctx->audio != NULL);
-+
-+ if (dc_is_dvi_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute(
-+ pipe_ctx->stream_enc,
-+ &stream->public.timing,
-+ (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
-+ true : false);
-+
-+ if (!pipe_ctx_old->stream) {
-+ core_link_enable_stream(pipe_ctx);
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ dce110_unblank_stream(pipe_ctx,
-+ &stream->sink->link->public.cur_link_settings);
-+ }
-+
-+ pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
-+ /* program_scaler and allocate_mem_input are not new asic */
-+ if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data,
-+ &pipe_ctx->scl_data,
-+ sizeof(struct scaler_data)) != 0)
-+ program_scaler(dc, pipe_ctx);
-+
-+ /* mst support - use total stream count */
-+ pipe_ctx->mi->funcs->allocate_mem_input(
-+ pipe_ctx->mi,
-+ stream->public.timing.h_total,
-+ stream->public.timing.v_total,
-+ stream->public.timing.pix_clk_khz,
-+ context->target_count);
-+
-+ return DC_OK;
-+}
-+
-+/******************************************************************************/
-+
-+static void power_down_encoders(struct core_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 core_dc *dc)
-+{
-+ int i;
-+
-+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
-+ dc->res_pool->timing_generators[i]->funcs->disable_crtc(
-+ dc->res_pool->timing_generators[i]);
-+ }
-+}
-+
-+static void power_down_clock_sources(struct core_dc *dc)
-+{
-+ int i;
-+
-+ if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
-+ dc->res_pool->dp_clock_source) == false)
-+ dm_error("Failed to power down pll! (dp clk src)\n");
-+
-+ 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 core_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 core_dc *dc)
-+{
-+ int i;
-+ struct timing_generator *tg;
-+ struct dc_context *ctx = dc->ctx;
-+
-+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
-+ tg = dc->res_pool->timing_generators[i];
-+
-+ tg->funcs->disable_vga(tg);
-+
-+ /* Enable CLOCK gating for each pipe BEFORE controller
-+ * powergating. */
-+ enable_display_pipe_clock_gating(ctx,
-+ true);
-+
-+ dc->hwss.power_down_front_end(
-+ dc, &dc->current_context->res_ctx.pipe_ctx[i]);
-+ }
-+}
-+
-+/**
-+ * 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)
-+ */
-+void dce110_enable_accelerated_mode(struct core_dc *dc)
-+{
-+ power_down_all_hw_blocks(dc);
-+
-+ disable_vga_and_power_gate_all_controllers(dc);
-+ bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
-+}
-+
-+/**
-+ * Call display_engine_clock_dce80 to perform the Dclk programming.
-+ */
-+void dce110_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 {
-+ /*
-+ * TODO: need to either port work around from DAL2 function
-+ * getActualRequiredDisplayClock or program displayclock without
-+ * calling vbios. Currently temporily work
-+ * around by increasing the displclk by 15 percent
-+ */
-+ dal_display_clock_set_clock(
-+ context->res_ctx.pool->display_clock,
-+ context->bw_results.dispclk_khz * 115 / 100);
-+ }
-+
-+
-+ /* TODO: When changing display engine clock, DMCU WaitLoop must be
-+ * reconfigured in order to maintain the same delays within DMCU
-+ * programming sequences. */
-+}
-+
-+static uint32_t compute_pstate_blackout_duration(
-+ struct bw_fixed blackout_duration,
-+ const struct core_stream *stream)
-+{
-+ uint32_t total_dest_line_time_ns;
-+ uint32_t pstate_blackout_duration_ns;
-+
-+ pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
-+
-+ total_dest_line_time_ns = 1000000UL *
-+ stream->public.timing.h_total /
-+ stream->public.timing.pix_clk_khz +
-+ pstate_blackout_duration_ns;
-+
-+ return total_dest_line_time_ns;
-+}
-+
-+/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/
-+int get_bw_result_idx(
-+ struct resource_context *res_ctx,
-+ int pipe_idx)
-+{
-+ int i, collapsed_idx;
-+
-+ if (res_ctx->pipe_ctx[pipe_idx].top_pipe)
-+ return 3;
-+
-+ collapsed_idx = 0;
-+ for (i = 0; i < pipe_idx; i++) {
-+ if (res_ctx->pipe_ctx[i].stream)
-+ collapsed_idx++;
-+ }
-+
-+ return collapsed_idx;
-+}
-+
-+static bool is_watermark_set_a_greater(
-+ const struct bw_watermarks *set_a,
-+ const struct bw_watermarks *set_b)
-+{
-+ if (set_a->a_mark > set_b->a_mark
-+ || set_a->b_mark > set_b->b_mark
-+ || set_a->c_mark > set_b->c_mark
-+ || set_a->d_mark > set_b->d_mark)
-+ return true;
-+ return false;
-+}
-+
-+static bool did_watermarks_increase(
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context,
-+ struct validate_context *old_context)
-+{
-+ int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx,
-+ pipe_ctx->pipe_idx);
-+ int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx,
-+ pipe_ctx->pipe_idx);
-+ struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
-+
-+ if (!old_pipe_ctx->stream)
-+ return true;
-+
-+ if (is_watermark_set_a_greater(
-+ &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx],
-+ &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx]))
-+ return true;
-+ if (is_watermark_set_a_greater(
-+ &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx],
-+ &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx]))
-+ return true;
-+ if (is_watermark_set_a_greater(
-+ &context->bw_results.urgent_wm_ns[collapsed_pipe_idx],
-+ &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx]))
-+ return true;
-+
-+ return false;
-+}
-+
-+static void program_wm_for_pipe(struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ int total_dest_line_time_ns = compute_pstate_blackout_duration(
-+ dc->bw_vbios.blackout_duration,
-+ pipe_ctx->stream);
-+ int bw_result_idx = get_bw_result_idx(&context->res_ctx,
-+ pipe_ctx->pipe_idx);
-+
-+ pipe_ctx->mi->funcs->mem_input_program_display_marks(
-+ pipe_ctx->mi,
-+ context->bw_results.nbp_state_change_wm_ns[bw_result_idx],
-+ context->bw_results.stutter_exit_wm_ns[bw_result_idx],
-+ context->bw_results.urgent_wm_ns[bw_result_idx],
-+ total_dest_line_time_ns);
-+
-+ if (pipe_ctx->top_pipe)
-+ pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
-+ pipe_ctx->mi,
-+ context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1],
-+ context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1],
-+ context->bw_results.urgent_wm_ns[bw_result_idx + 1],
-+ total_dest_line_time_ns);
-+}
-+
-+void dce110_set_displaymarks(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ uint8_t i, num_pipes;
-+ unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
-+
-+ for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+ uint32_t total_dest_line_time_ns;
-+
-+ if (pipe_ctx->stream == NULL)
-+ continue;
-+
-+ total_dest_line_time_ns = compute_pstate_blackout_duration(
-+ dc->bw_vbios.blackout_duration, pipe_ctx->stream);
-+ pipe_ctx->mi->funcs->mem_input_program_display_marks(
-+ pipe_ctx->mi,
-+ context->bw_results.nbp_state_change_wm_ns[num_pipes],
-+ context->bw_results.stutter_exit_wm_ns[num_pipes],
-+ context->bw_results.urgent_wm_ns[num_pipes],
-+ total_dest_line_time_ns);
-+ if (i == underlay_idx) {
-+ num_pipes++;
-+ pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
-+ pipe_ctx->mi,
-+ context->bw_results.nbp_state_change_wm_ns[num_pipes],
-+ context->bw_results.stutter_exit_wm_ns[num_pipes],
-+ context->bw_results.urgent_wm_ns[num_pipes],
-+ total_dest_line_time_ns);
-+ }
-+ num_pipes++;
-+ }
-+}
-+
-+static void set_safe_displaymarks(struct resource_context *res_ctx)
-+{
-+ int i;
-+ int underlay_idx = res_ctx->pool->underlay_pipe_index;
-+ struct bw_watermarks max_marks = {
-+ MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
-+ struct bw_watermarks nbp_marks = {
-+ SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ if (res_ctx->pipe_ctx[i].stream == NULL)
-+ continue;
-+
-+ res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks(
-+ res_ctx->pipe_ctx[i].mi,
-+ nbp_marks,
-+ max_marks,
-+ max_marks,
-+ MAX_WATERMARK);
-+ if (i == underlay_idx)
-+ res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks(
-+ res_ctx->pipe_ctx[i].mi,
-+ nbp_marks,
-+ max_marks,
-+ max_marks,
-+ MAX_WATERMARK);
-+ }
-+}
-+
-+static void switch_dp_clock_sources(
-+ const struct core_dc *dc,
-+ struct resource_context *res_ctx)
-+{
-+ uint8_t i;
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-+
-+ if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
-+ continue;
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
-+ struct clock_source *clk_src =
-+ resource_find_used_clk_src_for_sharing(
-+ res_ctx, pipe_ctx);
-+
-+ if (clk_src &&
-+ clk_src != pipe_ctx->clock_source) {
-+ resource_unreference_clock_source(
-+ res_ctx, pipe_ctx->clock_source);
-+ pipe_ctx->clock_source = clk_src;
-+ resource_reference_clock_source(res_ctx, clk_src);
-+
-+ dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i);
-+ }
-+ }
-+ }
-+}
-+
-+/*******************************************************************************
-+ * Public functions
-+ ******************************************************************************/
-+
-+static void reset_single_pipe_hw_ctx(
-+ const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ core_link_disable_stream(pipe_ctx);
-+ if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
-+ dm_error("DC: failed to blank crtc!\n");
-+ BREAK_TO_DEBUGGER();
-+ }
-+ pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
-+ pipe_ctx->mi->funcs->free_mem_input(
-+ pipe_ctx->mi, context->target_count);
-+ resource_unreference_clock_source(
-+ &context->res_ctx, pipe_ctx->clock_source);
-+
-+ dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx);
-+
-+ pipe_ctx->stream = NULL;
-+}
-+
-+static void set_drr(struct pipe_ctx **pipe_ctx,
-+ int num_pipes, int vmin, int vmax)
-+{
-+ int i = 0;
-+ struct drr_params params = {0};
-+
-+ params.vertical_total_max = vmax;
-+ params.vertical_total_min = vmin;
-+
-+ /* TODO: If multiple pipes are to be supported, you need
-+ * some GSL stuff
-+ */
-+
-+ for (i = 0; i < num_pipes; i++) {
-+ pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
-+ }
-+}
-+
-+static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
-+ int num_pipes, int value)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < num_pipes; i++)
-+ pipe_ctx[i]->tg->funcs->
-+ set_static_screen_control(pipe_ctx[i]->tg, value);
-+}
-+
-+/* unit: in_khz before mode set, get pixel clock from context. ASIC register
-+ * may not be programmed yet.
-+ * TODO: after mode set, pre_mode_set = false,
-+ * may read PLL register to get pixel clock
-+ */
-+static uint32_t get_max_pixel_clock_for_all_paths(
-+ struct core_dc *dc,
-+ struct validate_context *context,
-+ bool pre_mode_set)
-+{
-+ uint32_t max_pix_clk = 0;
-+ int i;
-+
-+ if (!pre_mode_set) {
-+ /* TODO: read ASIC register to get pixel clock */
-+ ASSERT(0);
-+ }
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->stream == NULL)
-+ continue;
-+
-+ /* do not check under lay */
-+ if (pipe_ctx->top_pipe)
-+ continue;
-+
-+ if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk)
-+ max_pix_clk =
-+ pipe_ctx->pix_clk_params.requested_pix_clk;
-+ }
-+
-+ if (max_pix_clk == 0)
-+ ASSERT(0);
-+
-+ return max_pix_clk;
-+}
-+
-+/*
-+ * Find clock state based on clock requested. if clock value is 0, simply
-+ * set clock state as requested without finding clock state by clock value
-+ */
-+static void apply_min_clocks(
-+ struct core_dc *dc,
-+ struct validate_context *context,
-+ enum clocks_state *clocks_state,
-+ bool pre_mode_set)
-+{
-+ struct state_dependent_clocks req_clocks = {0};
-+ struct pipe_ctx *pipe_ctx;
-+ int i;
-+
-+ for (i = 0; i < MAX_PIPES; i++) {
-+ pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+ if (pipe_ctx->dis_clk != NULL)
-+ break;
-+ }
-+
-+ if (!pre_mode_set) {
-+ /* set clock_state without verification */
-+ if (dal_display_clock_set_min_clocks_state(
-+ pipe_ctx->dis_clk, *clocks_state))
-+ return;
-+
-+ /* TODOFPGA */
-+ }
-+
-+ /* get the required state based on state dependent clocks:
-+ * display clock and pixel clock
-+ */
-+ req_clocks.display_clk_khz = context->bw_results.dispclk_khz;
-+
-+ req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
-+ dc, context, true);
-+
-+ if (dal_display_clock_get_required_clocks_state(
-+ pipe_ctx->dis_clk, &req_clocks, clocks_state)) {
-+ dal_display_clock_set_min_clocks_state(
-+ pipe_ctx->dis_clk, *clocks_state);
-+ } else {
-+ }
-+}
-+
-+static enum dc_status apply_ctx_to_hw_fpga(
-+ struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status status = DC_ERROR_UNEXPECTED;
-+ int i;
-+
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx_old =
-+ &dc->current_context->res_ctx.pipe_ctx[i];
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->stream == NULL)
-+ continue;
-+
-+ if (pipe_ctx->stream == pipe_ctx_old->stream)
-+ continue;
-+
-+ status = apply_single_controller_ctx_to_hw(
-+ pipe_ctx,
-+ context,
-+ dc);
-+
-+ if (status != DC_OK)
-+ return status;
-+ }
-+
-+ return DC_OK;
-+}
-+
-+static void reset_hw_ctx_wrap(
-+ struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ int i;
-+
-+ /* Reset old context */
-+ /* look up the targets that have been removed since last commit */
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx_old =
-+ &dc->current_context->res_ctx.pipe_ctx[i];
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ /* Note: We need to disable output if clock sources change,
-+ * since bios does optimization and doesn't apply if changing
-+ * PHY when not already disabled.
-+ */
-+
-+ /* Skip underlay pipe since it will be handled in commit surface*/
-+ if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
-+ continue;
-+
-+ if (!pipe_ctx->stream ||
-+ pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
-+ reset_single_pipe_hw_ctx(
-+ dc, pipe_ctx_old, dc->current_context);
-+ }
-+}
-+
-+/*TODO: const validate_context*/
-+enum dc_status dce110_apply_ctx_to_hw(
-+ struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ struct dc_bios *dcb = dc->ctx->dc_bios;
-+ enum dc_status status;
-+ int i;
-+ bool programmed_audio_dto = false;
-+ enum clocks_state clocks_state = CLOCKS_STATE_INVALID;
-+
-+ /* Reset old context */
-+ /* look up the targets that have been removed since last commit */
-+ dc->hwss.reset_hw_ctx_wrap(dc, context);
-+
-+ /* Skip applying if no targets */
-+ if (context->target_count <= 0)
-+ return DC_OK;
-+
-+ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-+ apply_ctx_to_hw_fpga(dc, context);
-+ return DC_OK;
-+ }
-+
-+ /* Apply new context */
-+ dcb->funcs->set_scratch_critical_state(dcb, true);
-+
-+ /* below is for real asic only */
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx_old =
-+ &dc->current_context->res_ctx.pipe_ctx[i];
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
-+ continue;
-+
-+ if (pipe_ctx->stream == pipe_ctx_old->stream) {
-+ if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
-+ dce_crtc_switch_to_clk_src(dc->hwseq,
-+ pipe_ctx->clock_source, i);
-+ continue;
-+ }
-+
-+ dc->hwss.enable_display_power_gating(
-+ dc, i, dc->ctx->dc_bios,
-+ PIPE_GATING_CONTROL_DISABLE);
-+ }
-+
-+ set_safe_displaymarks(&context->res_ctx);
-+ /*TODO: when pplib works*/
-+ apply_min_clocks(dc, context, &clocks_state, true);
-+
-+ if (context->bw_results.dispclk_khz
-+ > dc->current_context->bw_results.dispclk_khz)
-+ dc->hwss.set_display_clock(context);
-+
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx_old =
-+ &dc->current_context->res_ctx.pipe_ctx[i];
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->stream == NULL)
-+ continue;
-+
-+ if (pipe_ctx->stream == pipe_ctx_old->stream)
-+ continue;
-+
-+ if (pipe_ctx->top_pipe)
-+ continue;
-+
-+ if (context->res_ctx.pipe_ctx[i].audio != NULL) {
-+ /* Setup audio rate clock source */
-+ /* Issue:
-+ * Audio lag happened on DP monitor when unplug a HDMI monitor
-+ *
-+ * Cause:
-+ * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
-+ * is set to either dto0 or dto1, audio should work fine.
-+ * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
-+ * set to dto0 will cause audio lag.
-+ *
-+ * Solution:
-+ * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
-+ * find first available pipe with audio, setup audio wall DTO per topology
-+ * instead of per pipe.
-+ */
-+ struct audio_output audio_output;
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ build_audio_output(pipe_ctx, &audio_output);
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
-+ pipe_ctx->stream_enc->funcs->dp_audio_setup(
-+ pipe_ctx->stream_enc,
-+ pipe_ctx->audio->inst,
-+ &pipe_ctx->stream->public.audio_info);
-+ else
-+ pipe_ctx->stream_enc->funcs->hdmi_audio_setup(
-+ pipe_ctx->stream_enc,
-+ pipe_ctx->audio->inst,
-+ &pipe_ctx->stream->public.audio_info,
-+ &audio_output.crtc_info);
-+
-+ pipe_ctx->audio->funcs->az_configure(
-+ pipe_ctx->audio,
-+ pipe_ctx->stream->signal,
-+ &audio_output.crtc_info,
-+ &pipe_ctx->stream->public.audio_info);
-+
-+ if (!programmed_audio_dto) {
-+ pipe_ctx->audio->funcs->wall_dto_setup(
-+ pipe_ctx->audio,
-+ pipe_ctx->stream->signal,
-+ &audio_output.crtc_info,
-+ &audio_output.pll_info);
-+ programmed_audio_dto = true;
-+ }
-+ }
-+
-+ status = apply_single_controller_ctx_to_hw(
-+ pipe_ctx,
-+ context,
-+ dc);
-+
-+ if (DC_OK != status)
-+ return status;
-+ }
-+
-+ dc->hwss.set_displaymarks(dc, context);
-+
-+ /* to save power */
-+ apply_min_clocks(dc, context, &clocks_state, false);
-+
-+ dcb->funcs->set_scratch_critical_state(dcb, false);
-+
-+ switch_dp_clock_sources(dc, &context->res_ctx);
-+
-+ return DC_OK;
-+}
-+
-+/*******************************************************************************
-+ * Front End programming
-+ ******************************************************************************/
-+static void set_default_colors(struct pipe_ctx *pipe_ctx)
-+{
-+ struct default_adjustment default_adjust = { 0 };
-+
-+ default_adjust.force_hw_default = false;
-+ if (pipe_ctx->surface == NULL)
-+ default_adjust.in_color_space = COLOR_SPACE_SRGB;
-+ else
-+ default_adjust.in_color_space =
-+ pipe_ctx->surface->public.color_space;
-+ if (pipe_ctx->stream == NULL)
-+ default_adjust.out_color_space = COLOR_SPACE_SRGB;
-+ else
-+ default_adjust.out_color_space =
-+ pipe_ctx->stream->public.output_color_space;
-+ default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
-+ default_adjust.surface_pixel_format = pipe_ctx->scl_data.format;
-+
-+ /* display color depth */
-+ default_adjust.color_depth =
-+ pipe_ctx->stream->public.timing.display_color_depth;
-+
-+ /* Lb color depth */
-+ default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth;
-+
-+ pipe_ctx->opp->funcs->opp_set_csc_default(
-+ pipe_ctx->opp, &default_adjust);
-+}
-+
-+static void program_blender(const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
-+
-+ if (pipe_ctx->bottom_pipe) {
-+ if (pipe_ctx->bottom_pipe->surface->public.visible) {
-+ if (pipe_ctx->surface->public.visible)
-+ blender_mode = BLND_MODE_BLENDING;
-+ else
-+ blender_mode = BLND_MODE_OTHER_PIPE;
-+ }
-+ }
-+ dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode);
-+}
-+
-+/**
-+ * TODO REMOVE, USE UPDATE INSTEAD
-+ */
-+static void set_plane_config(
-+ const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct resource_context *res_ctx)
-+{
-+ struct mem_input *mi = pipe_ctx->mi;
-+ struct core_surface *surface = pipe_ctx->surface;
-+ struct xfm_grph_csc_adjustment adjust;
-+ struct out_csc_color_matrix tbl_entry;
-+ unsigned int i;
-+
-+ memset(&adjust, 0, sizeof(adjust));
-+ memset(&tbl_entry, 0, sizeof(tbl_entry));
-+ adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
-+
-+ dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
-+
-+ set_default_colors(pipe_ctx);
-+ if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
-+ == true) {
-+ tbl_entry.color_space =
-+ pipe_ctx->stream->public.output_color_space;
-+
-+ for (i = 0; i < 12; i++)
-+ tbl_entry.regval[i] =
-+ pipe_ctx->stream->public.csc_color_matrix.matrix[i];
-+
-+ pipe_ctx->opp->funcs->opp_set_csc_adjustment
-+ (pipe_ctx->opp, &tbl_entry);
-+ }
-+
-+ if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
-+ adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
-+ adjust.temperature_matrix[0] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[0];
-+ adjust.temperature_matrix[1] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[1];
-+ adjust.temperature_matrix[2] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[2];
-+ adjust.temperature_matrix[3] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[4];
-+ adjust.temperature_matrix[4] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[5];
-+ adjust.temperature_matrix[5] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[6];
-+ adjust.temperature_matrix[6] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[8];
-+ adjust.temperature_matrix[7] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[9];
-+ adjust.temperature_matrix[8] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[10];
-+ }
-+
-+ pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
-+
-+ pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
-+ program_scaler(dc, pipe_ctx);
-+
-+ program_blender(dc, pipe_ctx);
-+
-+ mi->funcs->mem_input_program_surface_config(
-+ mi,
-+ surface->public.format,
-+ &surface->public.tiling_info,
-+ &surface->public.plane_size,
-+ surface->public.rotation,
-+ NULL,
-+ false);
-+
-+ if (dc->public.config.gpu_vm_support)
-+ mi->funcs->mem_input_program_pte_vm(
-+ pipe_ctx->mi,
-+ surface->public.format,
-+ &surface->public.tiling_info,
-+ surface->public.rotation);
-+}
-+
-+static void update_plane_addr(const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_surface *surface = pipe_ctx->surface;
-+
-+ if (surface == NULL)
-+ return;
-+
-+ pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
-+ pipe_ctx->mi,
-+ &surface->public.address,
-+ surface->public.flip_immediate);
-+
-+ surface->status.requested_address = surface->public.address;
-+
-+ if (surface->public.visible)
-+ pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false);
-+}
-+
-+void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
-+{
-+ struct core_surface *surface = pipe_ctx->surface;
-+
-+ if (surface == NULL)
-+ return;
-+
-+ surface->status.is_flip_pending =
-+ pipe_ctx->mi->funcs->mem_input_is_flip_pending(
-+ pipe_ctx->mi);
-+
-+ if (surface->status.is_flip_pending && !surface->public.visible)
-+ pipe_ctx->mi->current_address = pipe_ctx->mi->request_address;
-+
-+ surface->status.current_address = pipe_ctx->mi->current_address;
-+}
-+
-+void dce110_power_down(struct core_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 dce110_enable_timing_synchronization(
-+ struct core_dc *dc,
-+ int group_index,
-+ int group_size,
-+ struct pipe_ctx *grouped_pipes[])
-+{
-+ struct dc_context *dc_ctx = dc->ctx;
-+ struct dcp_gsl_params gsl_params = { 0 };
-+ int i;
-+
-+ DC_SYNC_INFO("GSL: Setting-up...\n");
-+
-+ /* 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.gsl_group = 0;
-+ gsl_params.gsl_master = grouped_pipes[0]->tg->inst;
-+
-+ for (i = 0; i < group_size; i++)
-+ grouped_pipes[i]->tg->funcs->setup_global_swap_lock(
-+ grouped_pipes[i]->tg, &gsl_params);
-+
-+ /* Reset slave controllers on master VSync */
-+ DC_SYNC_INFO("GSL: enabling trigger-reset\n");
-+
-+ for (i = 1 /* skip the master */; i < group_size; i++)
-+ grouped_pipes[i]->tg->funcs->enable_reset_trigger(
-+ grouped_pipes[i]->tg, gsl_params.gsl_group);
-+
-+
-+
-+ for (i = 1 /* skip the master */; i < group_size; i++) {
-+ DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
-+ wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg);
-+ /* 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");
-+ grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg);
-+ }
-+
-+
-+ /* 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 < group_size; i++)
-+ grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg);
-+
-+ DC_SYNC_INFO("GSL: Set-up complete.\n");
-+}
-+
-+static void init_hw(struct core_dc *dc)
-+{
-+ int i;
-+ struct dc_bios *bp;
-+ struct transform *xfm;
-+
-+ bp = dc->ctx->dc_bios;
-+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
-+ xfm = dc->res_pool->transforms[i];
-+ xfm->funcs->transform_reset(xfm);
-+
-+ dc->hwss.enable_display_power_gating(
-+ dc, i, bp,
-+ PIPE_GATING_CONTROL_INIT);
-+ dc->hwss.enable_display_power_gating(
-+ dc, i, bp,
-+ PIPE_GATING_CONTROL_DISABLE);
-+ dc->hwss.enable_display_pipe_clock_gating(
-+ dc->ctx,
-+ true);
-+ }
-+
-+ dce_clock_gating_power_up(dc->hwseq, false);;
-+ /***************************************/
-+
-+ 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->pipe_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];
-+ audio->funcs->hw_init(audio);
-+ }
-+}
-+
-+/* TODO: move this to apply_ctx_tohw some how?*/
-+static void dce110_power_on_pipe_if_needed(
-+ struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
-+ struct dc_bios *dcb = dc->ctx->dc_bios;
-+ struct tg_color black_color = {0};
-+
-+ if (!old_pipe_ctx->stream && pipe_ctx->stream) {
-+ dc->hwss.enable_display_power_gating(
-+ dc,
-+ pipe_ctx->pipe_idx,
-+ dcb, PIPE_GATING_CONTROL_DISABLE);
-+
-+ /*
-+ * This is for powering on underlay, so crtc does not
-+ * need to be enabled
-+ */
-+
-+ pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg,
-+ &pipe_ctx->stream->public.timing,
-+ false);
-+
-+ pipe_ctx->tg->funcs->enable_advanced_request(
-+ pipe_ctx->tg,
-+ true,
-+ &pipe_ctx->stream->public.timing);
-+
-+ pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi,
-+ pipe_ctx->stream->public.timing.h_total,
-+ pipe_ctx->stream->public.timing.v_total,
-+ pipe_ctx->stream->public.timing.pix_clk_khz,
-+ context->target_count);
-+
-+ /* TODO unhardcode*/
-+ color_space_to_black_color(dc,
-+ COLOR_SPACE_YCBCR601, &black_color);
-+ pipe_ctx->tg->funcs->set_blank_color(
-+ pipe_ctx->tg,
-+ &black_color);
-+ }
-+}
-+
-+static void dce110_increase_watermarks_for_pipe(
-+ struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ if (did_watermarks_increase(pipe_ctx, context, dc->current_context))
-+ program_wm_for_pipe(dc, pipe_ctx, context);
-+}
-+
-+static void dce110_set_bandwidth(struct core_dc *dc)
-+{
-+ int i;
-+
-+ for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i];
-+
-+ if (!pipe_ctx->stream)
-+ continue;
-+
-+ program_wm_for_pipe(dc, pipe_ctx, dc->current_context);
-+ }
-+
-+ dc->hwss.set_display_clock(dc->current_context);
-+}
-+
-+static void dce110_program_front_end_for_pipe(
-+ struct core_dc *dc, struct pipe_ctx *pipe_ctx)
-+{
-+ struct mem_input *mi = pipe_ctx->mi;
-+ struct pipe_ctx *old_pipe = NULL;
-+ struct core_surface *surface = pipe_ctx->surface;
-+ struct xfm_grph_csc_adjustment adjust;
-+ struct out_csc_color_matrix tbl_entry;
-+ unsigned int i;
-+
-+ memset(&tbl_entry, 0, sizeof(tbl_entry));
-+
-+ if (dc->current_context)
-+ old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
-+
-+ memset(&adjust, 0, sizeof(adjust));
-+ adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
-+
-+ dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
-+
-+ set_default_colors(pipe_ctx);
-+ if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
-+ == true) {
-+ tbl_entry.color_space =
-+ pipe_ctx->stream->public.output_color_space;
-+
-+ for (i = 0; i < 12; i++)
-+ tbl_entry.regval[i] =
-+ pipe_ctx->stream->public.csc_color_matrix.matrix[i];
-+
-+ pipe_ctx->opp->funcs->opp_set_csc_adjustment
-+ (pipe_ctx->opp, &tbl_entry);
-+ }
-+
-+ if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
-+ adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
-+ adjust.temperature_matrix[0] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[0];
-+ adjust.temperature_matrix[1] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[1];
-+ adjust.temperature_matrix[2] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[2];
-+ adjust.temperature_matrix[3] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[4];
-+ adjust.temperature_matrix[4] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[5];
-+ adjust.temperature_matrix[5] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[6];
-+ adjust.temperature_matrix[6] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[8];
-+ adjust.temperature_matrix[7] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[9];
-+ adjust.temperature_matrix[8] =
-+ pipe_ctx->stream->
-+ public.gamut_remap_matrix.matrix[10];
-+ }
-+
-+ pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
-+
-+ pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
-+ if (old_pipe && memcmp(&old_pipe->scl_data,
-+ &pipe_ctx->scl_data,
-+ sizeof(struct scaler_data)) != 0)
-+ program_scaler(dc, pipe_ctx);
-+
-+ mi->funcs->mem_input_program_surface_config(
-+ mi,
-+ surface->public.format,
-+ &surface->public.tiling_info,
-+ &surface->public.plane_size,
-+ surface->public.rotation,
-+ false,
-+ false);
-+
-+ if (dc->public.config.gpu_vm_support)
-+ mi->funcs->mem_input_program_pte_vm(
-+ pipe_ctx->mi,
-+ surface->public.format,
-+ &surface->public.tiling_info,
-+ surface->public.rotation);
-+
-+ dm_logger_write(dc->ctx->logger, LOG_SURFACE,
-+ "Pipe:%d 0x%x: addr hi:0x%x, "
-+ "addr low:0x%x, "
-+ "src: %d, %d, %d,"
-+ " %d; dst: %d, %d, %d, %d;"
-+ "clip: %d, %d, %d, %d\n",
-+ pipe_ctx->pipe_idx,
-+ pipe_ctx->surface,
-+ pipe_ctx->surface->public.address.grph.addr.high_part,
-+ pipe_ctx->surface->public.address.grph.addr.low_part,
-+ pipe_ctx->surface->public.src_rect.x,
-+ pipe_ctx->surface->public.src_rect.y,
-+ pipe_ctx->surface->public.src_rect.width,
-+ pipe_ctx->surface->public.src_rect.height,
-+ pipe_ctx->surface->public.dst_rect.x,
-+ pipe_ctx->surface->public.dst_rect.y,
-+ pipe_ctx->surface->public.dst_rect.width,
-+ pipe_ctx->surface->public.dst_rect.height,
-+ pipe_ctx->surface->public.clip_rect.x,
-+ pipe_ctx->surface->public.clip_rect.y,
-+ pipe_ctx->surface->public.clip_rect.width,
-+ pipe_ctx->surface->public.clip_rect.height);
-+
-+ dm_logger_write(dc->ctx->logger, LOG_SURFACE,
-+ "Pipe %d: width, height, x, y\n"
-+ "viewport:%d, %d, %d, %d\n"
-+ "recout: %d, %d, %d, %d\n",
-+ pipe_ctx->pipe_idx,
-+ pipe_ctx->scl_data.viewport.width,
-+ pipe_ctx->scl_data.viewport.height,
-+ pipe_ctx->scl_data.viewport.x,
-+ pipe_ctx->scl_data.viewport.y,
-+ pipe_ctx->scl_data.recout.width,
-+ pipe_ctx->scl_data.recout.height,
-+ pipe_ctx->scl_data.recout.x,
-+ pipe_ctx->scl_data.recout.y);
-+}
-+
-+
-+
-+static void dce110_prepare_pipe_for_surface_commit(
-+ struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context) {
-+ struct core_gamma *gamma = NULL;
-+
-+ dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context);
-+
-+ if (pipe_ctx->surface->public.gamma_correction)
-+ gamma = DC_GAMMA_TO_CORE(
-+ pipe_ctx->surface->public.gamma_correction);
-+
-+ dc->hwss.set_gamma_correction(
-+ pipe_ctx->ipp,
-+ pipe_ctx->opp,
-+ gamma, pipe_ctx->surface);
-+}
-+
-+static void dce110_prepare_pipe_for_context(
-+ struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ dce110_power_on_pipe_if_needed(dc, pipe_ctx, context);
-+ dce110_prepare_pipe_for_surface_commit(dc, pipe_ctx, context);
-+}
-+
-+static void dce110_apply_ctx_for_surface(
-+ struct core_dc *dc,
-+ struct core_surface *surface,
-+ struct validate_context *context)
-+{
-+ int i;
-+
-+ /* TODO remove when removing the surface reset workaroud*/
-+ if (!surface)
-+ return;
-+
-+ for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
-+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-+
-+ if (pipe_ctx->surface != surface)
-+ continue;
-+
-+ dce110_program_front_end_for_pipe(dc, pipe_ctx);
-+ program_blender(dc, pipe_ctx);
-+
-+ }
-+
-+}
-+
-+static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
-+{
-+ int i;
-+
-+ for (i = 0; i < dc->res_pool->pipe_count; i++)
-+ if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe)
-+ break;
-+
-+ if (i == dc->res_pool->pipe_count)
-+ return;
-+
-+ dc->hwss.enable_display_power_gating(
-+ dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
-+ if (pipe->xfm)
-+ pipe->xfm->funcs->transform_reset(pipe->xfm);
-+ memset(&pipe->scl_data, 0, sizeof(struct scaler_data));
-+}
-+
-+static const struct hw_sequencer_funcs dce110_funcs = {
-+ .init_hw = init_hw,
-+ .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
-+ .prepare_pipe_for_context = dce110_prepare_pipe_for_context,
-+ .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
-+ .set_plane_config = set_plane_config,
-+ .update_plane_addr = update_plane_addr,
-+ .update_pending_status = dce110_update_pending_status,
-+ .set_gamma_correction = set_gamma_ramp,
-+ .power_down = dce110_power_down,
-+ .enable_accelerated_mode = dce110_enable_accelerated_mode,
-+ .enable_timing_synchronization = dce110_enable_timing_synchronization,
-+ .update_info_frame = dce110_update_info_frame,
-+ .enable_stream = dce110_enable_stream,
-+ .disable_stream = dce110_disable_stream,
-+ .unblank_stream = dce110_unblank_stream,
-+ .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
-+ .enable_display_power_gating = dce110_enable_display_power_gating,
-+ .power_down_front_end = dce110_power_down_fe,
-+ .pipe_control_lock = dce_pipe_control_lock,
-+ .set_display_clock = dce110_set_display_clock,
-+ .set_displaymarks = dce110_set_displaymarks,
-+ .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe,
-+ .set_bandwidth = dce110_set_bandwidth,
-+ .set_drr = set_drr,
-+ .set_static_screen_control = set_static_screen_control,
-+ .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
-+ .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg,
-+};
-+
-+bool dce110_hw_sequencer_construct(struct core_dc *dc)
-+{
-+ dc->hwss = dce110_funcs;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
-new file mode 100644
-index 0000000..a6b4d0d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.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 __DC_HWSS_DCE110_H__
-+#define __DC_HWSS_DCE110_H__
-+
-+#include "core_types.h"
-+
-+#define GAMMA_HW_POINTS_NUM 256
-+struct core_dc;
-+
-+bool dce110_hw_sequencer_construct(struct core_dc *dc);
-+
-+enum dc_status dce110_apply_ctx_to_hw(
-+ struct core_dc *dc,
-+ struct validate_context *context);
-+
-+void dce110_set_display_clock(struct validate_context *context);
-+
-+void dce110_set_displaymarks(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+void dce110_enable_stream(struct pipe_ctx *pipe_ctx);
-+
-+void dce110_disable_stream(struct pipe_ctx *pipe_ctx);
-+
-+void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
-+ struct dc_link_settings *link_settings);
-+
-+void dce110_update_info_frame(struct pipe_ctx *pipe_ctx);
-+
-+void dce110_enable_accelerated_mode(struct core_dc *dc);
-+
-+void dce110_power_down(struct core_dc *dc);
-+
-+void dce110_update_pending_status(struct pipe_ctx *pipe_ctx);
-+
-+#endif /* __DC_HWSS_DCE110_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
-new file mode 100644
-index 0000000..dd69f60
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
-@@ -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
-+ *
-+ */
-+
-+#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 const 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,
-+};
-+
-+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(TO_DCE110_IPP(*ipp));
-+ *ipp = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
-new file mode 100644
-index 0000000..60eebde
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
-@@ -0,0 +1,76 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "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;
-+};
-+
-+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 */
-+void 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,
-+ enum ipp_degamma_mode mode);
-+
-+void dce110_ipp_program_prescale(
-+ struct input_pixel_processor *ipp,
-+ struct ipp_prescale_params *params);
-+/*
-+ * Helper functions to be resused in other ASICs
-+ */
-+void dce110_helper_select_lut(struct dce110_ipp *ipp110);
-+
-+#endif /*__DC_IPP_DCE110_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c
-new file mode 100644
-index 0000000..95f6ca3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c
-@@ -0,0 +1,253 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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);
-+
-+void 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_hotspot,
-+ position->y_hotspot);
-+
-+ /* unlock cursor registers */
-+ lock(ipp110, false);
-+}
-+
-+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-1, attributes->height-1);
-+
-+ /* 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/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
-new file mode 100644
-index 0000000..79a6a6d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
-@@ -0,0 +1,303 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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
-+};
-+
-+/*PROTOTYPE DECLARATIONS*/
-+static void set_lut_inc(
-+ struct dce110_ipp *ipp110,
-+ uint8_t inc,
-+ bool is_float,
-+ bool is_signed);
-+
-+bool dce110_ipp_set_degamma(
-+ struct input_pixel_processor *ipp,
-+ enum ipp_degamma_mode mode)
-+{
-+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
-+
-+ uint32_t value = 0;
-+
-+ uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0;
-+
-+ ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS ||
-+ mode == IPP_DEGAMMA_MODE_HW_sRGB);
-+
-+ 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, DCP_REG(mmDEGAMMA_CONTROL), value);
-+
-+ return true;
-+}
-+
-+void dce110_ipp_program_prescale(
-+ struct input_pixel_processor *ipp,
-+ struct ipp_prescale_params *params)
-+{
-+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
-+
-+ uint32_t prescale_control = 0;
-+ uint32_t prescale_value = 0;
-+ uint32_t legacy_lut_control = 0;
-+
-+ prescale_control = dm_read_reg(ipp110->base.ctx,
-+ DCP_REG(mmPRESCALE_GRPH_CONTROL));
-+
-+ if (params->mode != IPP_PRESCALE_MODE_BYPASS) {
-+
-+ set_reg_field_value(
-+ prescale_control,
-+ 0,
-+ PRESCALE_GRPH_CONTROL,
-+ GRPH_PRESCALE_BYPASS);
-+
-+ /*
-+ * If prescale is in use, then legacy lut should
-+ * be bypassed
-+ */
-+ legacy_lut_control = dm_read_reg(ipp110->base.ctx,
-+ DCP_REG(mmINPUT_GAMMA_CONTROL));
-+
-+ set_reg_field_value(
-+ legacy_lut_control,
-+ 1,
-+ INPUT_GAMMA_CONTROL,
-+ GRPH_INPUT_GAMMA_MODE);
-+
-+ dm_write_reg(ipp110->base.ctx,
-+ DCP_REG(mmINPUT_GAMMA_CONTROL),
-+ legacy_lut_control);
-+ } else {
-+ set_reg_field_value(
-+ prescale_control,
-+ 1,
-+ PRESCALE_GRPH_CONTROL,
-+ GRPH_PRESCALE_BYPASS);
-+ }
-+
-+ set_reg_field_value(
-+ prescale_value,
-+ params->scale,
-+ PRESCALE_VALUES_GRPH_R,
-+ GRPH_PRESCALE_SCALE_R);
-+
-+ set_reg_field_value(
-+ prescale_value,
-+ params->bias,
-+ PRESCALE_VALUES_GRPH_R,
-+ GRPH_PRESCALE_BIAS_R);
-+
-+ dm_write_reg(ipp110->base.ctx,
-+ DCP_REG(mmPRESCALE_GRPH_CONTROL),
-+ prescale_control);
-+
-+ dm_write_reg(ipp110->base.ctx,
-+ DCP_REG(mmPRESCALE_VALUES_GRPH_R),
-+ prescale_value);
-+
-+ dm_write_reg(ipp110->base.ctx,
-+ DCP_REG(mmPRESCALE_VALUES_GRPH_G),
-+ prescale_value);
-+
-+ dm_write_reg(ipp110->base.ctx,
-+ DCP_REG(mmPRESCALE_VALUES_GRPH_B),
-+ prescale_value);
-+}
-+
-+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);
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c
-new file mode 100644
-index 0000000..c0a68c6
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c
-@@ -0,0 +1,535 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce110_mem_input.h"
-+
-+#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 program_sec_addr(
-+ struct dce110_mem_input *mem_input110,
-+ PHYSICAL_ADDRESS_LOC address)
-+{
-+ uint32_t value = 0;
-+ uint32_t temp;
-+
-+ /*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);
-+
-+ 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;
-+
-+ /*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);
-+
-+ 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);
-+}
-+
-+bool dce110_mem_input_is_flip_pending(struct mem_input *mem_input)
-+{
-+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
-+ uint32_t value;
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE));
-+
-+ if (get_reg_field_value(value, GRPH_UPDATE,
-+ GRPH_SURFACE_UPDATE_PENDING))
-+ return true;
-+
-+ mem_input->current_address = mem_input->request_address;
-+ return false;
-+}
-+
-+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);
-+
-+ uint32_t value = 0;
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL));
-+ if (flip_immediate) {
-+ set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN);
-+ set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN);
-+ } else {
-+ 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);
-+ }
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value);
-+
-+ switch (address->type) {
-+ case PLN_ADDR_TYPE_GRAPHICS:
-+ if (address->grph.addr.quad_part == 0)
-+ break;
-+ program_pri_addr(mem_input110, address->grph.addr);
-+ break;
-+ case PLN_ADDR_TYPE_GRPH_STEREO:
-+ if (address->grph_stereo.left_addr.quad_part == 0
-+ || address->grph_stereo.right_addr.quad_part == 0)
-+ break;
-+ program_pri_addr(mem_input110, address->grph_stereo.left_addr);
-+ program_sec_addr(mem_input110, address->grph_stereo.right_addr);
-+ break;
-+ default:
-+ /* not supported */
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+
-+ mem_input->request_address = *address;
-+ if (flip_immediate)
-+ mem_input->current_address = *address;
-+
-+ return true;
-+}
-+
-+/* Scatter Gather param tables */
-+static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = {
-+ { 8, 64, 64, 8, 8, 1, 4, 0, 0},
-+ { 16, 64, 32, 8, 16, 1, 8, 0, 0},
-+ { 32, 32, 32, 16, 16, 1, 8, 0, 0},
-+ { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
-+};
-+
-+static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = {
-+ { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */
-+ { 16, 256, 8, 2, 0, 1, 0, 0, 0},
-+ { 32, 128, 8, 4, 0, 1, 0, 0, 0},
-+ { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
-+};
-+
-+static const unsigned int dvmm_Hw_Setting_Linear[4][9] = {
-+ { 8, 4096, 1, 8, 0, 1, 0, 0, 0},
-+ { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
-+ { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
-+ { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
-+};
-+
-+/* Helper to get table entry from surface info */
-+static const unsigned int *get_dvmm_hw_setting(
-+ union dc_tiling_info *tiling_info,
-+ enum surface_pixel_format format)
-+{
-+ enum bits_per_pixel {
-+ bpp_8 = 0,
-+ bpp_16,
-+ bpp_32,
-+ bpp_64
-+ } bpp;
-+
-+ if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
-+ bpp = bpp_64;
-+ else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
-+ bpp = bpp_32;
-+ else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
-+ bpp = bpp_16;
-+ else
-+ bpp = bpp_8;
-+
-+ switch (tiling_info->gfx8.array_mode) {
-+ case DC_ARRAY_1D_TILED_THIN1:
-+ case DC_ARRAY_1D_TILED_THICK:
-+ case DC_ARRAY_PRT_TILED_THIN1:
-+ return dvmm_Hw_Setting_1DTiling[bpp];
-+ case DC_ARRAY_2D_TILED_THIN1:
-+ case DC_ARRAY_2D_TILED_THICK:
-+ case DC_ARRAY_2D_TILED_X_THICK:
-+ case DC_ARRAY_PRT_2D_TILED_THIN1:
-+ case DC_ARRAY_PRT_2D_TILED_THICK:
-+ return dvmm_Hw_Setting_2DTiling[bpp];
-+ case DC_ARRAY_LINEAR_GENERAL:
-+ case DC_ARRAY_LINEAR_ALLIGNED:
-+ return dvmm_Hw_Setting_Linear[bpp];
-+ default:
-+ return dvmm_Hw_Setting_2DTiling[bpp];
-+ }
-+}
-+
-+bool dce110_mem_input_program_pte_vm(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ enum dc_rotation_angle rotation)
-+{
-+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
-+ const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format);
-+
-+ unsigned int page_width = 0;
-+ unsigned int page_height = 0;
-+ unsigned int temp_page_width = pte[1];
-+ unsigned int temp_page_height = pte[2];
-+ unsigned int min_pte_before_flip = 0;
-+ uint32_t value = 0;
-+
-+ while ((temp_page_width >>= 1) != 0)
-+ page_width++;
-+ while ((temp_page_height >>= 1) != 0)
-+ page_height++;
-+
-+ switch (rotation) {
-+ case ROTATION_ANGLE_90:
-+ case ROTATION_ANGLE_270:
-+ min_pte_before_flip = pte[4];
-+ break;
-+ default:
-+ min_pte_before_flip = pte[3];
-+ break;
-+ }
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT));
-+ set_reg_field_value(value, 0xff, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL));
-+ set_reg_field_value(value, page_width, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH);
-+ set_reg_field_value(value, page_height, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT);
-+ set_reg_field_value(value, min_pte_before_flip, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL));
-+ set_reg_field_value(value, pte[5], DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK);
-+ set_reg_field_value(value, 0xff, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL), value);
-+
-+ 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.d_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.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);
-+}
-+
-+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);
-+
-+ if (ctx->dc->debug.disable_stutter) {
-+ set_reg_field_value(stutter_cntl,
-+ 0,
-+ DPG_PIPE_STUTTER_CONTROL,
-+ STUTTER_ENABLE);
-+ } else {
-+ 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.d_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);
-+
-+ /*Write watermark set B*/
-+ 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);
-+}
-+
-+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.d_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.a_mark,
-+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK);
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+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 total_dest_line_time_ns)
-+{
-+ struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input);
-+
-+ 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 struct mem_input_funcs dce110_mem_input_funcs = {
-+ .mem_input_program_display_marks =
-+ dce110_mem_input_program_display_marks,
-+ .allocate_mem_input = dce_mem_input_allocate_dmif,
-+ .free_mem_input = dce_mem_input_free_dmif,
-+ .mem_input_program_surface_flip_and_addr =
-+ dce110_mem_input_program_surface_flip_and_addr,
-+ .mem_input_program_pte_vm =
-+ dce110_mem_input_program_pte_vm,
-+ .mem_input_program_surface_config =
-+ dce_mem_input_program_surface_config,
-+ .mem_input_is_flip_pending =
-+ dce110_mem_input_is_flip_pending,
-+ .mem_input_update_dchub = NULL
-+};
-+/*****************************************/
-+/* 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)
-+{
-+ /* supported stutter method
-+ * STUTTER_MODE_ENHANCED
-+ * STUTTER_MODE_QUAD_DMIF_BUFFER
-+ * STUTTER_MODE_WATERMARK_NBP_STATE
-+ */
-+ mem_input110->base.funcs = &dce110_mem_input_funcs;
-+ mem_input110->base.ctx = ctx;
-+
-+ mem_input110->base.inst = inst;
-+
-+ mem_input110->offsets = *offsets;
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h
-new file mode 100644
-index 0000000..83b2df9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h
-@@ -0,0 +1,131 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "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;
-+};
-+
-+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 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 total_dest_line_time_ns);
-+
-+/*
-+ * dce110_allocate_mem_input
-+ *
-+ * This function will allocate a dmif buffer and program required
-+ * pixel duration for pipe
-+ */
-+void dce110_allocate_mem_input(
-+ struct mem_input *mem_input,
-+ uint32_t h_total,/* for current stream */
-+ uint32_t v_total,/* for current stream */
-+ uint32_t pix_clk_khz,/* for current stream */
-+ uint32_t total_stream_num);
-+
-+/*
-+ * dce110_free_mem_input
-+ *
-+ * This function will deallocate a dmif buffer from pipe
-+ */
-+void dce110_free_mem_input(
-+ struct mem_input *mem_input,
-+ uint32_t total_stream_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,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation,
-+ struct dc_plane_dcc_param *dcc,
-+ bool horizontal_mirror);
-+
-+/*
-+ * dce110_mem_input_program_pte_vm
-+ *
-+ * This function will program pte vm registers.
-+ */
-+bool dce110_mem_input_program_pte_vm(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ enum dc_rotation_angle rotation);
-+
-+/*
-+ * dce110_mem_input_is_flip_pending
-+ *
-+ * This function will wait until the surface update-pending bit is cleared.
-+ * This is necessary when a flip immediate call is requested as we shouldn't
-+ * return until the flip has actually occurred.
-+ */
-+bool dce110_mem_input_is_flip_pending(
-+ struct mem_input *mem_input);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
-new file mode 100644
-index 0000000..f0310ba
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
-@@ -0,0 +1,1081 @@
-+/*
-+ * 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"
-+
-+#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 "inc/bandwidth_calcs.h"
-+
-+#include "dce110_mem_input.h"
-+
-+#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 const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = {
-+ {
-+ .dcp = 0,
-+ .dmif = 0,
-+ .pipe = 0,
-+ }
-+};
-+
-+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(mmUNP_FLIP_CONTROL));
-+
-+ set_reg_field_value(value, 1,
-+ UNP_FLIP_CONTROL,
-+ GRPH_SURFACE_UPDATE_PENDING_MODE);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_FLIP_CONTROL),
-+ value);
-+}
-+
-+/* chroma part */
-+static void program_pri_addr_c(
-+ 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 &
-+UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK;
-+
-+ set_reg_field_value(value, temp,
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C,
-+ GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C),
-+ value);
-+
-+ temp = 0;
-+ value = 0;
-+ temp = address.low_part >>
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT;
-+
-+ set_reg_field_value(value, temp,
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C,
-+ GRPH_PRIMARY_SURFACE_ADDRESS_C);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C),
-+ value);
-+}
-+
-+/* luma part */
-+static void program_pri_addr_l(
-+ 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 &
-+UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK;
-+
-+ set_reg_field_value(value, temp,
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
-+ GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L),
-+ value);
-+
-+ temp = 0;
-+ value = 0;
-+ temp = address.low_part >>
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT;
-+
-+ set_reg_field_value(value, temp,
-+ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L,
-+ GRPH_PRIMARY_SURFACE_ADDRESS_L);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L),
-+ 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_l(
-+ mem_input110,
-+ addr->grph.addr);
-+ break;
-+ case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
-+ program_pri_addr_l(
-+ mem_input110,
-+ addr->video_progressive.luma_addr);
-+ program_pri_addr_c(
-+ mem_input110,
-+ addr->video_progressive.chroma_addr);
-+ break;
-+ 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(mmUNP_GRPH_ENABLE));
-+ set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE);
-+ dm_write_reg(mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_ENABLE),
-+ value);
-+}
-+
-+static void program_tiling(
-+ struct dce110_mem_input *mem_input110,
-+ const union dc_tiling_info *info,
-+ const enum surface_pixel_format pixel_format)
-+{
-+ uint32_t value = 0;
-+
-+ set_reg_field_value(value, info->gfx8.num_banks,
-+ UNP_GRPH_CONTROL, GRPH_NUM_BANKS);
-+
-+ set_reg_field_value(value, info->gfx8.bank_width,
-+ UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L);
-+
-+ set_reg_field_value(value, info->gfx8.bank_height,
-+ UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L);
-+
-+ set_reg_field_value(value, info->gfx8.tile_aspect,
-+ UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L);
-+
-+ set_reg_field_value(value, info->gfx8.tile_split,
-+ UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L);
-+
-+ set_reg_field_value(value, info->gfx8.tile_mode,
-+ UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L);
-+
-+ set_reg_field_value(value, info->gfx8.pipe_config,
-+ UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG);
-+
-+ set_reg_field_value(value, info->gfx8.array_mode,
-+ UNP_GRPH_CONTROL, GRPH_ARRAY_MODE);
-+
-+ set_reg_field_value(value, 1,
-+ UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE);
-+
-+ set_reg_field_value(value, 0,
-+ UNP_GRPH_CONTROL, GRPH_Z);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ mmUNP_GRPH_CONTROL,
-+ value);
-+
-+ value = 0;
-+
-+ set_reg_field_value(value, info->gfx8.bank_width_c,
-+ UNP_GRPH_CONTROL_C, GRPH_BANK_WIDTH_C);
-+
-+ set_reg_field_value(value, info->gfx8.bank_height_c,
-+ UNP_GRPH_CONTROL_C, GRPH_BANK_HEIGHT_C);
-+
-+ set_reg_field_value(value, info->gfx8.tile_aspect_c,
-+ UNP_GRPH_CONTROL_C, GRPH_MACRO_TILE_ASPECT_C);
-+
-+ set_reg_field_value(value, info->gfx8.tile_split_c,
-+ UNP_GRPH_CONTROL_C, GRPH_TILE_SPLIT_C);
-+
-+ set_reg_field_value(value, info->gfx8.tile_mode_c,
-+ UNP_GRPH_CONTROL_C, GRPH_MICRO_TILE_MODE_C);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ mmUNP_GRPH_CONTROL_C,
-+ 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.video.luma_size.x;
-+ local_size.video.luma_size.x =
-+ local_size.video.luma_size.y;
-+ local_size.video.luma_size.y = swap;
-+
-+ swap = local_size.video.luma_size.width;
-+ local_size.video.luma_size.width =
-+ local_size.video.luma_size.height;
-+ local_size.video.luma_size.height = swap;
-+
-+ swap = local_size.video.chroma_size.x;
-+ local_size.video.chroma_size.x =
-+ local_size.video.chroma_size.y;
-+ local_size.video.chroma_size.y = swap;
-+
-+ swap = local_size.video.chroma_size.width;
-+ local_size.video.chroma_size.width =
-+ local_size.video.chroma_size.height;
-+ local_size.video.chroma_size.height = swap;
-+ }
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.luma_pitch,
-+ UNP_GRPH_PITCH_L, GRPH_PITCH_L);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PITCH_L),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.chroma_pitch,
-+ UNP_GRPH_PITCH_C, GRPH_PITCH_C);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_PITCH_C),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, 0,
-+ UNP_GRPH_X_START_L, GRPH_X_START_L);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_X_START_L),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, 0,
-+ UNP_GRPH_X_START_C, GRPH_X_START_C);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_X_START_C),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, 0,
-+ UNP_GRPH_Y_START_L, GRPH_Y_START_L);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_Y_START_L),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, 0,
-+ UNP_GRPH_Y_START_C, GRPH_Y_START_C);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_Y_START_C),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.luma_size.x +
-+ local_size.video.luma_size.width,
-+ UNP_GRPH_X_END_L, GRPH_X_END_L);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_X_END_L),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.chroma_size.x +
-+ local_size.video.chroma_size.width,
-+ UNP_GRPH_X_END_C, GRPH_X_END_C);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_X_END_C),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.luma_size.y +
-+ local_size.video.luma_size.height,
-+ UNP_GRPH_Y_END_L, GRPH_Y_END_L);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_Y_END_L),
-+ value);
-+
-+ value = 0;
-+ set_reg_field_value(value, local_size.video.chroma_size.y +
-+ local_size.video.chroma_size.height,
-+ UNP_GRPH_Y_END_C, GRPH_Y_END_C);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_Y_END_C),
-+ value);
-+
-+ value = 0;
-+ switch (rotation) {
-+ case ROTATION_ANGLE_90:
-+ set_reg_field_value(value, 3,
-+ UNP_HW_ROTATION, ROTATION_ANGLE);
-+ break;
-+ case ROTATION_ANGLE_180:
-+ set_reg_field_value(value, 2,
-+ UNP_HW_ROTATION, ROTATION_ANGLE);
-+ break;
-+ case ROTATION_ANGLE_270:
-+ set_reg_field_value(value, 1,
-+ UNP_HW_ROTATION, ROTATION_ANGLE);
-+ break;
-+ default:
-+ set_reg_field_value(value, 0,
-+ UNP_HW_ROTATION, ROTATION_ANGLE);
-+ break;
-+ }
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_HW_ROTATION),
-+ value);
-+}
-+
-+static void program_pixel_format(
-+ struct dce110_mem_input *mem_input110,
-+ enum surface_pixel_format format)
-+{
-+ if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
-+ uint32_t value;
-+ uint8_t grph_depth;
-+ uint8_t grph_format;
-+
-+ value = dm_read_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL));
-+
-+ switch (format) {
-+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
-+ grph_depth = 0;
-+ grph_format = 0;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
-+ grph_depth = 1;
-+ grph_format = 1;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
-+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
-+ grph_depth = 2;
-+ grph_format = 0;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
-+ grph_depth = 2;
-+ grph_format = 1;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
-+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
-+ grph_depth = 3;
-+ grph_format = 0;
-+ break;
-+ default:
-+ grph_depth = 2;
-+ grph_format = 0;
-+ break;
-+ }
-+
-+ set_reg_field_value(
-+ value,
-+ grph_depth,
-+ UNP_GRPH_CONTROL,
-+ GRPH_DEPTH);
-+ set_reg_field_value(
-+ value,
-+ grph_format,
-+ UNP_GRPH_CONTROL,
-+ GRPH_FORMAT);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL),
-+ value);
-+
-+ value = dm_read_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL_EXP));
-+
-+ /* VIDEO FORMAT 0 */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ UNP_GRPH_CONTROL_EXP,
-+ VIDEO_FORMAT);
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL_EXP),
-+ value);
-+
-+ } else {
-+ /* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */
-+ uint32_t value;
-+ uint8_t video_format;
-+
-+ value = dm_read_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL_EXP));
-+
-+ switch (format) {
-+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
-+ video_format = 2;
-+ break;
-+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
-+ video_format = 3;
-+ break;
-+ default:
-+ video_format = 0;
-+ break;
-+ }
-+
-+ set_reg_field_value(
-+ value,
-+ video_format,
-+ UNP_GRPH_CONTROL_EXP,
-+ VIDEO_FORMAT);
-+
-+ dm_write_reg(
-+ mem_input110->base.ctx,
-+ DCP_REG(mmUNP_GRPH_CONTROL_EXP),
-+ value);
-+ }
-+}
-+
-+bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input)
-+{
-+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
-+ uint32_t value;
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_UPDATE));
-+
-+ if (get_reg_field_value(value, UNP_GRPH_UPDATE,
-+ GRPH_SURFACE_UPDATE_PENDING))
-+ return true;
-+
-+ mem_input->current_address = mem_input->request_address;
-+ return false;
-+}
-+
-+bool dce110_mem_input_v_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);
-+
-+ mem_input->request_address = *address;
-+
-+ return true;
-+}
-+
-+/* Scatter Gather param tables */
-+static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = {
-+ { 8, 64, 64, 8, 8, 1, 4, 0, 0},
-+ { 16, 64, 32, 8, 16, 1, 8, 0, 0},
-+ { 32, 32, 32, 16, 16, 1, 8, 0, 0},
-+ { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
-+};
-+
-+static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = {
-+ { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */
-+ { 16, 256, 8, 2, 0, 1, 0, 0, 0},
-+ { 32, 128, 8, 4, 0, 1, 0, 0, 0},
-+ { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
-+};
-+
-+static const unsigned int dvmm_Hw_Setting_Linear[4][9] = {
-+ { 8, 4096, 1, 8, 0, 1, 0, 0, 0},
-+ { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
-+ { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
-+ { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
-+};
-+
-+/* Helper to get table entry from surface info */
-+static const unsigned int *get_dvmm_hw_setting(
-+ union dc_tiling_info *tiling_info,
-+ enum surface_pixel_format format,
-+ bool chroma)
-+{
-+ enum bits_per_pixel {
-+ bpp_8 = 0,
-+ bpp_16,
-+ bpp_32,
-+ bpp_64
-+ } bpp;
-+
-+ if (format >= SURFACE_PIXEL_FORMAT_INVALID)
-+ bpp = bpp_32;
-+ else if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ bpp = chroma ? bpp_16 : bpp_8;
-+ else
-+ bpp = bpp_8;
-+
-+ switch (tiling_info->gfx8.array_mode) {
-+ case DC_ARRAY_1D_TILED_THIN1:
-+ case DC_ARRAY_1D_TILED_THICK:
-+ case DC_ARRAY_PRT_TILED_THIN1:
-+ return dvmm_Hw_Setting_1DTiling[bpp];
-+ case DC_ARRAY_2D_TILED_THIN1:
-+ case DC_ARRAY_2D_TILED_THICK:
-+ case DC_ARRAY_2D_TILED_X_THICK:
-+ case DC_ARRAY_PRT_2D_TILED_THIN1:
-+ case DC_ARRAY_PRT_2D_TILED_THICK:
-+ return dvmm_Hw_Setting_2DTiling[bpp];
-+ case DC_ARRAY_LINEAR_GENERAL:
-+ case DC_ARRAY_LINEAR_ALLIGNED:
-+ return dvmm_Hw_Setting_Linear[bpp];
-+ default:
-+ return dvmm_Hw_Setting_2DTiling[bpp];
-+ }
-+}
-+
-+bool dce110_mem_input_v_program_pte_vm(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ enum dc_rotation_angle rotation)
-+{
-+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
-+ const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false);
-+ const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true);
-+
-+ unsigned int page_width = 0;
-+ unsigned int page_height = 0;
-+ unsigned int page_width_chroma = 0;
-+ unsigned int page_height_chroma = 0;
-+ unsigned int temp_page_width = pte[1];
-+ unsigned int temp_page_height = pte[2];
-+ unsigned int min_pte_before_flip = 0;
-+ unsigned int min_pte_before_flip_chroma = 0;
-+ uint32_t value = 0;
-+
-+ while ((temp_page_width >>= 1) != 0)
-+ page_width++;
-+ while ((temp_page_height >>= 1) != 0)
-+ page_height++;
-+
-+ temp_page_width = pte_chroma[1];
-+ temp_page_height = pte_chroma[2];
-+ while ((temp_page_width >>= 1) != 0)
-+ page_width_chroma++;
-+ while ((temp_page_height >>= 1) != 0)
-+ page_height_chroma++;
-+
-+ switch (rotation) {
-+ case ROTATION_ANGLE_90:
-+ case ROTATION_ANGLE_270:
-+ min_pte_before_flip = pte[4];
-+ min_pte_before_flip_chroma = pte_chroma[4];
-+ break;
-+ default:
-+ min_pte_before_flip = pte[3];
-+ min_pte_before_flip_chroma = pte_chroma[3];
-+ break;
-+ }
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT));
-+ /* TODO: un-hardcode requestlimit */
-+ set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L);
-+ set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL));
-+ set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH);
-+ set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT);
-+ set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL));
-+ set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK);
-+ set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C));
-+ set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C);
-+ set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C);
-+ set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C), value);
-+
-+ value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C));
-+ set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C);
-+ set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C);
-+ dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value);
-+
-+ return true;
-+}
-+
-+bool dce110_mem_input_v_program_surface_config(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation,
-+ struct dc_plane_dcc_param *dcc,
-+ bool horizotal_mirror)
-+{
-+ 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 urgency_addr,
-+ const uint32_t wm_addr,
-+ 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;
-+
-+ /*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,
-+ DPGV0_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,
-+ DPGV0_PIPE_URGENCY_CONTROL,
-+ URGENCY_LOW_WATERMARK);
-+
-+ set_reg_field_value(
-+ urgency_cntl,
-+ total_dest_line_time_ns,
-+ DPGV0_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,
-+ DPGV0_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,
-+ DPGV0_PIPE_URGENCY_CONTROL,
-+ URGENCY_LOW_WATERMARK);
-+
-+ set_reg_field_value(urgency_cntl,
-+ total_dest_line_time_ns,
-+ DPGV0_PIPE_URGENCY_CONTROL,
-+ URGENCY_HIGH_WATERMARK);
-+
-+ dm_write_reg(ctx, urgency_addr, urgency_cntl);
-+}
-+
-+static void program_urgency_watermark_l(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks_low,
-+ uint32_t total_dest_line_time_ns)
-+{
-+ program_urgency_watermark(
-+ ctx,
-+ mmDPGV0_PIPE_URGENCY_CONTROL,
-+ mmDPGV0_WATERMARK_MASK_CONTROL,
-+ marks_low,
-+ total_dest_line_time_ns);
-+}
-+
-+static void program_urgency_watermark_c(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks_low,
-+ uint32_t total_dest_line_time_ns)
-+{
-+ program_urgency_watermark(
-+ ctx,
-+ mmDPGV1_PIPE_URGENCY_CONTROL,
-+ mmDPGV1_WATERMARK_MASK_CONTROL,
-+ marks_low,
-+ total_dest_line_time_ns);
-+}
-+
-+static void program_stutter_watermark(
-+ const struct dc_context *ctx,
-+ const uint32_t stutter_addr,
-+ const uint32_t wm_addr,
-+ struct bw_watermarks marks)
-+{
-+ /* register value */
-+ uint32_t stutter_cntl = 0;
-+ uint32_t wm_mask_cntl = 0;
-+
-+ /*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,
-+ DPGV0_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);
-+
-+ if (ctx->dc->debug.disable_stutter) {
-+ set_reg_field_value(stutter_cntl,
-+ 0,
-+ DPGV0_PIPE_STUTTER_CONTROL,
-+ STUTTER_ENABLE);
-+ } else {
-+ set_reg_field_value(stutter_cntl,
-+ 1,
-+ DPGV0_PIPE_STUTTER_CONTROL,
-+ STUTTER_ENABLE);
-+ }
-+
-+ set_reg_field_value(stutter_cntl,
-+ 1,
-+ DPGV0_PIPE_STUTTER_CONTROL,
-+ STUTTER_IGNORE_FBC);
-+
-+ /*Write watermark set A*/
-+ set_reg_field_value(stutter_cntl,
-+ marks.a_mark,
-+ DPGV0_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,
-+ DPGV0_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);
-+ /*Write watermark set B*/
-+ set_reg_field_value(stutter_cntl,
-+ marks.b_mark,
-+ DPGV0_PIPE_STUTTER_CONTROL,
-+ STUTTER_EXIT_SELF_REFRESH_WATERMARK);
-+ dm_write_reg(ctx, stutter_addr, stutter_cntl);
-+}
-+
-+static void program_stutter_watermark_l(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks)
-+{
-+ program_stutter_watermark(ctx,
-+ mmDPGV0_PIPE_STUTTER_CONTROL,
-+ mmDPGV0_WATERMARK_MASK_CONTROL,
-+ marks);
-+}
-+
-+static void program_stutter_watermark_c(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks)
-+{
-+ program_stutter_watermark(ctx,
-+ mmDPGV1_PIPE_STUTTER_CONTROL,
-+ mmDPGV1_WATERMARK_MASK_CONTROL,
-+ marks);
-+}
-+
-+static void program_nbp_watermark(
-+ const struct dc_context *ctx,
-+ const uint32_t wm_mask_ctrl_addr,
-+ const uint32_t nbp_pstate_ctrl_addr,
-+ struct bw_watermarks marks)
-+{
-+ uint32_t value;
-+
-+ /* Write mask to enable reading/writing of watermark set A */
-+
-+ value = dm_read_reg(ctx, wm_mask_ctrl_addr);
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_WATERMARK_MASK_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK_MASK);
-+ dm_write_reg(ctx, wm_mask_ctrl_addr, value);
-+
-+ value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_ENABLE);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
-+ dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
-+
-+ /* Write watermark set A */
-+ value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
-+ set_reg_field_value(
-+ value,
-+ marks.a_mark,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK);
-+ dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
-+
-+ /* Write mask to enable reading/writing of watermark set B */
-+ value = dm_read_reg(ctx, wm_mask_ctrl_addr);
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ DPGV0_WATERMARK_MASK_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK_MASK);
-+ dm_write_reg(ctx, wm_mask_ctrl_addr, value);
-+
-+ value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_ENABLE);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
-+ dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
-+
-+ /* Write watermark set B */
-+ value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
-+ set_reg_field_value(
-+ value,
-+ marks.b_mark,
-+ DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ NB_PSTATE_CHANGE_WATERMARK);
-+ dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
-+}
-+
-+static void program_nbp_watermark_l(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks)
-+{
-+ program_nbp_watermark(ctx,
-+ mmDPGV0_WATERMARK_MASK_CONTROL,
-+ mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ marks);
-+}
-+
-+static void program_nbp_watermark_c(
-+ const struct dc_context *ctx,
-+ struct bw_watermarks marks)
-+{
-+ program_nbp_watermark(ctx,
-+ mmDPGV1_WATERMARK_MASK_CONTROL,
-+ mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL,
-+ marks);
-+}
-+
-+void dce110_mem_input_v_program_display_marks(
-+ struct mem_input *mem_input,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns)
-+{
-+ program_urgency_watermark_l(
-+ mem_input->ctx,
-+ urgent,
-+ total_dest_line_time_ns);
-+
-+ program_nbp_watermark_l(
-+ mem_input->ctx,
-+ nbp);
-+
-+ program_stutter_watermark_l(
-+ mem_input->ctx,
-+ stutter);
-+
-+}
-+
-+void dce110_mem_input_program_chroma_display_marks(
-+ struct mem_input *mem_input,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns)
-+{
-+ program_urgency_watermark_c(
-+ mem_input->ctx,
-+ urgent,
-+ total_dest_line_time_ns);
-+
-+ program_nbp_watermark_c(
-+ mem_input->ctx,
-+ nbp);
-+
-+ program_stutter_watermark_c(
-+ mem_input->ctx,
-+ stutter);
-+}
-+
-+void dce110_allocate_mem_input_v(
-+ struct mem_input *mi,
-+ uint32_t h_total,/* for current stream */
-+ uint32_t v_total,/* for current stream */
-+ uint32_t pix_clk_khz,/* for current stream */
-+ uint32_t total_stream_num)
-+{
-+ uint32_t addr;
-+ uint32_t value;
-+ uint32_t pix_dur;
-+ if (pix_clk_khz != 0) {
-+ addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1;
-+ value = dm_read_reg(mi->ctx, addr);
-+ pix_dur = 1000000000ULL / pix_clk_khz;
-+ set_reg_field_value(
-+ value,
-+ pix_dur,
-+ DPGV0_PIPE_ARBITRATION_CONTROL1,
-+ PIXEL_DURATION);
-+ dm_write_reg(mi->ctx, addr, value);
-+
-+ addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1;
-+ value = dm_read_reg(mi->ctx, addr);
-+ pix_dur = 1000000000ULL / pix_clk_khz;
-+ set_reg_field_value(
-+ value,
-+ pix_dur,
-+ DPGV1_PIPE_ARBITRATION_CONTROL1,
-+ PIXEL_DURATION);
-+ dm_write_reg(mi->ctx, addr, value);
-+
-+ addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2;
-+ value = 0x4000800;
-+ dm_write_reg(mi->ctx, addr, value);
-+
-+ addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2;
-+ value = 0x4000800;
-+ dm_write_reg(mi->ctx, addr, value);
-+ }
-+
-+}
-+
-+void dce110_free_mem_input_v(
-+ struct mem_input *mi,
-+ uint32_t total_stream_num)
-+{
-+}
-+
-+static struct mem_input_funcs dce110_mem_input_v_funcs = {
-+ .mem_input_program_display_marks =
-+ dce110_mem_input_v_program_display_marks,
-+ .mem_input_program_chroma_display_marks =
-+ dce110_mem_input_program_chroma_display_marks,
-+ .allocate_mem_input = dce110_allocate_mem_input_v,
-+ .free_mem_input = dce110_free_mem_input_v,
-+ .mem_input_program_surface_flip_and_addr =
-+ dce110_mem_input_v_program_surface_flip_and_addr,
-+ .mem_input_program_pte_vm =
-+ dce110_mem_input_v_program_pte_vm,
-+ .mem_input_program_surface_config =
-+ dce110_mem_input_v_program_surface_config,
-+ .mem_input_is_flip_pending =
-+ dce110_mem_input_v_is_surface_pending
-+};
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce110_mem_input_v_construct(
-+ struct dce110_mem_input *mem_input110,
-+ struct dc_context *ctx)
-+{
-+ mem_input110->base.funcs = &dce110_mem_input_v_funcs;
-+ mem_input110->base.ctx = ctx;
-+
-+ mem_input110->base.inst = 0;
-+
-+ mem_input110->offsets = dce110_mi_v_reg_offsets[0];
-+
-+ return true;
-+}
-+
-+#if 0
-+void dce110_mem_input_v_destroy(struct mem_input **mem_input)
-+{
-+ dm_free(TO_DCE110_MEM_INPUT(*mem_input));
-+ *mem_input = NULL;
-+}
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h
-new file mode 100644
-index 0000000..5b1796c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h
-@@ -0,0 +1,94 @@
-+/* 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 __DC_MEM_INPUT_V_DCE110_H__
-+#define __DC_MEM_INPUT_V_DCE110_H__
-+
-+#include "mem_input.h"
-+#include "dce110_mem_input.h"
-+
-+bool dce110_mem_input_v_construct(
-+ struct dce110_mem_input *mem_input110,
-+ struct dc_context *ctx);
-+
-+/*
-+ * This function will program nbp stutter and urgency watermarks to minimum
-+ * allowable values
-+ */
-+void dce110_mem_input_v_program_display_marks(
-+ struct mem_input *mem_input,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns);
-+
-+/*
-+ * This function will allocate a dmif buffer and program required
-+ * pixel duration for pipe
-+ */
-+void dce110_allocate_mem_v_input(
-+ struct mem_input *mem_input,
-+ uint32_t h_total,/* for current stream */
-+ uint32_t v_total,/* for current stream */
-+ uint32_t pix_clk_khz,/* for current stream */
-+ uint32_t total_stream_num);
-+
-+/*
-+ * This function will deallocate a dmif buffer from pipe
-+ */
-+void dce110_free_mem_v_input(
-+ struct mem_input *mem_input,
-+ uint32_t total_stream_num);
-+
-+/*
-+ * This function programs hsync/vsync mode and surface address
-+ */
-+bool dce110_mem_input_v_program_surface_flip_and_addr(
-+ struct mem_input *mem_input,
-+ const struct dc_plane_address *address,
-+ bool flip_immediate);
-+
-+/*
-+ * dce110_mem_input_v_program_scatter_gather
-+ *
-+ * This function will program scatter gather registers.
-+ */
-+bool dce110_mem_input_v_program_pte_vm(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ enum dc_rotation_angle rotation);
-+
-+/*
-+ * This function will program surface tiling, size, rotation and pixel format
-+ * to corresponding dcp registers.
-+ */
-+bool dce110_mem_input_v_program_surface_config(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c
-new file mode 100644
-index 0000000..698ec2f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.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"
-+
-+/* 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
-+};
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+static const struct opp_funcs funcs = {
-+ .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
-+ .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_program_regamma_pwl = dce110_opp_program_regamma_pwl,
-+ .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
-+ .opp_destroy = dce110_opp_destroy,
-+ .opp_program_fmt = dce110_opp_program_fmt,
-+};
-+
-+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;
-+
-+ return true;
-+}
-+
-+void dce110_opp_destroy(struct output_pixel_processor **opp)
-+{
-+ dm_free(FROM_DCE11_OPP(*opp));
-+ *opp = NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h
-new file mode 100644
-index 0000000..2fbb241
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h
-@@ -0,0 +1,149 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "opp.h"
-+#include "core_types.h"
-+
-+#include "gamma_types.h" /* decprecated */
-+
-+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;
-+ 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 fmt_mem_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_program_regamma_pwl(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params);
-+
-+void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
-+ enum opp_regamma mode);
-+
-+void dce110_opp_set_csc_adjustment(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry);
-+
-+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 dc_color_space color_sp,
-+ enum dc_color_depth color_dpth,
-+ enum signal_type signal);
-+
-+void dce110_opp_program_fmt(
-+ struct output_pixel_processor *opp,
-+ struct bit_depth_reduction_params *fmt_bit_depth,
-+ struct clamping_and_pixel_encoding_params *clamping);
-+
-+void dce110_opp_set_clamping(
-+ struct dce110_opp *opp110,
-+ const struct clamping_and_pixel_encoding_params *params);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c
-new file mode 100644
-index 0000000..b46db20
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c
-@@ -0,0 +1,363 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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
-+};
-+
-+static const struct out_csc_color_matrix global_color_matrix[] = {
-+{ COLOR_SPACE_SRGB,
-+ { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-+{ COLOR_SPACE_SRGB_LIMITED,
-+ { 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} },
-+/* TODO: correct values below */
-+{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
-+ 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
-+{ COLOR_SPACE_YCBCR709_LIMITED, { 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);
-+ }
-+}
-+
-+static bool configure_graphics_mode(
-+ struct dce110_opp *opp110,
-+ enum csc_color_mode config,
-+ enum graphics_csc_adjust_type csc_adjust_type,
-+ enum dc_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:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_GRPH_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_GRPH_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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 out_csc_color_matrix *tbl_entry)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+ enum csc_color_mode config =
-+ CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
-+
-+ program_color_matrix(
-+ opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
-+
-+ /* We did everything ,now program DxOUTPUT_CSC_CONTROL */
-+ configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
-+ tbl_entry->color_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->out_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->out_color_space);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
-new file mode 100644
-index 0000000..975466f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
-@@ -0,0 +1,738 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+#include "dce/dce_11_0_enum.h"
-+
-+enum {
-+ OUTPUT_CSC_MATRIX_SIZE = 12
-+};
-+
-+/* constrast:0 - 2.0, default 1.0 */
-+#define UNDERLAY_CONTRAST_DEFAULT 100
-+#define UNDERLAY_CONTRAST_MAX 200
-+#define UNDERLAY_CONTRAST_MIN 0
-+#define UNDERLAY_CONTRAST_STEP 1
-+#define UNDERLAY_CONTRAST_DIVIDER 100
-+
-+/* Saturation: 0 - 2.0; default 1.0 */
-+#define UNDERLAY_SATURATION_DEFAULT 100 /*1.00*/
-+#define UNDERLAY_SATURATION_MIN 0
-+#define UNDERLAY_SATURATION_MAX 200 /* 2.00 */
-+#define UNDERLAY_SATURATION_STEP 1 /* 0.01 */
-+/*actual max overlay saturation
-+ * value = UNDERLAY_SATURATION_MAX /UNDERLAY_SATURATION_DIVIDER
-+ */
-+
-+/* Hue */
-+#define UNDERLAY_HUE_DEFAULT 0
-+#define UNDERLAY_HUE_MIN -300
-+#define UNDERLAY_HUE_MAX 300
-+#define UNDERLAY_HUE_STEP 5
-+#define UNDERLAY_HUE_DIVIDER 10 /* HW range: -30 ~ +30 */
-+#define UNDERLAY_SATURATION_DIVIDER 100
-+
-+/* Brightness: in DAL usually -.25 ~ .25.
-+ * In MMD is -100 to +100 in 16-235 range; which when scaled to full range is
-+ * ~-116 to +116. When normalized this is about 0.4566.
-+ * With 100 divider this becomes 46, but we may use another for better precision
-+ * The ideal one is 100/219 ((100/255)*(255/219)),
-+ * i.e. min/max = +-100, divider = 219
-+ * default 0.0
-+ */
-+#define UNDERLAY_BRIGHTNESS_DEFAULT 0
-+#define UNDERLAY_BRIGHTNESS_MIN -46 /* ~116/255 */
-+#define UNDERLAY_BRIGHTNESS_MAX 46
-+#define UNDERLAY_BRIGHTNESS_STEP 1 /* .01 */
-+#define UNDERLAY_BRIGHTNESS_DIVIDER 100
-+
-+static const struct out_csc_color_matrix global_color_matrix[] = {
-+{ COLOR_SPACE_SRGB,
-+ { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-+{ COLOR_SPACE_SRGB_LIMITED,
-+ { 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} },
-+/* TODO: correct values below */
-+{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
-+ 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
-+{ COLOR_SPACE_YCBCR709_LIMITED, { 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_v(
-+ 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 cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL);
-+ bool use_set_a = (get_reg_field_value(cntl_value,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE) != 4);
-+
-+ set_reg_field_value(
-+ cntl_value,
-+ 0,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+
-+ if (use_set_a) {
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C11_C12_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[0],
-+ OUTPUT_CSC_C11_C12_A,
-+ OUTPUT_CSC_C11_A);
-+
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[1],
-+ OUTPUT_CSC_C11_C12_A,
-+ OUTPUT_CSC_C12_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C13_C14_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[2],
-+ OUTPUT_CSC_C13_C14_A,
-+ OUTPUT_CSC_C13_A);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[3],
-+ OUTPUT_CSC_C13_C14_A,
-+ OUTPUT_CSC_C14_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C21_C22_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[4],
-+ OUTPUT_CSC_C21_C22_A,
-+ OUTPUT_CSC_C21_A);
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[5],
-+ OUTPUT_CSC_C21_C22_A,
-+ OUTPUT_CSC_C22_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C23_C24_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[6],
-+ OUTPUT_CSC_C23_C24_A,
-+ OUTPUT_CSC_C23_A);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[7],
-+ OUTPUT_CSC_C23_C24_A,
-+ OUTPUT_CSC_C24_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C31_C32_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[8],
-+ OUTPUT_CSC_C31_C32_A,
-+ OUTPUT_CSC_C31_A);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[9],
-+ OUTPUT_CSC_C31_C32_A,
-+ OUTPUT_CSC_C32_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C33_C34_A;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[10],
-+ OUTPUT_CSC_C33_C34_A,
-+ OUTPUT_CSC_C33_A);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[11],
-+ OUTPUT_CSC_C33_C34_A,
-+ OUTPUT_CSC_C34_A);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ set_reg_field_value(
-+ cntl_value,
-+ 4,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ } else {
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C11_C12_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[0],
-+ OUTPUT_CSC_C11_C12_B,
-+ OUTPUT_CSC_C11_B);
-+
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[1],
-+ OUTPUT_CSC_C11_C12_B,
-+ OUTPUT_CSC_C12_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C13_C14_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[2],
-+ OUTPUT_CSC_C13_C14_B,
-+ OUTPUT_CSC_C13_B);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[3],
-+ OUTPUT_CSC_C13_C14_B,
-+ OUTPUT_CSC_C14_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C21_C22_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[4],
-+ OUTPUT_CSC_C21_C22_B,
-+ OUTPUT_CSC_C21_B);
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[5],
-+ OUTPUT_CSC_C21_C22_B,
-+ OUTPUT_CSC_C22_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C23_C24_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[6],
-+ OUTPUT_CSC_C23_C24_B,
-+ OUTPUT_CSC_C23_B);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[7],
-+ OUTPUT_CSC_C23_C24_B,
-+ OUTPUT_CSC_C24_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C31_C32_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[8],
-+ OUTPUT_CSC_C31_C32_B,
-+ OUTPUT_CSC_C31_B);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[9],
-+ OUTPUT_CSC_C31_C32_B,
-+ OUTPUT_CSC_C32_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ {
-+ uint32_t value = 0;
-+ uint32_t addr = mmOUTPUT_CSC_C33_C34_B;
-+ /* fixed S2.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[10],
-+ OUTPUT_CSC_C33_C34_B,
-+ OUTPUT_CSC_C33_B);
-+ /* fixed S0.13 format */
-+ set_reg_field_value(
-+ value,
-+ tbl_entry->regval[11],
-+ OUTPUT_CSC_C33_C34_B,
-+ OUTPUT_CSC_C34_B);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ set_reg_field_value(
-+ cntl_value,
-+ 5,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ }
-+
-+ dm_write_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL, cntl_value);
-+}
-+
-+static bool configure_graphics_mode_v(
-+ struct dce110_opp *opp110,
-+ enum csc_color_mode config,
-+ enum graphics_csc_adjust_type csc_adjust_type,
-+ enum dc_color_space color_space)
-+{
-+ struct dc_context *ctx = opp110->base.ctx;
-+ uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL;
-+ uint32_t value = dm_read_reg(ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+
-+ if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
-+ if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC)
-+ return true;
-+
-+ switch (color_space) {
-+ case COLOR_SPACE_SRGB:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* not supported for underlay on CZ */
-+ return false;
-+
-+ case COLOR_SPACE_YCBCR601:
-+ case COLOR_SPACE_YPBPR601:
-+ case COLOR_SPACE_YCBCR601_LIMITED:
-+ /* YCbCr601 */
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ case COLOR_SPACE_YCBCR709:
-+ case COLOR_SPACE_YPBPR709:
-+ case COLOR_SPACE_YCBCR709_LIMITED:
-+ /* YCbCr709 */
-+ set_reg_field_value(
-+ value,
-+ 3,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ default:
-+ return false;
-+ }
-+
-+ } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
-+ switch (color_space) {
-+ case COLOR_SPACE_SRGB:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* not supported for underlay on CZ */
-+ return false;
-+ case COLOR_SPACE_YCBCR601:
-+ case COLOR_SPACE_YPBPR601:
-+ case COLOR_SPACE_YCBCR601_LIMITED:
-+ /* YCbCr601 */
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ case COLOR_SPACE_YCBCR709:
-+ case COLOR_SPACE_YPBPR709:
-+ case COLOR_SPACE_YCBCR709_LIMITED:
-+ /* YCbCr709 */
-+ set_reg_field_value(
-+ value,
-+ 3,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+ break;
-+ default:
-+ return false;
-+ }
-+
-+ } else
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ COL_MAN_OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_MODE);
-+
-+ addr = mmCOL_MAN_OUTPUT_CSC_CONTROL;
-+ dm_write_reg(ctx, addr, value);
-+
-+ return true;
-+}
-+
-+/*TODO: color depth is not correct when this is called*/
-+static void set_Denormalization(struct output_pixel_processor *opp,
-+ enum dc_color_depth color_depth)
-+{
-+ uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL);
-+
-+ switch (color_depth) {
-+ case COLOR_DEPTH_888:
-+ /* 255/256 for 8 bit output color depth */
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DENORM_CLAMP_CONTROL,
-+ DENORM_MODE);
-+ break;
-+ case COLOR_DEPTH_101010:
-+ /* 1023/1024 for 10 bit output color depth */
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ DENORM_CLAMP_CONTROL,
-+ DENORM_MODE);
-+ break;
-+ case COLOR_DEPTH_121212:
-+ /* 4095/4096 for 12 bit output color depth */
-+ set_reg_field_value(
-+ value,
-+ 3,
-+ DENORM_CLAMP_CONTROL,
-+ DENORM_MODE);
-+ break;
-+ default:
-+ /* not valid case */
-+ break;
-+ }
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DENORM_CLAMP_CONTROL,
-+ DENORM_10BIT_OUT);
-+
-+ dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value);
-+}
-+
-+struct input_csc_matrix {
-+ enum dc_color_space color_space;
-+ uint32_t regval[12];
-+};
-+
-+static const struct input_csc_matrix input_csc_matrix[] = {
-+ {COLOR_SPACE_SRGB,
-+/*1_1 1_2 1_3 1_4 2_1 2_2 2_3 2_4 3_1 3_2 3_3 3_4 */
-+ {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-+ {COLOR_SPACE_SRGB_LIMITED,
-+ {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-+ {COLOR_SPACE_YCBCR601,
-+ {0x2cdd, 0x2000, 0x0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
-+ 0x0, 0x2000, 0x38b4, 0xe3a6} },
-+ {COLOR_SPACE_YCBCR601_LIMITED,
-+ {0x3353, 0x2568, 0x0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
-+ 0x0, 0x2568, 0x40de, 0xdd3a} },
-+ {COLOR_SPACE_YCBCR709,
-+ {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
-+ 0x2000, 0x3b61, 0xe24f} },
-+ {COLOR_SPACE_YCBCR709_LIMITED,
-+ {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
-+ 0x2568, 0x43ee, 0xdbb2} }
-+};
-+
-+static void program_input_csc(
-+ struct output_pixel_processor *opp, enum dc_color_space color_space)
-+{
-+ int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix);
-+ struct dc_context *ctx = opp->ctx;
-+ const uint32_t *regval = NULL;
-+ bool use_set_a;
-+ uint32_t value;
-+ int i;
-+
-+ for (i = 0; i < arr_size; i++)
-+ if (input_csc_matrix[i].color_space == color_space) {
-+ regval = input_csc_matrix[i].regval;
-+ break;
-+ }
-+ if (regval == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ /*
-+ * 1 == set A, the logic is 'if currently we're not using set A,
-+ * then use set A, otherwise use set B'
-+ */
-+ value = dm_read_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL);
-+ use_set_a = get_reg_field_value(
-+ value, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_MODE) != 1;
-+
-+ if (use_set_a) {
-+ /* fixed S2.13 format */
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[0], INPUT_CSC_C11_C12_A, INPUT_CSC_C11_A);
-+ set_reg_field_value(
-+ value, regval[1], INPUT_CSC_C11_C12_A, INPUT_CSC_C12_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C11_C12_A, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[2], INPUT_CSC_C13_C14_A, INPUT_CSC_C13_A);
-+ set_reg_field_value(
-+ value, regval[3], INPUT_CSC_C13_C14_A, INPUT_CSC_C14_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C13_C14_A, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[4], INPUT_CSC_C21_C22_A, INPUT_CSC_C21_A);
-+ set_reg_field_value(
-+ value, regval[5], INPUT_CSC_C21_C22_A, INPUT_CSC_C22_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C21_C22_A, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[6], INPUT_CSC_C23_C24_A, INPUT_CSC_C23_A);
-+ set_reg_field_value(
-+ value, regval[7], INPUT_CSC_C23_C24_A, INPUT_CSC_C24_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C23_C24_A, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[8], INPUT_CSC_C31_C32_A, INPUT_CSC_C31_A);
-+ set_reg_field_value(
-+ value, regval[9], INPUT_CSC_C31_C32_A, INPUT_CSC_C32_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C31_C32_A, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[10], INPUT_CSC_C33_C34_A, INPUT_CSC_C33_A);
-+ set_reg_field_value(
-+ value, regval[11], INPUT_CSC_C33_C34_A, INPUT_CSC_C34_A);
-+ dm_write_reg(ctx, mmINPUT_CSC_C33_C34_A, value);
-+ } else {
-+ /* fixed S2.13 format */
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[0], INPUT_CSC_C11_C12_B, INPUT_CSC_C11_B);
-+ set_reg_field_value(
-+ value, regval[1], INPUT_CSC_C11_C12_B, INPUT_CSC_C12_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C11_C12_B, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[2], INPUT_CSC_C13_C14_B, INPUT_CSC_C13_B);
-+ set_reg_field_value(
-+ value, regval[3], INPUT_CSC_C13_C14_B, INPUT_CSC_C14_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C13_C14_B, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[4], INPUT_CSC_C21_C22_B, INPUT_CSC_C21_B);
-+ set_reg_field_value(
-+ value, regval[5], INPUT_CSC_C21_C22_B, INPUT_CSC_C22_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C21_C22_B, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[6], INPUT_CSC_C23_C24_B, INPUT_CSC_C23_B);
-+ set_reg_field_value(
-+ value, regval[7], INPUT_CSC_C23_C24_B, INPUT_CSC_C24_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C23_C24_B, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[8], INPUT_CSC_C31_C32_B, INPUT_CSC_C31_B);
-+ set_reg_field_value(
-+ value, regval[9], INPUT_CSC_C31_C32_B, INPUT_CSC_C32_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C31_C32_B, value);
-+
-+ value = 0;
-+ set_reg_field_value(
-+ value, regval[10], INPUT_CSC_C33_C34_B, INPUT_CSC_C33_B);
-+ set_reg_field_value(
-+ value, regval[11], INPUT_CSC_C33_C34_B, INPUT_CSC_C34_B);
-+ dm_write_reg(ctx, mmINPUT_CSC_C33_C34_B, value);
-+ }
-+
-+ /* KK: leave INPUT_CSC_CONVERSION_MODE at default */
-+ value = 0;
-+ /*
-+ * select 8.4 input type instead of default 12.0. From the discussion
-+ * with HW team, this format depends on the UNP surface format, so for
-+ * 8-bit we should select 8.4 (4 bits truncated). For 10 it should be
-+ * 10.2. For Carrizo we only support 8-bit surfaces on underlay pipe
-+ * so we can always keep this at 8.4 (input_type=2). If the later asics
-+ * start supporting 10+ bits, we will have a problem: surface
-+ * programming including UNP_GRPH* is being done in DalISR after this,
-+ * so either we pass surface format to here, or move this logic to ISR
-+ */
-+
-+ set_reg_field_value(
-+ value, 2, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_INPUT_TYPE);
-+ set_reg_field_value(
-+ value,
-+ use_set_a ? 1 : 2,
-+ COL_MAN_INPUT_CSC_CONTROL,
-+ INPUT_CSC_MODE);
-+
-+ dm_write_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL, value);
-+}
-+
-+void dce110_opp_v_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->out_color_space)
-+ continue;
-+ /* program the matrix with default values from this
-+ * file
-+ */
-+ program_color_matrix_v(opp110, elm, option);
-+ config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
-+ break;
-+ }
-+ }
-+
-+ program_input_csc(opp, default_adjust->in_color_space);
-+
-+ /* 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_v(opp110, config,
-+ default_adjust->csc_adjust_type,
-+ default_adjust->out_color_space);
-+
-+ set_Denormalization(opp, default_adjust->color_depth);
-+}
-+
-+void dce110_opp_v_set_csc_adjustment(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+ enum csc_color_mode config =
-+ CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
-+
-+ program_color_matrix_v(
-+ opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
-+
-+ /* We did everything ,now program DxOUTPUT_CSC_CONTROL */
-+ configure_graphics_mode_v(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
-+ tbl_entry->color_space);
-+
-+ /*TODO: Check if denormalization is needed*/
-+ /*set_Denormalization(opp, adjust->color_depth);*/
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c
-new file mode 100644
-index 0000000..eac2077
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c
-@@ -0,0 +1,627 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_FRAME_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
-+ */
-+void dce110_opp_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);
-+
-+ dce110_opp_set_clamping(opp110, params);
-+ set_pixel_encoding(opp110, params);
-+}
-+
-+void dce110_opp_set_dyn_expansion(
-+ struct output_pixel_processor *opp,
-+ enum dc_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)
-+ 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);
-+}
-+
-+void dce110_opp_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 */
-+ dce110_opp_program_bit_depth_reduction(
-+ opp,
-+ fmt_bit_depth);
-+
-+ dce110_opp_program_clamping_and_pixel_encoding(
-+ opp,
-+ clamping);
-+
-+ return;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c
-new file mode 100644
-index 0000000..62051ab
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c
-@@ -0,0 +1,537 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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
-+
-+};
-+
-+/*
-+ *****************************************************************************
-+ * 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,
-+ const struct pwl_params *params)
-+{
-+ const struct gamma_curve *curve;
-+ uint32_t value = 0;
-+
-+ {
-+ set_reg_field_value(
-+ value,
-+ params->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,
-+ params->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,
-+ params->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,
-+ params->arr_points[2].custom_float_slope,
-+ REGAMMA_CNTLA_END_CNTL2,
-+ REGAMMA_CNTLA_EXP_REGION_END_BASE);
-+
-+ set_reg_field_value(
-+ value,
-+ params->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 = params->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 pwl_params *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) {
-+ dm_logger_write(opp110->base.ctx->logger, LOG_WARNING,
-+ "%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;
-+
-+ const struct pwl_result_data *rgb = params->rgb_resulted;
-+
-+ while (i != params->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);
-+}
-+
-+bool dce110_opp_program_regamma_pwl(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+
-+ /* Setup regions */
-+ regamma_config_regions_and_segments(opp110, params);
-+
-+ /* Program PWL */
-+ program_pwl(opp110, params);
-+
-+ return true;
-+}
-+
-+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);
-+}
-+
-+void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
-+ enum opp_regamma mode)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+ uint32_t value = dm_read_reg(opp110->base.ctx,
-+ DCP_REG(mmREGAMMA_CONTROL));
-+
-+ set_reg_field_value(
-+ value,
-+ mode,
-+ REGAMMA_CONTROL,
-+ GRPH_REGAMMA_MODE);
-+
-+ dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL),
-+ value);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
-new file mode 100644
-index 0000000..3b3a917
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
-@@ -0,0 +1,551 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+
-+static void power_on_lut(struct output_pixel_processor *opp,
-+ bool power_on, bool inputgamma, bool regamma)
-+{
-+ uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL);
-+ int i;
-+
-+ if (power_on) {
-+ if (inputgamma)
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
-+ if (regamma)
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
-+ } else {
-+ if (inputgamma)
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
-+ if (regamma)
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
-+ }
-+
-+ dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value);
-+
-+ for (i = 0; i < 3; i++) {
-+ value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL);
-+ if (get_reg_field_value(value,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) &&
-+ get_reg_field_value(value,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_GAMMA_CORR_MEM_PWR_DIS))
-+ break;
-+
-+ udelay(2);
-+ }
-+}
-+
-+static void set_bypass_input_gamma(struct dce110_opp *opp110)
-+{
-+ uint32_t value;
-+
-+ value = dm_read_reg(opp110->base.ctx,
-+ mmCOL_MAN_INPUT_GAMMA_CONTROL1);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ COL_MAN_INPUT_GAMMA_CONTROL1,
-+ INPUT_GAMMA_MODE);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmCOL_MAN_INPUT_GAMMA_CONTROL1, value);
-+}
-+
-+static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode)
-+{
-+ uint32_t value = 0;
-+
-+ set_reg_field_value(
-+ value,
-+ mode,
-+ GAMMA_CORR_CONTROL,
-+ GAMMA_CORR_MODE);
-+
-+ dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0);
-+}
-+
-+/*
-+ *****************************************************************************
-+ * 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, const struct pwl_params *params)
-+{
-+ const struct gamma_curve *curve;
-+ uint32_t value = 0;
-+
-+ {
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[0].custom_float_x,
-+ GAMMA_CORR_CNTLA_START_CNTL,
-+ GAMMA_CORR_CNTLA_EXP_REGION_START);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ GAMMA_CORR_CNTLA_START_CNTL,
-+ GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT);
-+
-+ dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL,
-+ value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[0].custom_float_slope,
-+ GAMMA_CORR_CNTLA_SLOPE_CNTL,
-+ GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[1].custom_float_x,
-+ GAMMA_CORR_CNTLA_END_CNTL1,
-+ GAMMA_CORR_CNTLA_EXP_REGION_END);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_END_CNTL1, value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[2].custom_float_slope,
-+ GAMMA_CORR_CNTLA_END_CNTL2,
-+ GAMMA_CORR_CNTLA_EXP_REGION_END_BASE);
-+
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[1].custom_float_y,
-+ GAMMA_CORR_CNTLA_END_CNTL2,
-+ GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_END_CNTL2, value);
-+ }
-+
-+ curve = params->arr_curve_points;
-+
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_0_1,
-+ GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_0_1,
-+ GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_0_1,
-+ GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_0_1,
-+ GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS);
-+
-+ dm_write_reg(
-+ opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_0_1,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_2_3,
-+ GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_2_3,
-+ GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_2_3,
-+ GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_2_3,
-+ GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_2_3,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_4_5,
-+ GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_4_5,
-+ GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_4_5,
-+ GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_4_5,
-+ GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_4_5,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_6_7,
-+ GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_6_7,
-+ GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_6_7,
-+ GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_6_7,
-+ GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_6_7,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_8_9,
-+ GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_8_9,
-+ GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_8_9,
-+ GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_8_9,
-+ GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_8_9,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_10_11,
-+ GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_10_11,
-+ GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_10_11,
-+ GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_10_11,
-+ GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_10_11,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_12_13,
-+ GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_12_13,
-+ GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_12_13,
-+ GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_12_13,
-+ GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_12_13,
-+ value);
-+ }
-+
-+ curve += 2;
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ curve[0].offset,
-+ GAMMA_CORR_CNTLA_REGION_14_15,
-+ GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[0].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_14_15,
-+ GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].offset,
-+ GAMMA_CORR_CNTLA_REGION_14_15,
-+ GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET);
-+
-+ set_reg_field_value(
-+ value,
-+ curve[1].segments_num,
-+ GAMMA_CORR_CNTLA_REGION_14_15,
-+ GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_CNTLA_REGION_14_15,
-+ value);
-+ }
-+}
-+
-+static void program_pwl(struct dce110_opp *opp110,
-+ const struct pwl_params *params)
-+{
-+ uint32_t value = 0;
-+
-+ set_reg_field_value(
-+ value,
-+ 7,
-+ GAMMA_CORR_LUT_WRITE_EN_MASK,
-+ GAMMA_CORR_LUT_WRITE_EN_MASK);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_LUT_WRITE_EN_MASK, value);
-+
-+ dm_write_reg(opp110->base.ctx,
-+ mmGAMMA_CORR_LUT_INDEX, 0);
-+
-+ /* Program REGAMMA_LUT_DATA */
-+ {
-+ const uint32_t addr = mmGAMMA_CORR_LUT_DATA;
-+ uint32_t i = 0;
-+ const struct pwl_result_data *rgb =
-+ params->rgb_resulted;
-+
-+ while (i != params->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;
-+ }
-+ }
-+}
-+
-+bool dce110_opp_program_regamma_pwl_v(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+
-+ /* Setup regions */
-+ regamma_config_regions_and_segments(opp110, params);
-+
-+ set_bypass_input_gamma(opp110);
-+
-+ /* Power on gamma LUT memory */
-+ power_on_lut(opp, true, false, true);
-+
-+ /* Program PWL */
-+ program_pwl(opp110, params);
-+
-+ /* program regamma config */
-+ configure_regamma_mode(opp110, 1);
-+
-+ /* Power return to auto back */
-+ power_on_lut(opp, false, false, true);
-+
-+ return true;
-+}
-+
-+void dce110_opp_power_on_regamma_lut_v(
-+ struct output_pixel_processor *opp,
-+ bool power_on)
-+{
-+ uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_GAMMA_CORR_MEM_PWR_FORCE);
-+
-+ set_reg_field_value(
-+ value,
-+ power_on,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE);
-+
-+ set_reg_field_value(
-+ value,
-+ power_on,
-+ DCFEV_MEM_PWR_CTRL,
-+ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
-+
-+ dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
-new file mode 100644
-index 0000000..4b32397
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
-@@ -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
-+ *
-+ */
-+
-+#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 "dce110_opp_v.h"
-+
-+#include "gamma_types.h"
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+static const struct opp_funcs funcs = {
-+ .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v,
-+ .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v,
-+ .opp_set_csc_default = dce110_opp_v_set_csc_default,
-+ .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment,
-+ .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
-+ .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
-+ .opp_destroy = dce110_opp_destroy,
-+ .opp_program_fmt = dce110_opp_program_fmt,
-+ .opp_program_bit_depth_reduction =
-+ dce110_opp_program_bit_depth_reduction
-+};
-+
-+bool dce110_opp_v_construct(struct dce110_opp *opp110,
-+ struct dc_context *ctx)
-+{
-+ opp110->base.funcs = &funcs;
-+
-+ opp110->base.ctx = ctx;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h
-new file mode 100644
-index 0000000..dcdbf86
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.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 __DC_OPP_DCE110_V_H__
-+#define __DC_OPP_DCE110_V_H__
-+
-+#include "dc_types.h"
-+#include "opp.h"
-+#include "core_types.h"
-+
-+#include "gamma_types.h" /* decprecated */
-+
-+struct gamma_parameters;
-+
-+bool dce110_opp_v_construct(struct dce110_opp *opp110,
-+ struct dc_context *ctx);
-+
-+/* underlay callbacks */
-+void dce110_opp_v_set_csc_default(
-+ struct output_pixel_processor *opp,
-+ const struct default_adjustment *default_adjust);
-+
-+void dce110_opp_v_set_csc_adjustment(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry);
-+
-+bool dce110_opp_program_regamma_pwl_v(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params);
-+
-+void dce110_opp_power_on_regamma_lut_v(
-+ struct output_pixel_processor *opp,
-+ bool power_on);
-+
-+#endif /* __DC_OPP_DCE110_V_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
-new file mode 100644
-index 0000000..959467f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
-@@ -0,0 +1,1413 @@
-+/*
-+* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce110/dce110_resource.h"
-+
-+#include "include/irq_service_interface.h"
-+#include "dce/dce_audio.h"
-+#include "dce110/dce110_timing_generator.h"
-+#include "irq/dce110/irq_service_dce110.h"
-+#include "dce110/dce110_timing_generator_v.h"
-+#include "dce/dce_link_encoder.h"
-+#include "dce/dce_stream_encoder.h"
-+#include "dce110/dce110_mem_input.h"
-+#include "dce110/dce110_mem_input_v.h"
-+#include "dce110/dce110_ipp.h"
-+#include "dce/dce_transform.h"
-+#include "dce110/dce110_transform_v.h"
-+#include "dce110/dce110_opp.h"
-+#include "dce110/dce110_opp_v.h"
-+#include "dce/dce_clock_source.h"
-+#include "dce/dce_hwseq.h"
-+#include "dce110/dce110_hw_sequencer.h"
-+
-+#include "reg_helper.h"
-+
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
-+#include "gmc/gmc_8_2_d.h"
-+#include "gmc/gmc_8_2_sh_mask.h"
-+#endif
-+
-+#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
-+
-+#ifndef mmBIOS_SCRATCH_2
-+ #define mmBIOS_SCRATCH_2 0x05CB
-+ #define mmBIOS_SCRATCH_6 0x05CF
-+#endif
-+
-+#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
-+ #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC
-+ #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC
-+ #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC
-+ #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC
-+ #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC
-+ #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC
-+#endif
-+
-+#ifndef mmDP_DPHY_FAST_TRAINING
-+ #define mmDP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
-+ #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
-+ #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
-+ #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
-+ #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
-+ #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
-+#endif
-+
-+#ifndef DPHY_RX_FAST_TRAINING_CAPABLE
-+ #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1
-+#endif
-+
-+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_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),
-+}
-+};
-+
-+
-+
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+
-+#define transform_regs(id)\
-+[id] = {\
-+ XFM_COMMON_REG_LIST_DCE110(id)\
-+}
-+
-+static const struct dce_transform_registers xfm_regs[] = {
-+ transform_regs(0),
-+ transform_regs(1),
-+ transform_regs(2)
-+};
-+
-+static const struct dce_transform_shift xfm_shift = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce_transform_mask xfm_mask = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_REG_LIST(id)\
-+}
-+
-+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 hpd_regs(id)\
-+[id] = {\
-+ HPD_REG_LIST(id)\
-+}
-+
-+static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
-+ hpd_regs(0),
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5)
-+};
-+
-+
-+#define link_regs(id)\
-+[id] = {\
-+ LE_DCE110_REG_LIST(id)\
-+}
-+
-+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] = {\
-+ SE_COMMON_REG_LIST(id),\
-+ .TMDS_CNTL = 0,\
-+}
-+
-+static const struct dce110_stream_enc_registers stream_enc_regs[] = {
-+ stream_enc_regs(0),
-+ stream_enc_regs(1),
-+ stream_enc_regs(2)
-+};
-+
-+static const struct dce_stream_encoder_shift se_shift = {
-+ SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce_stream_encoder_mask se_mask = {
-+ SE_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+#define audio_regs(id)\
-+[id] = {\
-+ AUD_COMMON_REG_LIST(id)\
-+}
-+
-+static const struct dce_audio_registers audio_regs[] = {
-+ audio_regs(0),
-+ audio_regs(1),
-+ audio_regs(2),
-+ audio_regs(3),
-+ audio_regs(4),
-+ audio_regs(5),
-+ audio_regs(6),
-+};
-+
-+static const struct dce_audio_shift audio_shift = {
-+ AUD_COMMON_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_aduio_mask audio_mask = {
-+ AUD_COMMON_MASK_SH_LIST(_MASK)
-+};
-+
-+/* 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),
-+}
-+};
-+
-+#define clk_src_regs(id)\
-+[id] = {\
-+ CS_COMMON_REG_LIST_DCE_100_110(id),\
-+}
-+
-+static const struct dce110_clk_src_regs clk_src_regs[] = {
-+ clk_src_regs(0),
-+ clk_src_regs(1),
-+ clk_src_regs(2)
-+};
-+
-+static const struct dce110_clk_src_shift cs_shift = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
-+};
-+
-+static const struct dce110_clk_src_mask cs_mask = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
-+};
-+
-+static const struct bios_registers bios_regs = {
-+ .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
-+};
-+
-+static const struct resource_caps carrizo_resource_cap = {
-+ .num_timing_generator = 3,
-+ .num_video_plane = 1,
-+ .num_audio = 3,
-+ .num_stream_encoder = 3,
-+ .num_pll = 2,
-+};
-+
-+static const struct resource_caps stoney_resource_cap = {
-+ .num_timing_generator = 2,
-+ .num_video_plane = 1,
-+ .num_audio = 3,
-+ .num_stream_encoder = 3,
-+ .num_pll = 2,
-+};
-+
-+#define CTX ctx
-+#define REG(reg) mm ## reg
-+
-+#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 void read_dce_straps(
-+ struct dc_context *ctx,
-+ struct resource_straps *straps)
-+{
-+ REG_GET_2(CC_DC_HDMI_STRAPS,
-+ HDMI_DISABLE, &straps->hdmi_disable,
-+ AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
-+
-+ REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
-+}
-+
-+static struct audio *create_audio(
-+ struct dc_context *ctx, unsigned int inst)
-+{
-+ return dce_audio_create(ctx, inst,
-+ &audio_regs[inst], &audio_shift, &audio_mask);
-+}
-+
-+static struct timing_generator *dce110_timing_generator_create(
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ struct dce110_timing_generator *tg110 =
-+ dm_alloc(sizeof(struct dce110_timing_generator));
-+
-+ if (!tg110)
-+ return NULL;
-+
-+ if (dce110_timing_generator_construct(tg110, ctx, instance, offsets))
-+ return &tg110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(tg110);
-+ return NULL;
-+}
-+
-+static struct stream_encoder *dce110_stream_encoder_create(
-+ enum engine_id eng_id,
-+ struct dc_context *ctx)
-+{
-+ struct dce110_stream_encoder *enc110 =
-+ dm_alloc(sizeof(struct dce110_stream_encoder));
-+
-+ if (!enc110)
-+ return NULL;
-+
-+ if (dce110_stream_encoder_construct(
-+ enc110, ctx, ctx->dc_bios, eng_id,
-+ &stream_enc_regs[eng_id], &se_shift, &se_mask))
-+ return &enc110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+#define SRII(reg_name, block, id)\
-+ .reg_name[id] = mm ## block ## id ## _ ## reg_name
-+
-+static const struct dce_hwseq_registers hwseq_stoney_reg = {
-+ HWSEQ_ST_REG_LIST()
-+};
-+
-+static const struct dce_hwseq_registers hwseq_cz_reg = {
-+ HWSEQ_CZ_REG_LIST()
-+};
-+
-+static const struct dce_hwseq_shift hwseq_shift = {
-+ HWSEQ_DCE11_MASK_SH_LIST(__SHIFT),
-+};
-+
-+static const struct dce_hwseq_mask hwseq_mask = {
-+ HWSEQ_DCE11_MASK_SH_LIST(_MASK),
-+};
-+
-+static struct dce_hwseq *dce110_hwseq_create(
-+ struct dc_context *ctx)
-+{
-+ struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
-+
-+ if (hws) {
-+ hws->ctx = ctx;
-+ hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ?
-+ &hwseq_stoney_reg : &hwseq_cz_reg;
-+ hws->shifts = &hwseq_shift;
-+ hws->masks = &hwseq_mask;
-+ hws->wa.blnd_crtc_trigger = true;
-+ }
-+ return hws;
-+}
-+
-+static const struct resource_create_funcs res_create_funcs = {
-+ .read_dce_straps = read_dce_straps,
-+ .create_audio = create_audio,
-+ .create_stream_encoder = dce110_stream_encoder_create,
-+ .create_hwseq = dce110_hwseq_create,
-+};
-+
-+#define mi_inst_regs(id) { \
-+ MI_REG_LIST(id), \
-+ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
-+}
-+static const struct dce_mem_input_registers mi_regs[] = {
-+ mi_inst_regs(0),
-+ mi_inst_regs(1),
-+ mi_inst_regs(2),
-+};
-+
-+static const struct dce_mem_input_shift mi_shifts = {
-+ MI_DCE_MASK_SH_LIST(__SHIFT),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
-+};
-+
-+static const struct dce_mem_input_mask mi_masks = {
-+ MI_DCE_MASK_SH_LIST(_MASK),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
-+};
-+
-+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(sizeof(struct dce110_mem_input));
-+
-+ if (!mem_input110)
-+ return NULL;
-+
-+ if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) {
-+ struct mem_input *mi = &mem_input110->base;
-+
-+ mi->regs = &mi_regs[inst];
-+ mi->shifts = &mi_shifts;
-+ mi->masks = &mi_masks;
-+ mi->wa.single_head_rdreq_dmif_limit = 3;
-+ return mi;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(mem_input110);
-+ return NULL;
-+}
-+
-+static void dce110_transform_destroy(struct transform **xfm)
-+{
-+ dm_free(TO_DCE_TRANSFORM(*xfm));
-+ *xfm = NULL;
-+}
-+
-+static struct transform *dce110_transform_create(
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ struct dce_transform *transform =
-+ dm_alloc(sizeof(struct dce_transform));
-+
-+ if (!transform)
-+ return NULL;
-+
-+ if (dce_transform_construct(transform, ctx, inst,
-+ &xfm_regs[inst], &xfm_shift, &xfm_mask))
-+ return &transform->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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(sizeof(struct dce110_ipp));
-+
-+ if (!ipp)
-+ return NULL;
-+
-+ if (dce110_ipp_construct(ipp, ctx, inst, offsets))
-+ return &ipp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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(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_hpd_regs[enc_init_data->hpd_source])) {
-+
-+ enc110->base.features.ycbcr420_supported = false;
-+ enc110->base.features.max_hdmi_pixel_clock = 594000;
-+ return &enc110->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return 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(sizeof(struct dce110_opp));
-+
-+ if (!opp)
-+ return NULL;
-+
-+ if (dce110_opp_construct(opp,
-+ ctx, inst, offsets))
-+ return &opp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(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_regs *regs,
-+ bool dp_clk_src)
-+{
-+ struct dce110_clk_src *clk_src =
-+ dm_alloc(sizeof(struct dce110_clk_src));
-+
-+ if (!clk_src)
-+ return NULL;
-+
-+ if (dce110_clk_src_construct(clk_src, ctx, bios, id,
-+ regs, &cs_shift, &cs_mask)) {
-+ clk_src->base.dp_clk_src = dp_clk_src;
-+ return &clk_src->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-+void dce110_clock_source_destroy(struct clock_source **clk_src)
-+{
-+ struct dce110_clk_src *dce110_clk_src;
-+
-+ if (!clk_src)
-+ return;
-+
-+ dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src);
-+
-+ if (dce110_clk_src->dp_ss_params)
-+ dm_free(dce110_clk_src->dp_ss_params);
-+
-+ if (dce110_clk_src->hdmi_ss_params)
-+ dm_free(dce110_clk_src->hdmi_ss_params);
-+
-+ if (dce110_clk_src->dvi_ss_params)
-+ dm_free(dce110_clk_src->dvi_ss_params);
-+
-+ dm_free(dce110_clk_src);
-+ *clk_src = NULL;
-+}
-+
-+static void destruct(struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ if (pool->base.opps[i] != NULL)
-+ dce110_opp_destroy(&pool->base.opps[i]);
-+
-+ if (pool->base.transforms[i] != NULL)
-+ dce110_transform_destroy(&pool->base.transforms[i]);
-+
-+ if (pool->base.ipps[i] != NULL)
-+ dce110_ipp_destroy(&pool->base.ipps[i]);
-+
-+ if (pool->base.mis[i] != NULL) {
-+ dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
-+ pool->base.mis[i] = NULL;
-+ }
-+
-+ if (pool->base.timing_generators[i] != NULL) {
-+ dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
-+ pool->base.timing_generators[i] = NULL;
-+ }
-+ }
-+
-+ for (i = 0; i < pool->base.stream_enc_count; i++) {
-+ if (pool->base.stream_enc[i] != NULL)
-+ dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] != NULL) {
-+ dce110_clock_source_destroy(&pool->base.clock_sources[i]);
-+ }
-+ }
-+
-+ if (pool->base.dp_clock_source != NULL)
-+ dce110_clock_source_destroy(&pool->base.dp_clock_source);
-+
-+ for (i = 0; i < pool->base.audio_count; i++) {
-+ if (pool->base.audios[i] != NULL) {
-+ dce_aud_destroy(&pool->base.audios[i]);
-+ }
-+ }
-+
-+ if (pool->base.display_clock != NULL) {
-+ dal_display_clock_destroy(&pool->base.display_clock);
-+ }
-+
-+ if (pool->base.irqs != NULL) {
-+ dal_irq_service_destroy(&pool->base.irqs);
-+ }
-+}
-+
-+
-+static void get_pixel_clock_parameters(
-+ const struct pipe_ctx *pipe_ctx,
-+ struct pixel_clk_params *pixel_clk_params)
-+{
-+ const struct core_stream *stream = pipe_ctx->stream;
-+
-+ /*TODO: is this halved for YCbCr 420? in that case we might want to move
-+ * the pixel clock normalization for hdmi up to here instead of doing it
-+ * in pll_adjust_pix_clk
-+ */
-+ 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 = pipe_ctx->stream->signal;
-+ pixel_clk_params->controller_id = pipe_ctx->pipe_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;
-+ pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding ==
-+ PIXEL_ENCODING_YCBCR420);
-+}
-+
-+void dce110_resource_build_bit_depth_reduction_params(
-+ const struct core_stream *stream,
-+ struct bit_depth_reduction_params *fmt_bit_depth)
-+{
-+ 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) {
-+ switch (stream->public.timing.display_color_depth) {
-+ case COLOR_DEPTH_666:
-+ fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
-+ fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
-+ break;
-+ case COLOR_DEPTH_888:
-+ fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
-+ fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
-+ break;
-+ case COLOR_DEPTH_101010:
-+ fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
-+ fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
-+ break;
-+ default:
-+ break;
-+ }
-+ fmt_bit_depth->flags.RGB_RANDOM = 1;
-+ fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
-+ fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
-+ fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
-+ }
-+
-+ return;
-+}
-+
-+enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
-+{
-+ get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params);
-+ pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
-+ pipe_ctx->clock_source,
-+ &pipe_ctx->pix_clk_params,
-+ &pipe_ctx->pll_settings);
-+ dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream,
-+ &pipe_ctx->stream->bit_depth_params);
-+ pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding;
-+
-+ return DC_OK;
-+}
-+
-+static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx)
-+{
-+ if (pipe_ctx->pipe_idx != underlay_idx)
-+ return true;
-+ if (!pipe_ctx->surface)
-+ return false;
-+ if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+ return true;
-+}
-+
-+static enum dc_status validate_mapped_resource(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status status = DC_OK;
-+ uint8_t i, j, k;
-+
-+ 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 core_link *link = stream->sink->link;
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (!is_surface_pixel_format_supported(pipe_ctx,
-+ context->res_ctx.pool->underlay_pipe_index))
-+ return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED;
-+
-+ if (!pipe_ctx->tg->funcs->validate_timing(
-+ pipe_ctx->tg, &stream->public.timing))
-+ return DC_FAIL_CONTROLLER_VALIDATE;
-+
-+ status = dce110_resource_build_pipe_hw_param(pipe_ctx);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ if (!link->link_enc->funcs->validate_output_with_stream(
-+ link->link_enc,
-+ pipe_ctx))
-+ return DC_FAIL_ENC_VALIDATE;
-+
-+ /* TODO: validate audio ASIC caps, encoder */
-+
-+ status = dc_link_validate_mode_timing(stream,
-+ link,
-+ &stream->public.timing);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ resource_build_info_frame(pipe_ctx);
-+
-+ /* do not need to validate non root pipes */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+enum dc_status dce110_validate_bandwidth(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ dm_logger_write(
-+ dc->ctx->logger, LOG_BANDWIDTH_CALCS,
-+ "%s: start",
-+ __func__);
-+
-+ if (!bw_calcs(
-+ dc->ctx,
-+ &dc->bw_dceip,
-+ &dc->bw_vbios,
-+ context->res_ctx.pipe_ctx,
-+ context->res_ctx.pool->pipe_count,
-+ &context->bw_results))
-+ result = DC_FAIL_BANDWIDTH_VALIDATE;
-+ else
-+ result = DC_OK;
-+
-+ if (result == DC_FAIL_BANDWIDTH_VALIDATE)
-+ dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
-+ "%s: %dx%d@%d Bandwidth validation failed!\n",
-+ __func__,
-+ context->targets[0]->public.streams[0]->timing.h_addressable,
-+ context->targets[0]->public.streams[0]->timing.v_addressable,
-+ context->targets[0]->public.streams[0]->timing.pix_clk_khz);
-+
-+ if (memcmp(&dc->current_context->bw_results,
-+ &context->bw_results, sizeof(context->bw_results))) {
-+ struct log_entry log_entry;
-+ dm_logger_open(
-+ dc->ctx->logger,
-+ &log_entry,
-+ LOG_BANDWIDTH_CALCS);
-+ dm_logger_append(&log_entry, "%s: finish,\n"
-+ "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
-+ "stutMark_b: %d stutMark_a: %d\n",
-+ __func__,
-+ 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);
-+ dm_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);
-+ dm_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);
-+ dm_logger_append(&log_entry,
-+ "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
-+ "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %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.blackout_recovery_time_us);
-+ dm_logger_close(&log_entry);
-+ }
-+ return result;
-+}
-+
-+static bool dce110_validate_surface_sets(
-+ const struct dc_validation_set set[],
-+ int set_count)
-+{
-+ int i;
-+
-+ for (i = 0; i < set_count; i++) {
-+ if (set[i].surface_count == 0)
-+ continue;
-+
-+ if (set[i].surface_count > 2)
-+ return false;
-+
-+ if (set[i].surfaces[0]->src_rect.width
-+ != set[i].target->streams[0]->src.width
-+ || set[i].surfaces[0]->src_rect.height
-+ != set[i].target->streams[0]->src.height)
-+ return false;
-+ if (set[i].surfaces[0]->format
-+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+
-+ if (set[i].surface_count == 2) {
-+ if (set[i].surfaces[1]->format
-+ < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+ if (set[i].surfaces[1]->src_rect.width > 1920
-+ || set[i].surfaces[1]->src_rect.height > 1080)
-+ return false;
-+
-+ if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB)
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+enum dc_status dce110_validate_with_context(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context)
-+{
-+ struct dc_context *dc_ctx = dc->ctx;
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ int i;
-+
-+ if (!dce110_validate_surface_sets(set, set_count))
-+ return DC_FAIL_SURFACE_VALIDATE;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ for (i = 0; i < set_count; i++) {
-+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
-+ dc_target_retain(&context->targets[i]->public);
-+ context->target_count++;
-+ }
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (!resource_validate_attach_surfaces(
-+ set, set_count, dc->current_context, context)) {
-+ DC_ERROR("Failed to attach surface to target!\n");
-+ return DC_FAIL_ATTACH_SURFACES;
-+ }
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_build_scaling_params_for_context(dc, context);
-+
-+ if (result == DC_OK)
-+ result = dce110_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+enum dc_status dce110_validate_guaranteed(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ context->targets[0] = DC_TARGET_TO_CORE(dc_target);
-+ dc_target_retain(&context->targets[0]->public);
-+ context->target_count++;
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK) {
-+ validate_guaranteed_copy_target(
-+ context, dc->public.caps.max_targets);
-+ result = resource_build_scaling_params_for_context(dc, context);
-+ }
-+
-+ if (result == DC_OK)
-+ result = dce110_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer(
-+ struct resource_context *res_ctx,
-+ struct core_stream *stream)
-+{
-+ unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index;
-+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx];
-+
-+ if (res_ctx->pipe_ctx[underlay_idx].stream) {
-+ return NULL;
-+ }
-+
-+ pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx];
-+ pipe_ctx->mi = res_ctx->pool->mis[underlay_idx];
-+ /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/
-+ pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx];
-+ pipe_ctx->opp = res_ctx->pool->opps[underlay_idx];
-+ pipe_ctx->dis_clk = res_ctx->pool->display_clock;
-+ pipe_ctx->pipe_idx = underlay_idx;
-+
-+ pipe_ctx->stream = stream;
-+
-+ return pipe_ctx;
-+
-+}
-+
-+static void dce110_destroy_resource_pool(struct resource_pool **pool)
-+{
-+ struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
-+
-+ destruct(dce110_pool);
-+ dm_free(dce110_pool);
-+ *pool = NULL;
-+}
-+
-+
-+static const struct resource_funcs dce110_res_pool_funcs = {
-+ .destroy = dce110_destroy_resource_pool,
-+ .link_enc_create = dce110_link_encoder_create,
-+ .validate_with_context = dce110_validate_with_context,
-+ .validate_guaranteed = dce110_validate_guaranteed,
-+ .validate_bandwidth = dce110_validate_bandwidth,
-+ .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer,
-+ .build_bit_depth_reduction_params =
-+ dce110_resource_build_bit_depth_reduction_params
-+};
-+
-+static void underlay_create(struct dc_context *ctx, struct resource_pool *pool)
-+{
-+ struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv));
-+ struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv));
-+ struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv));
-+ struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv));
-+
-+ dce110_opp_v_construct(dce110_oppv, ctx);
-+ dce110_timing_generator_v_construct(dce110_tgv, ctx);
-+ dce110_mem_input_v_construct(dce110_miv, ctx);
-+ dce110_transform_v_construct(dce110_xfmv, ctx);
-+
-+ pool->opps[pool->pipe_count] = &dce110_oppv->base;
-+ pool->timing_generators[pool->pipe_count] = &dce110_tgv->base;
-+ pool->mis[pool->pipe_count] = &dce110_miv->base;
-+ pool->transforms[pool->pipe_count] = &dce110_xfmv->base;
-+ pool->pipe_count++;
-+
-+ /* update the public caps to indicate an underlay is available */
-+ ctx->dc->caps.max_slave_planes = 1;
-+ ctx->dc->caps.max_slave_planes = 1;
-+}
-+
-+static void bw_calcs_data_update_from_pplib(struct core_dc *dc)
-+{
-+ struct dm_pp_clock_levels clks = {0};
-+
-+ /*do system clock*/
-+ dm_pp_get_clock_levels_by_type(
-+ dc->ctx,
-+ DM_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.mid1_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels/8], 1000);
-+ dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*2/8], 1000);
-+ dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*3/8], 1000);
-+ dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*4/8], 1000);
-+ dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*5/8], 1000);
-+ dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*6/8], 1000);
-+ dc->bw_vbios.low_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[0], 1000);
-+ dc->sclk_lvls = clks;
-+
-+ /*do display clock*/
-+ dm_pp_get_clock_levels_by_type(
-+ dc->ctx,
-+ DM_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,
-+ DM_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);
-+}
-+
-+enum clocks_state dce110_resource_convert_clock_state_pp_to_dc(
-+ enum dm_pp_clocks_state pp_clock_state)
-+{
-+ enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID;
-+
-+ switch (pp_clock_state) {
-+ case DM_PP_CLOCKS_STATE_INVALID:
-+ dc_clocks_state = CLOCKS_STATE_INVALID;
-+ break;
-+ case DM_PP_CLOCKS_STATE_ULTRA_LOW:
-+ dc_clocks_state = CLOCKS_STATE_ULTRA_LOW;
-+ break;
-+ case DM_PP_CLOCKS_STATE_LOW:
-+ dc_clocks_state = CLOCKS_STATE_LOW;
-+ break;
-+ case DM_PP_CLOCKS_STATE_NOMINAL:
-+ dc_clocks_state = CLOCKS_STATE_NOMINAL;
-+ break;
-+ case DM_PP_CLOCKS_STATE_PERFORMANCE:
-+ dc_clocks_state = CLOCKS_STATE_PERFORMANCE;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_4:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_5:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_6:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_7:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7;
-+ break;
-+ default:
-+ dc_clocks_state = CLOCKS_STATE_INVALID;
-+ break;
-+ }
-+
-+ return dc_clocks_state;
-+}
-+
-+const struct resource_caps *dce110_resource_cap(
-+ struct hw_asic_id *asic_id)
-+{
-+ if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev))
-+ return &stoney_resource_cap;
-+ else
-+ return &carrizo_resource_cap;
-+}
-+
-+static bool construct(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct dce110_resource_pool *pool,
-+ struct hw_asic_id asic_id)
-+{
-+ unsigned int i;
-+ struct dc_context *ctx = dc->ctx;
-+ struct firmware_info info;
-+ struct dc_bios *bp;
-+ struct dm_pp_static_clock_info static_clk_info = {0};
-+
-+ ctx->dc_bios->regs = &bios_regs;
-+
-+ pool->base.res_cap = dce110_resource_cap(&ctx->asic_id);
-+ pool->base.funcs = &dce110_res_pool_funcs;
-+
-+ /*************************************************
-+ * Resource + asic cap harcoding *
-+ *************************************************/
-+
-+ pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
-+ pool->base.underlay_pipe_index = pool->base.pipe_count;
-+
-+ dc->public.caps.max_downscale_ratio = 150;
-+ dc->public.caps.i2c_speed_in_khz = 100;
-+
-+ /*************************************************
-+ * Create resources *
-+ *************************************************/
-+
-+ bp = ctx->dc_bios;
-+
-+ if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
-+ info.external_clock_source_frequency_for_dp != 0) {
-+ pool->base.dp_clock_source =
-+ dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
-+
-+ pool->base.clock_sources[0] =
-+ dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0,
-+ &clk_src_regs[0], false);
-+ pool->base.clock_sources[1] =
-+ dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1,
-+ &clk_src_regs[1], false);
-+
-+ pool->base.clk_src_count = 2;
-+
-+ /* TODO: find out if CZ support 3 PLLs */
-+ }
-+
-+ if (pool->base.dp_clock_source == NULL) {
-+ dm_error("DC: failed to create dp clock source!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] == NULL) {
-+ dm_error("DC: failed to create clock sources!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ pool->base.display_clock = dal_display_clock_dce110_create(ctx);
-+ if (pool->base.display_clock == NULL) {
-+ dm_error("DC: failed to create display clock!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+ /* get static clock information for PPLIB or firmware, save
-+ * max_clock_state
-+ */
-+ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) {
-+ enum clocks_state max_clocks_state =
-+ dce110_resource_convert_clock_state_pp_to_dc(
-+ static_clk_info.max_clocks_state);
-+
-+ dal_display_clock_store_max_clocks_state(
-+ pool->base.display_clock, max_clocks_state);
-+ }
-+
-+ {
-+ struct irq_service_init_data init_data;
-+ init_data.ctx = dc->ctx;
-+ pool->base.irqs = dal_irq_service_dce110_create(&init_data);
-+ if (!pool->base.irqs)
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ pool->base.timing_generators[i] = dce110_timing_generator_create(
-+ ctx, i, &dce110_tg_offsets[i]);
-+ if (pool->base.timing_generators[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create tg!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.mis[i] = dce110_mem_input_create(ctx, i,
-+ &dce110_mi_reg_offsets[i]);
-+ if (pool->base.mis[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create memory input!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]);
-+ if (pool->base.ipps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create input pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.transforms[i] = dce110_transform_create(ctx, i);
-+ if (pool->base.transforms[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create transform!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
-+ if (pool->base.opps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create output pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ underlay_create(ctx, &pool->base);
-+
-+ if (!resource_construct(num_virtual_links, dc, &pool->base,
-+ &res_create_funcs))
-+ goto res_create_fail;
-+
-+ /* Create hardware sequencer */
-+ if (!dce110_hw_sequencer_construct(dc))
-+ goto res_create_fail;
-+
-+ if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev))
-+ bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY);
-+ else
-+ bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO);
-+
-+ bw_calcs_data_update_from_pplib(dc);
-+
-+ return true;
-+
-+res_create_fail:
-+ destruct(pool);
-+ return false;
-+}
-+
-+struct resource_pool *dce110_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct hw_asic_id asic_id)
-+{
-+ struct dce110_resource_pool *pool =
-+ dm_alloc(sizeof(struct dce110_resource_pool));
-+
-+ if (!pool)
-+ return NULL;
-+
-+ if (construct(num_virtual_links, dc, pool, asic_id))
-+ return &pool->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h
-new file mode 100644
-index 0000000..535623a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.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 __DC_RESOURCE_DCE110_H__
-+#define __DC_RESOURCE_DCE110_H__
-+
-+#include "core_types.h"
-+
-+struct core_dc;
-+struct resource_pool;
-+
-+#define TO_DCE110_RES_POOL(pool)\
-+ container_of(pool, struct dce110_resource_pool, base)
-+
-+struct dce110_resource_pool {
-+ struct resource_pool base;
-+};
-+
-+enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx);
-+
-+enum clocks_state dce110_resource_convert_clock_state_pp_to_dc(
-+ enum dm_pp_clocks_state pp_clock_state);
-+
-+void dce110_resource_build_bit_depth_reduction_params(
-+ const struct core_stream *stream,
-+ struct bit_depth_reduction_params *fmt_bit_depth);
-+
-+struct resource_pool *dce110_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct hw_asic_id asic_id);
-+
-+#endif /* __DC_RESOURCE_DCE110_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
-new file mode 100644
-index 0000000..b1c9712
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
-@@ -0,0 +1,1953 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dc.h"
-+
-+#include "include/grph_object_id.h"
-+#include "include/logger_interface.h"
-+#include "dce110_timing_generator.h"
-+
-+#include "timing_generator.h"
-+
-+
-+#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)
-+
-+/* Flowing register offsets are same in files of
-+ * dce/dce_11_0_d.h
-+ * dce/vi_polaris10_p/vi_polaris10_d.h
-+ *
-+ * So we can create dce110 timing generator to use it.
-+ */
-+
-+
-+/*
-+* 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;
-+ }
-+}
-+
-+/**
-+ *****************************************************************************
-+ * 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;
-+
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t value = 0;
-+
-+ /*
-+ * 3 is used to make sure V_UPDATE occurs at the beginning of the first
-+ * line of vertical front porch
-+ */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_MASTER_UPDATE_MODE,
-+ MASTER_UPDATE_MODE);
-+
-+ dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
-+
-+ /* TODO: may want this on to catch underflow */
-+ value = 0;
-+ dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), 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,
-+ const struct tg_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->color_b_cb,
-+ CRTC_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_g_y,
-+ CRTC_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_r_cr,
-+ CRTC_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_R_CR);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+/**
-+ *****************************************************************************
-+ * 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;
-+
-+ 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: set_drr
-+ *
-+ * @brief
-+ * Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
-+ *
-+ * @param [in] pHwCrtcTiming: point to H
-+ * wCrtcTiming struct
-+ *****************************************************************************
-+ */
-+void dce110_timing_generator_set_drr(
-+ struct timing_generator *tg,
-+ const struct drr_params *params)
-+{
-+ /* 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 (params != NULL &&
-+ params->vertical_total_max > 0 &&
-+ params->vertical_total_min > 0) {
-+
-+ set_reg_field_value(v_total_max,
-+ params->vertical_total_max - 1,
-+ CRTC_V_TOTAL_MAX,
-+ CRTC_V_TOTAL_MAX);
-+
-+ set_reg_field_value(v_total_min,
-+ params->vertical_total_min - 1,
-+ CRTC_V_TOTAL_MIN,
-+ CRTC_V_TOTAL_MIN);
-+
-+ set_reg_field_value(v_total_cntl,
-+ 1,
-+ CRTC_V_TOTAL_CONTROL,
-+ CRTC_V_TOTAL_MIN_SEL);
-+
-+ set_reg_field_value(v_total_cntl,
-+ 1,
-+ 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);
-+
-+ set_reg_field_value(v_total_cntl,
-+ 0,
-+ CRTC_V_TOTAL_CONTROL,
-+ CRTC_SET_V_TOTAL_MIN_MASK_EN);
-+
-+ 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,
-+ 0x180,
-+ CRTC_STATIC_SCREEN_CONTROL,
-+ CRTC_STATIC_SCREEN_EVENT_MASK);
-+ } 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);
-+}
-+
-+void dce110_timing_generator_set_static_screen_control(
-+ struct timing_generator *tg,
-+ uint32_t value)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t static_screen_cntl = 0;
-+ uint32_t addr = 0;
-+
-+ addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
-+ static_screen_cntl = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(static_screen_cntl,
-+ value,
-+ CRTC_STATIC_SCREEN_CONTROL,
-+ CRTC_STATIC_SCREEN_EVENT_MASK);
-+
-+ set_reg_field_value(static_screen_cntl,
-+ 2,
-+ CRTC_STATIC_SCREEN_CONTROL,
-+ CRTC_STATIC_SCREEN_FRAME_COUNT);
-+
-+ 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,
-+ uint32_t *vbl,
-+ uint32_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);
-+ enum test_pattern_color_format bit_depth;
-+ enum test_pattern_dyn_range dyn_range;
-+ enum test_pattern_mode mode;
-+ /* color ramp generator mixes 16-bits color */
-+ uint32_t src_bpc = 16;
-+ /* requested bpc */
-+ uint32_t dst_bpc;
-+ uint32_t index;
-+ /* RGB values of the color bars.
-+ * Produce two RGB colors: RGB0 - white (all Fs)
-+ * and RGB1 - black (all 0s)
-+ * (three RGB components for two colors)
-+ */
-+ uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
-+ 0x0000, 0x0000};
-+ /* dest color (converted to the specified color format) */
-+ uint16_t dst_color[6];
-+ uint32_t inc_base;
-+
-+ /* translate to bit depth */
-+ switch (color_depth) {
-+ case COLOR_DEPTH_666:
-+ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
-+ break;
-+ case COLOR_DEPTH_888:
-+ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
-+ break;
-+ case COLOR_DEPTH_101010:
-+ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
-+ break;
-+ case COLOR_DEPTH_121212:
-+ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
-+ break;
-+ default:
-+ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
-+ break;
-+ }
-+
-+ switch (test_pattern) {
-+ case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
-+ case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
-+ {
-+ dyn_range = (test_pattern ==
-+ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
-+ TEST_PATTERN_DYN_RANGE_CEA :
-+ TEST_PATTERN_DYN_RANGE_VESA);
-+ mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
-+ 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,
-+ mode,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_MODE);
-+
-+ set_reg_field_value(
-+ value,
-+ dyn_range,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_DYNAMIC_RANGE);
-+ set_reg_field_value(
-+ value,
-+ bit_depth,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_COLOR_FORMAT);
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ break;
-+
-+ case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
-+ case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
-+ {
-+ mode = (test_pattern ==
-+ CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
-+ TEST_PATTERN_MODE_VERTICALBARS :
-+ TEST_PATTERN_MODE_HORIZONTALBARS);
-+
-+ switch (bit_depth) {
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_6:
-+ dst_bpc = 6;
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_8:
-+ dst_bpc = 8;
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_10:
-+ dst_bpc = 10;
-+ break;
-+ default:
-+ dst_bpc = 8;
-+ break;
-+ }
-+
-+ /* adjust color to the required colorFormat */
-+ for (index = 0; index < 6; index++) {
-+ /* dst = 2^dstBpc * src / 2^srcBpc = src >>
-+ * (srcBpc - dstBpc);
-+ */
-+ dst_color[index] =
-+ src_color[index] >> (src_bpc - dst_bpc);
-+ /* CRTC_TEST_PATTERN_DATA has 16 bits,
-+ * lowest 6 are hardwired to ZERO
-+ * color bits should be left aligned aligned to MSB
-+ * XXXXXXXXXX000000 for 10 bit,
-+ * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
-+ */
-+ dst_color[index] <<= (16 - dst_bpc);
-+ }
-+
-+ value = 0;
-+ addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
-+ dm_write_reg(ctx, addr, value);
-+
-+ /* We have to write the mask before data, similar to pipeline.
-+ * For example, for 8 bpc, if we want RGB0 to be magenta,
-+ * and RGB1 to be cyan,
-+ * we need to make 7 writes:
-+ * MASK DATA
-+ * 000001 00000000 00000000 set mask to R0
-+ * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0
-+ * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0
-+ * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1
-+ * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1
-+ * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1
-+ * 100000 11111111 00000000 B1 255, 0xFF00
-+ *
-+ * we will make a loop of 6 in which we prepare the mask,
-+ * then write, then prepare the color for next write.
-+ * first iteration will write mask only,
-+ * but each next iteration color prepared in
-+ * previous iteration will be written within new mask,
-+ * the last component will written separately,
-+ * mask is not changing between 6th and 7th write
-+ * and color will be prepared by last iteration
-+ */
-+
-+ /* write color, color values mask in CRTC_TEST_PATTERN_MASK
-+ * is B1, G1, R1, B0, G0, R0
-+ */
-+ value = 0;
-+ addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
-+ for (index = 0; index < 6; index++) {
-+ /* prepare color mask, first write PATTERN_DATA
-+ * will have all zeros
-+ */
-+ set_reg_field_value(
-+ value,
-+ (1 << index),
-+ CRTC_TEST_PATTERN_COLOR,
-+ CRTC_TEST_PATTERN_MASK);
-+ /* write color component */
-+ dm_write_reg(ctx, addr, value);
-+ /* prepare next color component,
-+ * will be written in the next iteration
-+ */
-+ set_reg_field_value(
-+ value,
-+ dst_color[index],
-+ CRTC_TEST_PATTERN_COLOR,
-+ CRTC_TEST_PATTERN_DATA);
-+ }
-+ /* write last color component,
-+ * it's been already prepared in the loop
-+ */
-+ dm_write_reg(ctx, addr, value);
-+
-+ /* enable test pattern */
-+ 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,
-+ mode,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_MODE);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_DYNAMIC_RANGE);
-+
-+ set_reg_field_value(
-+ value,
-+ bit_depth,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_COLOR_FORMAT);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ break;
-+
-+ case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
-+ {
-+ mode = (bit_depth ==
-+ TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
-+ TEST_PATTERN_MODE_DUALRAMP_RGB :
-+ TEST_PATTERN_MODE_SINGLERAMP_RGB);
-+
-+ switch (bit_depth) {
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_6:
-+ dst_bpc = 6;
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_8:
-+ dst_bpc = 8;
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_10:
-+ dst_bpc = 10;
-+ break;
-+ default:
-+ dst_bpc = 8;
-+ break;
-+ }
-+
-+ /* increment for the first ramp for one color gradation
-+ * 1 gradation for 6-bit color is 2^10
-+ * gradations in 16-bit color
-+ */
-+ inc_base = (src_bpc - dst_bpc);
-+
-+ value = 0;
-+ addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
-+
-+ switch (bit_depth) {
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_6:
-+ {
-+ set_reg_field_value(
-+ value,
-+ inc_base,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC0);
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC1);
-+ set_reg_field_value(
-+ value,
-+ 6,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_HRES);
-+ set_reg_field_value(
-+ value,
-+ 6,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_VRES);
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_RAMP0_OFFSET);
-+ }
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_8:
-+ {
-+ set_reg_field_value(
-+ value,
-+ inc_base,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC0);
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC1);
-+ set_reg_field_value(
-+ value,
-+ 8,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_HRES);
-+ set_reg_field_value(
-+ value,
-+ 6,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_VRES);
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_RAMP0_OFFSET);
-+ }
-+ break;
-+ case TEST_PATTERN_COLOR_FORMAT_BPC_10:
-+ {
-+ set_reg_field_value(
-+ value,
-+ inc_base,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC0);
-+ set_reg_field_value(
-+ value,
-+ inc_base + 2,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_INC1);
-+ set_reg_field_value(
-+ value,
-+ 8,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_HRES);
-+ set_reg_field_value(
-+ value,
-+ 5,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_VRES);
-+ set_reg_field_value(
-+ value,
-+ 384 << 6,
-+ CRTC_TEST_PATTERN_PARAMETERS,
-+ CRTC_TEST_PATTERN_RAMP0_OFFSET);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ dm_write_reg(ctx, addr, value);
-+
-+ value = 0;
-+ addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
-+ dm_write_reg(ctx, addr, value);
-+
-+ /* enable test pattern */
-+ 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,
-+ mode,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_MODE);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_DYNAMIC_RANGE);
-+ /* add color depth translation here */
-+ set_reg_field_value(
-+ value,
-+ bit_depth,
-+ CRTC_TEST_PATTERN_CONTROL,
-+ CRTC_TEST_PATTERN_COLOR_FORMAT);
-+
-+ dm_write_reg(ctx, addr, value);
-+ }
-+ break;
-+ case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
-+ {
-+ value = 0;
-+ dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value);
-+ dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value);
-+ dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS),
-+ value);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/**
-+* 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;
-+ }
-+ }
-+}
-+
-+/**
-+ *****************************************************************************
-+ * 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->gsl_master == tg->inst,
-+ 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);
-+
-+
-+ {
-+ 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_PURPOSE_SURFACE_FLIP */
-+ 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;
-+
-+ tg->funcs->get_position(tg, &h1, &v1);
-+ tg->funcs->get_position(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) {
-+ 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,
-+ int source_tg_inst)
-+{
-+ uint32_t value;
-+ 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 */
-+ {
-+ 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;
-+ }
-+ }
-+
-+ value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
-+
-+ trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
-+
-+ 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,
-+ const struct tg_color *color)
-+{
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t addr;
-+ uint32_t value = 0;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_b_cb,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_r_cr,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_g_y,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ 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 tg_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->color_b_cb,
-+ CRTC_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_g_y,
-+ CRTC_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color->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 tg_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->color_b_cb,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->color_g_y,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->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_is_blanked(struct timing_generator *tg)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
-+
-+ 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)
-+ return true;
-+ return false;
-+}
-+
-+bool dce110_tg_set_blank(struct timing_generator *tg,
-+ bool enable_blanking)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t value = 0;
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTC_DOUBLE_BUFFER_CONTROL,
-+ CRTC_BLANK_DATA_DOUBLE_BUFFER_EN);
-+
-+ dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value);
-+ value = 0;
-+
-+ if (enable_blanking) {
-+ int counter;
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTC_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN);
-+
-+ dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
-+
-+ for (counter = 0; counter < 100; counter++) {
-+ value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
-+
-+ 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;
-+
-+ msleep(1);
-+ }
-+
-+ if (counter == 100) {
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "timing generator %d blank timing out.\n",
-+ tg110->controller_id);
-+ return false;
-+ }
-+ } else
-+ dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
-+
-+ return true;
-+}
-+
-+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 tg_color *blank_color,
-+ const struct tg_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);
-+}
-+
-+static const 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,
-+ .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
-+ .set_early_control = dce110_timing_generator_set_early_control,
-+ .wait_for_state = dce110_tg_wait_for_state,
-+ .set_blank = dce110_tg_set_blank,
-+ .is_blanked = dce110_tg_is_blanked,
-+ .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,
-+ .set_drr =
-+ dce110_timing_generator_set_drr,
-+ .set_static_screen_control =
-+ dce110_timing_generator_set_static_screen_control,
-+ .set_test_pattern = dce110_timing_generator_set_test_pattern
-+
-+};
-+
-+bool dce110_timing_generator_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ if (!tg110)
-+ return false;
-+
-+ tg110->controller_id = CONTROLLER_ID_D0 + instance;
-+ tg110->base.inst = instance;
-+
-+ tg110->offsets = *offsets;
-+
-+ tg110->base.funcs = &dce110_tg_funcs;
-+
-+ tg110->base.ctx = ctx;
-+ tg110->base.bp = ctx->dc_bios;
-+
-+ 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;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
-new file mode 100644
-index 0000000..3990650
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
-@@ -0,0 +1,273 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "timing_generator.h"
-+#include "../include/grph_object_id.h"
-+#include "../include/hw_sequencer_types.h"
-+
-+/* 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-defendant, 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
-+};
-+
-+
-+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;
-+
-+ uint32_t min_h_sync_width;
-+ uint32_t min_v_sync_width;
-+ uint32_t min_v_blank;
-+
-+};
-+
-+#define DCE110TG_FROM_TG(tg)\
-+ container_of(tg, struct dce110_timing_generator, base)
-+
-+bool dce110_timing_generator_construct(
-+ struct dce110_timing_generator *tg,
-+ 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,
-+ int source);
-+
-+/* 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 *****************/
-+/* 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,
-+ const struct tg_color *black_color);
-+/* Combine with above and move YUV/RGB color conversion to SW layer */
-+void dce110_timing_generator_set_overscan_color_black(
-+ struct timing_generator *tg,
-+ const struct tg_color *color);
-+void dce110_timing_generator_color_space_to_black_color(
-+ enum dc_color_space colorspace,
-+ struct tg_color *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_set_drr(
-+ struct timing_generator *tg,
-+ const struct drr_params *params);
-+
-+void dce110_timing_generator_set_static_screen_control(
-+ struct timing_generator *tg,
-+ uint32_t value);
-+
-+uint32_t dce110_timing_generator_get_crtc_scanoutpos(
-+ struct timing_generator *tg,
-+ uint32_t *vbl,
-+ uint32_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 tg_color *black_color);
-+
-+void dce110_tg_set_overscan_color(struct timing_generator *tg,
-+ const struct tg_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_is_blanked(struct timing_generator *tg);
-+
-+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 tg_color *blank_color,
-+ const struct tg_color *overscan_color);
-+
-+#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
-new file mode 100644
-index 0000000..3bf3179
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
-@@ -0,0 +1,743 @@
-+#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 "dc.h"
-+
-+#include "include/grph_object_id.h"
-+#include "include/logger_interface.h"
-+#include "dce110_timing_generator.h"
-+#include "dce110_timing_generator_v.h"
-+
-+#include "timing_generator.h"
-+
-+/** ********************************************************************************
-+ *
-+ * DCE11 Timing Generator Implementation
-+ *
-+ **********************************************************************************/
-+
-+/**
-+* Enable CRTCV
-+*/
-+
-+static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg)
-+{
-+/*
-+* Set MASTER_UPDATE_MODE to 0
-+* This is needed for DRR, and also suggested to be default value by Syed.
-+*/
-+
-+ uint32_t value;
-+
-+ value = 0;
-+ set_reg_field_value(value, 0,
-+ CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_MASTER_UPDATE_MODE, value);
-+
-+ /* TODO: may want this on for looking for underflow */
-+ value = 0;
-+ dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value);
-+
-+ value = 0;
-+ set_reg_field_value(value, 1,
-+ CRTCV_MASTER_EN, CRTC_MASTER_EN);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_MASTER_EN, value);
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
-+{
-+ uint32_t value;
-+
-+ value = dm_read_reg(tg->ctx,
-+ mmCRTCV_CONTROL);
-+ set_reg_field_value(value, 0,
-+ CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL);
-+ set_reg_field_value(value, 0,
-+ CRTCV_CONTROL, CRTC_MASTER_EN);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_CONTROL, value);
-+ /*
-+ * TODO: call this when adding stereo support
-+ * tg->funcs->disable_stereo(tg);
-+ */
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_BLANK_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+ uint8_t counter = 100;
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_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,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN) == 1 &&
-+ get_reg_field_value(
-+ value,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_CURRENT_BLANK_STATE) == 1)
-+ break;
-+
-+ msleep(1);
-+ counter--;
-+ }
-+
-+ if (!counter) {
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "timing generator %d blank timing out.\n",
-+ tg110->controller_id);
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
-+{
-+ uint32_t addr = mmCRTCV_BLANK_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DE_MODE);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_is_in_vertical_blank(
-+ struct timing_generator *tg)
-+{
-+ uint32_t addr = 0;
-+ uint32_t value = 0;
-+ uint32_t field = 0;
-+
-+ addr = mmCRTCV_STATUS;
-+ value = dm_read_reg(tg->ctx, addr);
-+ field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK);
-+ return field == 1;
-+}
-+
-+static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg)
-+{
-+ uint32_t value;
-+ uint32_t h1 = 0;
-+ uint32_t h2 = 0;
-+ uint32_t v1 = 0;
-+ uint32_t v2 = 0;
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ h1 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ v1 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ h2 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ v2 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+
-+ if (h1 == h2 && v1 == v2)
-+ return false;
-+ else
-+ return true;
-+}
-+
-+static void dce110_timing_generator_v_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_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+
-+ while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+}
-+
-+/**
-+* Wait till we are in VActive (anywhere in VActive)
-+*/
-+static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg)
-+{
-+ while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+}
-+
-+static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg,
-+ enum crtc_state state)
-+{
-+ switch (state) {
-+ case CRTC_STATE_VBLANK:
-+ dce110_timing_generator_v_wait_for_vblank(tg);
-+ break;
-+
-+ case CRTC_STATE_VACTIVE:
-+ dce110_timing_generator_v_wait_for_vactive(tg);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+}
-+
-+static void dce110_timing_generator_v_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 dc_context *ctx = tg->ctx;
-+ uint32_t value = 0;
-+ uint32_t addr = 0;
-+ uint32_t tmp = 0;
-+
-+ addr = mmCRTCV_H_TOTAL;
-+ value = dm_read_reg(ctx, addr);
-+ set_reg_field_value(
-+ value,
-+ timing->h_total - 1,
-+ CRTCV_H_TOTAL,
-+ CRTC_H_TOTAL);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_V_TOTAL;
-+ value = dm_read_reg(ctx, addr);
-+ set_reg_field_value(
-+ value,
-+ timing->v_total - 1,
-+ CRTCV_V_TOTAL,
-+ CRTC_V_TOTAL);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_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,
-+ CRTCV_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,
-+ CRTCV_H_BLANK_START_END,
-+ CRTC_H_BLANK_START);
-+
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_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,
-+ CRTCV_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,
-+ CRTCV_V_BLANK_START_END,
-+ CRTC_V_BLANK_START);
-+
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_H_SYNC_A;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ timing->h_sync_width,
-+ CRTCV_H_SYNC_A,
-+ CRTC_H_SYNC_A_END);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_H_SYNC_A_CNTL;
-+ value = dm_read_reg(ctx, addr);
-+ if (timing->flags.HSYNC_POSITIVE_POLARITY) {
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_H_SYNC_A_CNTL,
-+ CRTC_H_SYNC_A_POL);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_H_SYNC_A_CNTL,
-+ CRTC_H_SYNC_A_POL);
-+ }
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_V_SYNC_A;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ timing->v_sync_width,
-+ CRTCV_V_SYNC_A,
-+ CRTC_V_SYNC_A_END);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_V_SYNC_A_CNTL;
-+ value = dm_read_reg(ctx, addr);
-+ if (timing->flags.VSYNC_POSITIVE_POLARITY) {
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_V_SYNC_A_CNTL,
-+ CRTC_V_SYNC_A_POL);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_V_SYNC_A_CNTL,
-+ CRTC_V_SYNC_A_POL);
-+ }
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_INTERLACE_CONTROL;
-+ value = dm_read_reg(ctx, addr);
-+ set_reg_field_value(
-+ value,
-+ timing->flags.INTERLACE,
-+ CRTCV_INTERLACE_CONTROL,
-+ CRTC_INTERLACE_ENABLE);
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_enable_advanced_request(
-+ struct timing_generator *tg,
-+ bool enable,
-+ const struct dc_crtc_timing *timing)
-+{
-+ uint32_t addr = mmCRTCV_START_LINE_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ if (enable) {
-+ if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
-+ set_reg_field_value(
-+ value,
-+ 3,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 4,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ }
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_LEGACY_REQUESTOR_EN);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_LEGACY_REQUESTOR_EN);
-+ }
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg,
-+ bool enable_blanking)
-+{
-+ if (enable_blanking)
-+ return dce110_timing_generator_v_blank_crtc(tg);
-+ else
-+ return dce110_timing_generator_v_unblank_crtc(tg);
-+}
-+
-+static void dce110_timing_generator_v_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_v_program_blanking(tg, timing);
-+}
-+
-+static void dce110_timing_generator_v_program_blank_color(
-+ struct timing_generator *tg,
-+ const struct tg_color *black_color)
-+{
-+ uint32_t addr = mmCRTCV_BLACK_COLOR;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ black_color->color_b_cb,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_g_y,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_r_cr,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_R_CR);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_overscan_color_black(
-+ struct timing_generator *tg,
-+ const struct tg_color *color)
-+{
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t addr;
-+ uint32_t value = 0;
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_b_cb,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_r_cr,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+
-+ set_reg_field_value(
-+ value,
-+ color->color_g_y,
-+ CRTC_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ addr = mmCRTCV_OVERSCAN_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+ addr = mmCRTCV_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 = mmCRTCV_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
-+ */
-+}
-+
-+static void dce110_tg_v_program_blank_color(struct timing_generator *tg,
-+ const struct tg_color *black_color)
-+{
-+ uint32_t addr = mmCRTCV_BLACK_COLOR;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ black_color->color_b_cb,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_g_y,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color->color_r_cr,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_R_CR);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+
-+ addr = mmCRTCV_BLANK_DATA_COLOR;
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg,
-+ const struct tg_color *overscan_color)
-+{
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t value = 0;
-+ uint32_t addr;
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->color_b_cb,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->color_g_y,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->color_r_cr,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+
-+ addr = mmCRTCV_OVERSCAN_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_colors(struct timing_generator *tg,
-+ const struct tg_color *blank_color,
-+ const struct tg_color *overscan_color)
-+{
-+ if (blank_color != NULL)
-+ dce110_tg_v_program_blank_color(tg, blank_color);
-+ if (overscan_color != NULL)
-+ dce110_timing_generator_v_set_overscan_color(tg, overscan_color);
-+}
-+
-+static void dce110_timing_generator_v_set_early_control(
-+ struct timing_generator *tg,
-+ uint32_t early_cntl)
-+{
-+ uint32_t regval;
-+ uint32_t address = mmCRTC_CONTROL;
-+
-+ regval = dm_read_reg(tg->ctx, address);
-+ set_reg_field_value(regval, early_cntl,
-+ CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
-+ dm_write_reg(tg->ctx, address, regval);
-+}
-+
-+static void dce110_timing_generator_v_get_crtc_positions(
-+ struct timing_generator *tg,
-+ int32_t *h_position,
-+ int32_t *v_position)
-+{
-+ uint32_t value;
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ *h_position = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ *v_position = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+}
-+
-+static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg)
-+{
-+ uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+ uint32_t field = get_reg_field_value(
-+ value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
-+
-+ return field;
-+}
-+
-+static bool dce110_timing_generator_v_did_triggered_reset_occur(
-+ struct timing_generator *tg)
-+{
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return false;
-+}
-+
-+static void dce110_timing_generator_v_setup_global_swap_lock(
-+ struct timing_generator *tg,
-+ const struct dcp_gsl_params *gsl_params)
-+{
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_enable_reset_trigger(
-+ struct timing_generator *tg,
-+ int source_tg_inst)
-+{
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_disable_reset_trigger(
-+ struct timing_generator *tg)
-+{
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_tear_down_global_swap_lock(
-+ struct timing_generator *tg)
-+{
-+ dm_logger_write(tg->ctx->logger, LOG_ERROR,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_disable_vga(
-+ struct timing_generator *tg)
-+{
-+ return;
-+}
-+
-+static bool dce110_tg_v_is_blanked(struct timing_generator *tg)
-+{
-+ /* Signal comes from the primary pipe, underlay is never blanked. */
-+ return false;
-+}
-+
-+/** ********************************************************************************************
-+ *
-+ * DCE11 Timing Generator Constructor / Destructor
-+ *
-+ *********************************************************************************************/
-+static const struct timing_generator_funcs dce110_tg_v_funcs = {
-+ .validate_timing = dce110_tg_validate_timing,
-+ .program_timing = dce110_timing_generator_v_program_timing,
-+ .enable_crtc = dce110_timing_generator_v_enable_crtc,
-+ .disable_crtc = dce110_timing_generator_v_disable_crtc,
-+ .is_counter_moving = dce110_timing_generator_v_is_counter_moving,
-+ .get_position = dce110_timing_generator_v_get_crtc_positions,
-+ .get_frame_count = dce110_timing_generator_v_get_vblank_counter,
-+ .set_early_control = dce110_timing_generator_v_set_early_control,
-+ .wait_for_state = dce110_timing_generator_v_wait_for_state,
-+ .set_blank = dce110_timing_generator_v_set_blank,
-+ .is_blanked = dce110_tg_v_is_blanked,
-+ .set_colors = dce110_timing_generator_v_set_colors,
-+ .set_overscan_blank_color =
-+ dce110_timing_generator_v_set_overscan_color_black,
-+ .set_blank_color = dce110_timing_generator_v_program_blank_color,
-+ .disable_vga = dce110_timing_generator_v_disable_vga,
-+ .did_triggered_reset_occur =
-+ dce110_timing_generator_v_did_triggered_reset_occur,
-+ .setup_global_swap_lock =
-+ dce110_timing_generator_v_setup_global_swap_lock,
-+ .enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger,
-+ .disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger,
-+ .tear_down_global_swap_lock =
-+ dce110_timing_generator_v_tear_down_global_swap_lock,
-+ .enable_advanced_request =
-+ dce110_timing_generator_v_enable_advanced_request
-+};
-+
-+bool dce110_timing_generator_v_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct dc_context *ctx)
-+{
-+ if (!tg110)
-+ return false;
-+
-+ tg110->controller_id = CONTROLLER_ID_UNDERLAY0;
-+
-+ tg110->base.funcs = &dce110_tg_v_funcs;
-+
-+ tg110->base.ctx = ctx;
-+ tg110->base.bp = ctx->dc_bios;
-+
-+ 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;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h
-new file mode 100644
-index 0000000..7e49ca8
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.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 __DC_TIMING_GENERATOR_V_DCE110_H__
-+#define __DC_TIMING_GENERATOR_V_DCE110_H__
-+
-+bool dce110_timing_generator_v_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct dc_context *ctx);
-+
-+#endif /* __DC_TIMING_GENERATOR_V_DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
-new file mode 100644
-index 0000000..7d8cf7a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
-@@ -0,0 +1,704 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce110_transform_v.h"
-+#include "dm_services.h"
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+#define SCLV_PHASES 64
-+
-+struct sclv_ratios_inits {
-+ 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;
-+};
-+
-+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;
-+ chroma_viewport->x = luma_viewport->x;
-+ chroma_viewport->y = luma_viewport->y;
-+ chroma_viewport->height = luma_viewport->height;
-+ chroma_viewport->width = luma_viewport->width;
-+
-+ if (scl_data->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 dce_transform *xfm_dce,
-+ struct rect *luma_view_port,
-+ struct rect *chroma_view_port)
-+{
-+ struct dc_context *ctx = xfm_dce->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);
-+ }
-+}
-+
-+/*
-+ * 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 dce_transform *xfm_dce,
-+ const struct scaler_data *data)
-+{
-+ bool is_scaling_needed = false;
-+ struct dc_context *ctx = xfm_dce->base.ctx;
-+ uint32_t value = 0;
-+
-+ 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);
-+
-+ 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->format != PIXEL_FORMAT_420BPP12) {
-+ 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 = 0;
-+ /*
-+ * 0 - Replaced out of bound pixels with black pixel
-+ * (or any other required color)
-+ * 1 - Replaced out of bound pixels with the edge pixel
-+ */
-+ set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
-+ 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 dce_transform *xfm_dce,
-+ const struct scaler_data *data)
-+{
-+ uint32_t overscan_left_right = 0;
-+ uint32_t overscan_top_bottom = 0;
-+
-+ int overscan_right = data->h_active - data->recout.x - data->recout.width;
-+ int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
-+
-+ if (overscan_right < 0) {
-+ BREAK_TO_DEBUGGER();
-+ overscan_right = 0;
-+ }
-+ if (overscan_bottom < 0) {
-+ BREAK_TO_DEBUGGER();
-+ overscan_bottom = 0;
-+ }
-+
-+ set_reg_field_value(overscan_left_right, data->recout.x,
-+ 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, data->recout.y,
-+ 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(xfm_dce->base.ctx,
-+ mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
-+ overscan_left_right);
-+
-+ dm_write_reg(xfm_dce->base.ctx,
-+ mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
-+ overscan_top_bottom);
-+}
-+
-+static void set_coeff_update_complete(
-+ struct dce_transform *xfm_dce)
-+{
-+ uint32_t value;
-+
-+ value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
-+ set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
-+ dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
-+}
-+
-+static void program_multi_taps_filter(
-+ struct dce_transform *xfm_dce,
-+ int taps,
-+ const uint16_t *coeffs,
-+ enum ram_filter_type filter_type)
-+{
-+ struct dc_context *ctx = xfm_dce->base.ctx;
-+ int i, phase, pair;
-+ int array_idx = 0;
-+ int taps_pairs = (taps + 1) / 2;
-+ int phases_to_program = SCLV_PHASES / 2 + 1;
-+
-+ uint32_t select = 0;
-+ uint32_t power_ctl, power_ctl_off;
-+
-+ if (!coeffs)
-+ return;
-+
-+ /*We need to disable power gating on coeff memory to do programming*/
-+ power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
-+ power_ctl_off = power_ctl;
-+ set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
-+ dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
-+
-+ /*Wait to disable gating:*/
-+ for (i = 0; i < 10; i++) {
-+ if (get_reg_field_value(
-+ dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS),
-+ DCFEV_MEM_PWR_STATUS,
-+ SCLV_COEFF_MEM_PWR_STATE) == 0)
-+ break;
-+
-+ udelay(1);
-+ }
-+
-+ set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
-+
-+ 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, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
-+ for (pair = 0; pair < taps_pairs; pair++) {
-+ uint32_t data = 0;
-+
-+ set_reg_field_value(select, pair,
-+ SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
-+
-+ dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
-+
-+ set_reg_field_value(
-+ data, 1,
-+ SCLV_COEF_RAM_TAP_DATA,
-+ SCL_C_RAM_EVEN_TAP_COEF_EN);
-+ set_reg_field_value(
-+ data, coeffs[array_idx],
-+ SCLV_COEF_RAM_TAP_DATA,
-+ SCL_C_RAM_EVEN_TAP_COEF);
-+
-+ if (taps % 2 && pair == taps_pairs - 1) {
-+ set_reg_field_value(
-+ data, 0,
-+ SCLV_COEF_RAM_TAP_DATA,
-+ SCL_C_RAM_ODD_TAP_COEF_EN);
-+ array_idx++;
-+ } else {
-+ set_reg_field_value(
-+ data, 1,
-+ SCLV_COEF_RAM_TAP_DATA,
-+ SCL_C_RAM_ODD_TAP_COEF_EN);
-+ set_reg_field_value(
-+ data, coeffs[array_idx + 1],
-+ SCLV_COEF_RAM_TAP_DATA,
-+ SCL_C_RAM_ODD_TAP_COEF);
-+
-+ array_idx += 2;
-+ }
-+
-+ dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data);
-+ }
-+ }
-+
-+ /*We need to restore power gating on coeff memory to initial state*/
-+ dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
-+}
-+
-+static void calculate_inits(
-+ struct dce_transform *xfm_dce,
-+ const struct scaler_data *data,
-+ struct sclv_ratios_inits *inits,
-+ struct rect *luma_viewport,
-+ struct rect *chroma_viewport)
-+{
-+ inits->h_int_scale_ratio_luma =
-+ dal_fixed31_32_u2d19(data->ratios.horz) << 5;
-+ inits->v_int_scale_ratio_luma =
-+ dal_fixed31_32_u2d19(data->ratios.vert) << 5;
-+ inits->h_int_scale_ratio_chroma =
-+ dal_fixed31_32_u2d19(data->ratios.horz_c) << 5;
-+ inits->v_int_scale_ratio_chroma =
-+ dal_fixed31_32_u2d19(data->ratios.vert_c) << 5;
-+
-+ inits->h_init_luma.integer = 1;
-+ inits->v_init_luma.integer = 1;
-+ inits->h_init_chroma.integer = 1;
-+ inits->v_init_chroma.integer = 1;
-+}
-+
-+static void program_scl_ratios_inits(
-+ struct dce_transform *xfm_dce,
-+ struct sclv_ratios_inits *inits)
-+{
-+ struct dc_context *ctx = xfm_dce->base.ctx;
-+ uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
-+ uint32_t value = 0;
-+
-+ 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 = 0;
-+ 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 = 0;
-+ 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 = 0;
-+ 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);
-+
-+ addr = mmSCLV_HORZ_FILTER_INIT;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ inits->h_init_luma.fraction,
-+ SCLV_HORZ_FILTER_INIT,
-+ SCL_H_INIT_FRAC);
-+ set_reg_field_value(
-+ value,
-+ inits->h_init_luma.integer,
-+ SCLV_HORZ_FILTER_INIT,
-+ SCL_H_INIT_INT);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmSCLV_VERT_FILTER_INIT;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ inits->v_init_luma.fraction,
-+ SCLV_VERT_FILTER_INIT,
-+ SCL_V_INIT_FRAC);
-+ set_reg_field_value(
-+ value,
-+ inits->v_init_luma.integer,
-+ SCLV_VERT_FILTER_INIT,
-+ SCL_V_INIT_INT);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmSCLV_HORZ_FILTER_INIT_C;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ inits->h_init_chroma.fraction,
-+ SCLV_HORZ_FILTER_INIT_C,
-+ SCL_H_INIT_FRAC_C);
-+ set_reg_field_value(
-+ value,
-+ inits->h_init_chroma.integer,
-+ SCLV_HORZ_FILTER_INIT_C,
-+ SCL_H_INIT_INT_C);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmSCLV_VERT_FILTER_INIT_C;
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ inits->v_init_chroma.fraction,
-+ SCLV_VERT_FILTER_INIT_C,
-+ SCL_V_INIT_FRAC_C);
-+ set_reg_field_value(
-+ value,
-+ inits->v_init_chroma.integer,
-+ SCLV_VERT_FILTER_INIT_C,
-+ SCL_V_INIT_INT_C);
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
-+{
-+ if (taps == 4)
-+ return get_filter_4tap_64p(ratio);
-+ else if (taps == 2)
-+ return filter_2tap_64p;
-+ else if (taps == 1)
-+ return NULL;
-+ else {
-+ /* should never happen, bug */
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+}
-+
-+static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ uint32_t value;
-+
-+ value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
-+
-+ /*Use all three pieces of memory always*/
-+ set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
-+ /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
-+ set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
-+ LB_MEMORY_SIZE);
-+
-+ dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
-+
-+ return true;
-+}
-+
-+static void dce110_xfmv_set_scaler(
-+ struct transform *xfm,
-+ const struct scaler_data *data)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ bool is_scaling_required = false;
-+ bool filter_updated = false;
-+ const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
-+ struct rect luma_viewport = {0};
-+ struct rect chroma_viewport = {0};
-+
-+ dce110_xfmv_power_up_line_buffer(xfm);
-+ /* 1. 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);
-+
-+ /* 2. Program overscan */
-+ program_overscan(xfm_dce, data);
-+
-+ /* 3. Program taps and configuration */
-+ is_scaling_required = setup_scaling_configuration(xfm_dce, data);
-+
-+ if (is_scaling_required) {
-+ /* 4. Calculate and program ratio, filter initialization */
-+
-+ struct sclv_ratios_inits inits = { 0 };
-+
-+ calculate_inits(
-+ xfm_dce,
-+ data,
-+ &inits,
-+ &luma_viewport,
-+ &chroma_viewport);
-+
-+ program_scl_ratios_inits(xfm_dce, &inits);
-+
-+ coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert);
-+ coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz);
-+ coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c);
-+ coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c);
-+
-+ if (coeffs_v != xfm_dce->filter_v
-+ || coeffs_v_c != xfm_dce->filter_v_c
-+ || coeffs_h != xfm_dce->filter_h
-+ || coeffs_h_c != xfm_dce->filter_h_c) {
-+ /* 5. Program vertical filters */
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.v_taps,
-+ coeffs_v,
-+ FILTER_TYPE_RGB_Y_VERTICAL);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.v_taps_c,
-+ coeffs_v_c,
-+ FILTER_TYPE_CBCR_VERTICAL);
-+
-+ /* 6. Program horizontal filters */
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.h_taps,
-+ coeffs_h,
-+ FILTER_TYPE_RGB_Y_HORIZONTAL);
-+ program_multi_taps_filter(
-+ xfm_dce,
-+ data->taps.h_taps_c,
-+ coeffs_h_c,
-+ FILTER_TYPE_CBCR_HORIZONTAL);
-+
-+ xfm_dce->filter_v = coeffs_v;
-+ xfm_dce->filter_v_c = coeffs_v_c;
-+ xfm_dce->filter_h = coeffs_h;
-+ xfm_dce->filter_h_c = coeffs_h_c;
-+ filter_updated = true;
-+ }
-+ }
-+
-+ /* 7. Program the viewport */
-+ program_viewport(xfm_dce, &luma_viewport, &chroma_viewport);
-+
-+ /* 8. Set bit to flip to new coefficient memory */
-+ if (filter_updated)
-+ set_coeff_update_complete(xfm_dce);
-+}
-+
-+static void dce110_xfmv_reset(struct transform *xfm)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+
-+ xfm_dce->filter_h = NULL;
-+ xfm_dce->filter_v = NULL;
-+ xfm_dce->filter_h_c = NULL;
-+ xfm_dce->filter_v_c = NULL;
-+}
-+
-+static void dce110_xfmv_set_gamut_remap(
-+ struct transform *xfm,
-+ const struct xfm_grph_csc_adjustment *adjust)
-+{
-+ /* DO NOTHING*/
-+}
-+
-+static void dce110_xfmv_set_pixel_storage_depth(
-+ struct transform *xfm,
-+ enum lb_pixel_depth depth,
-+ const struct bit_depth_reduction_params *bit_depth_params)
-+{
-+ struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
-+ int pixel_depth, expan_mode;
-+ uint32_t reg_data = 0;
-+
-+ switch (depth) {
-+ case LB_PIXEL_DEPTH_18BPP:
-+ pixel_depth = 2;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_24BPP:
-+ pixel_depth = 1;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_30BPP:
-+ pixel_depth = 0;
-+ expan_mode = 1;
-+ break;
-+ case LB_PIXEL_DEPTH_36BPP:
-+ pixel_depth = 3;
-+ expan_mode = 0;
-+ break;
-+ default:
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+
-+ set_reg_field_value(
-+ reg_data,
-+ expan_mode,
-+ LBV_DATA_FORMAT,
-+ PIXEL_EXPAN_MODE);
-+
-+ set_reg_field_value(
-+ reg_data,
-+ pixel_depth,
-+ LBV_DATA_FORMAT,
-+ PIXEL_DEPTH);
-+
-+ dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
-+
-+ if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
-+ /*we should use unsupported capabilities
-+ * unless it is required by w/a*/
-+ dm_logger_write(xfm->ctx->logger, LOG_WARNING,
-+ "%s: Capability not supported",
-+ __func__);
-+ }
-+}
-+
-+static const struct transform_funcs dce110_xfmv_funcs = {
-+ .transform_reset = dce110_xfmv_reset,
-+ .transform_set_scaler = dce110_xfmv_set_scaler,
-+ .transform_set_gamut_remap =
-+ dce110_xfmv_set_gamut_remap,
-+ .transform_set_pixel_storage_depth =
-+ dce110_xfmv_set_pixel_storage_depth,
-+ .transform_get_optimal_number_of_taps =
-+ dce_transform_get_optimal_number_of_taps
-+};
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce110_transform_v_construct(
-+ struct dce_transform *xfm_dce,
-+ struct dc_context *ctx)
-+{
-+ xfm_dce->base.ctx = ctx;
-+
-+ xfm_dce->base.funcs = &dce110_xfmv_funcs;
-+
-+ xfm_dce->lb_pixel_depth_supported =
-+ LB_PIXEL_DEPTH_18BPP |
-+ LB_PIXEL_DEPTH_24BPP |
-+ LB_PIXEL_DEPTH_30BPP;
-+
-+ xfm_dce->prescaler_on = true;
-+ xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
-+ xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h
-new file mode 100644
-index 0000000..267af34
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h
-@@ -0,0 +1,37 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_V_DCE110_H__
-+#define __DAL_TRANSFORM_V_DCE110_H__
-+
-+#include "../dce/dce_transform.h"
-+
-+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
-+#define LB_BITS_PER_ENTRY 144
-+
-+bool dce110_transform_v_construct(
-+ struct dce_transform *xfm110,
-+ struct dc_context *ctx);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h
-new file mode 100644
-index 0000000..55f5238
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h
-@@ -0,0 +1,30 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ * Authors: AMD
-+ *
-+ */
-+
-+#ifndef _DCE110_TYPES_H_
-+#define __DCE110_TYPES_H_
-+
-+#define GAMMA_SEGMENTS_NUM 16
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_DCE110_DCE110_TYPES_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
-new file mode 100644
-index 0000000..34fba07
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
-@@ -0,0 +1,11 @@
-+#
-+# Makefile for the 'controller' sub-component of DAL.
-+# It provides the control and status of HW CRTC block.
-+
-+DCE112 = dce112_compressor.o dce112_hw_sequencer.o \
-+dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \
-+dce112_opp.o
-+
-+AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_DCE112)
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
-new file mode 100644
-index 0000000..22a5aba
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
-@@ -0,0 +1,859 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+#include "gmc/gmc_8_1_sh_mask.h"
-+#include "gmc/gmc_8_1_d.h"
-+
-+#include "include/logger_interface.h"
-+
-+#include "dce112_compressor.h"
-+
-+#define DCP_REG(reg)\
-+ (reg + cp110->offsets.dcp_offset)
-+#define DMIF_REG(reg)\
-+ (reg + cp110->offsets.dmif_offset)
-+
-+static const struct dce112_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 dce112_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 dce112_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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%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:
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%s: Invalid LPT ROW_SIZE!!!",
-+ __func__);
-+ break;
-+ }
-+ } else {
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%s: LPT MC Configuration is not provided",
-+ __func__);
-+ }
-+
-+ return lpt_control;
-+}
-+
-+static bool is_source_bigger_than_epanel_size(
-+ struct dce112_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 dce112_compressor *cp110,
-+ uint32_t pixels)
-+{
-+ return 256 * ((pixels + 255) / 256);
-+}
-+
-+static void wait_for_fbc_state_changed(
-+ struct dce112_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;
-+ udelay(10);
-+ counter++;
-+ }
-+
-+ if (counter == 10) {
-+ dm_logger_write(
-+ cp110->base.ctx->logger, LOG_WARNING,
-+ "%s: wait counter exceeded, changes to HW not applied",
-+ __func__);
-+ }
-+}
-+
-+void dce112_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 dce112_compressor_enable_fbc(
-+ struct compressor *compressor,
-+ uint32_t paths_num,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
-+
-+ if (compressor->options.bits.FBC_SUPPORT &&
-+ (compressor->options.bits.DUMMY_BACKEND == 0) &&
-+ (!dce112_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)) {
-+ dce112_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 dce112_compressor_disable_fbc(struct compressor *compressor)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
-+
-+ if (compressor->options.bits.FBC_SUPPORT &&
-+ dce112_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)
-+ dce112_compressor_disable_lpt(compressor);
-+
-+ wait_for_fbc_state_changed(cp110, false);
-+ }
-+}
-+
-+bool dce112_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 dce112_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 dce112_compressor_program_compressed_surface_address_and_pitch(
-+ struct compressor *compressor,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_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
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%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 dce112_compressor_disable_lpt(struct compressor *compressor)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_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 dce112_compressor_enable_lpt(struct compressor *compressor)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_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 dce112_compressor_program_lpt_control(
-+ struct compressor *compressor,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce112_compressor *cp110 = TO_DCE112_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:
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%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 dce112_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 dce112_compressor_construct(struct dce112_compressor *compressor,
-+ struct dc_context *ctx)
-+{
-+ struct dc_bios *bp = ctx->dc_bios;
-+ struct embedded_panel_info panel_info;
-+
-+ compressor->base.options.bits.FBC_SUPPORT = true;
-+ compressor->base.options.bits.LPT_SUPPORT = true;
-+ /* For DCE 11 always use one DRAM channel for LPT */
-+ compressor->base.lpt_channels_num = 1;
-+ compressor->base.options.bits.DUMMY_BACKEND = false;
-+
-+ /* 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;
-+
-+ compressor->base.options.bits.CLK_GATING_DISABLED = false;
-+
-+ compressor->base.ctx = ctx;
-+ compressor->base.embedded_panel_h_size = 0;
-+ compressor->base.embedded_panel_v_size = 0;
-+ compressor->base.memory_bus_width = ctx->asic_id.vram_width;
-+ 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 (BP_RESULT_OK ==
-+ bp->funcs->get_embedded_panel_info(bp, &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 *dce112_compressor_create(struct dc_context *ctx)
-+{
-+ struct dce112_compressor *cp110 =
-+ dm_alloc(sizeof(struct dce112_compressor));
-+
-+ if (!cp110)
-+ return NULL;
-+
-+ if (dce112_compressor_construct(cp110, ctx))
-+ return &cp110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(cp110);
-+ return NULL;
-+}
-+
-+void dce112_compressor_destroy(struct compressor **compressor)
-+{
-+ dm_free(TO_DCE112_COMPRESSOR(*compressor));
-+ *compressor = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h
-new file mode 100644
-index 0000000..1065063
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h
-@@ -0,0 +1,78 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_DCE112_H__
-+#define __DC_COMPRESSOR_DCE112_H__
-+
-+#include "../inc/compressor.h"
-+
-+#define TO_DCE112_COMPRESSOR(compressor)\
-+ container_of(compressor, struct dce112_compressor, base)
-+
-+struct dce112_compressor_reg_offsets {
-+ uint32_t dcp_offset;
-+ uint32_t dmif_offset;
-+};
-+
-+struct dce112_compressor {
-+ struct compressor base;
-+ struct dce112_compressor_reg_offsets offsets;
-+};
-+
-+struct compressor *dce112_compressor_create(struct dc_context *ctx);
-+
-+bool dce112_compressor_construct(struct dce112_compressor *cp110,
-+ struct dc_context *ctx);
-+
-+void dce112_compressor_destroy(struct compressor **cp);
-+
-+/* FBC RELATED */
-+void dce112_compressor_power_up_fbc(struct compressor *cp);
-+
-+void dce112_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num,
-+ struct compr_addr_and_pitch_params *params);
-+
-+void dce112_compressor_disable_fbc(struct compressor *cp);
-+
-+void dce112_compressor_set_fbc_invalidation_triggers(struct compressor *cp,
-+ uint32_t fbc_trigger);
-+
-+void dce112_compressor_program_compressed_surface_address_and_pitch(
-+ struct compressor *cp,
-+ struct compr_addr_and_pitch_params *params);
-+
-+bool dce112_compressor_is_fbc_enabled_in_hw(struct compressor *cp,
-+ uint32_t *fbc_mapped_crtc_id);
-+
-+/* LPT RELATED */
-+void dce112_compressor_enable_lpt(struct compressor *cp);
-+
-+void dce112_compressor_disable_lpt(struct compressor *cp);
-+
-+void dce112_compressor_program_lpt_control(struct compressor *cp,
-+ struct compr_addr_and_pitch_params *params);
-+
-+bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *cp);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
-new file mode 100644
-index 0000000..204f613
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
-@@ -0,0 +1,166 @@
-+/*
-+ * 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 "dce112_hw_sequencer.h"
-+
-+#include "dce110/dce110_hw_sequencer.h"
-+
-+/* include DCE11.2 register header files */
-+#include "dce/dce_11_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+struct dce112_hw_seq_reg_offsets {
-+ uint32_t crtc;
-+};
-+
-+
-+static const struct dce112_hw_seq_reg_offsets reg_offsets[] = {
-+{
-+ .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+}
-+};
-+#define HW_REG_CRTC(reg, id)\
-+ (reg + reg_offsets[id].crtc)
-+
-+/*******************************************************************************
-+ * Private definitions
-+ ******************************************************************************/
-+
-+static void dce112_init_pte(struct dc_context *ctx)
-+{
-+ uint32_t addr;
-+ uint32_t value = 0;
-+ uint32_t chunk_int = 0;
-+ uint32_t chunk_mul = 0;
-+
-+ 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);
-+ }
-+}
-+
-+static bool dce112_enable_display_power_gating(
-+ struct core_dc *dc,
-+ 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;
-+ struct dc_context *ctx = dc->ctx;
-+
-+ 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);
-+
-+ /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
-+ * by default when command table is called
-+ */
-+ dm_write_reg(ctx,
-+ HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
-+ 0);
-+ }
-+
-+ if (power_gating != PIPE_GATING_CONTROL_ENABLE)
-+ dce112_init_pte(ctx);
-+
-+ if (bp_result == BP_RESULT_OK)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+bool dce112_hw_sequencer_construct(struct core_dc *dc)
-+{
-+ /* All registers used by dce11.2 match those in dce11 in offset and
-+ * structure
-+ */
-+ dce110_hw_sequencer_construct(dc);
-+ dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h
-new file mode 100644
-index 0000000..d96c582
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_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_DCE112_H__
-+#define __DC_HWSS_DCE112_H__
-+
-+#include "core_types.h"
-+
-+struct core_dc;
-+
-+bool dce112_hw_sequencer_construct(struct core_dc *dc);
-+
-+#endif /* __DC_HWSS_DCE112_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c
-new file mode 100644
-index 0000000..c29007d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c
-@@ -0,0 +1,54 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce112_mem_input.h"
-+
-+
-+#include "dce/dce_11_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+
-+#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)
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce112_mem_input_construct(
-+ struct dce110_mem_input *mem_input110,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_mem_input_reg_offsets *offsets)
-+{
-+ if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets))
-+ return false;
-+
-+ mem_input110->base.funcs->mem_input_program_display_marks =
-+ dce_mem_input_program_display_marks;
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h
-new file mode 100644
-index 0000000..de2aaf0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.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 __DC_MEM_INPUT_DCE112_H__
-+#define __DC_MEM_INPUT_DCE112_H__
-+
-+#include "mem_input.h"
-+#include "dce110/dce110_mem_input.h"
-+
-+bool dce112_mem_input_construct(
-+ struct dce110_mem_input *mem_input110,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_mem_input_reg_offsets *offsets);
-+
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c
-new file mode 100644
-index 0000000..23c2d10
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c
-@@ -0,0 +1,72 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+#include "dce112_opp.h"
-+
-+#include "gamma_types.h"
-+
-+enum {
-+ MAX_LUT_ENTRY = 256,
-+ MAX_NUMBER_OF_ENTRIES = 256
-+};
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+static struct opp_funcs funcs = {
-+ .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
-+ .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_program_regamma_pwl = dce110_opp_program_regamma_pwl,
-+ .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
-+ .opp_destroy = dce110_opp_destroy,
-+ .opp_program_fmt = dce112_opp_program_fmt,
-+ .opp_program_bit_depth_reduction =
-+ dce110_opp_program_bit_depth_reduction
-+};
-+
-+bool dce112_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;
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h
-new file mode 100644
-index 0000000..9443b87
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.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 __DC_OPP_DCE112_H__
-+#define __DC_OPP_DCE112_H__
-+
-+#include "dc_types.h"
-+#include "opp.h"
-+#include "../dce110/dce110_opp.h"
-+#include "core_types.h"
-+
-+void dce112_opp_program_clamping_and_pixel_encoding(
-+ struct output_pixel_processor *opp,
-+ const struct clamping_and_pixel_encoding_params *params);
-+
-+void dce112_opp_program_fmt(
-+ struct output_pixel_processor *opp,
-+ struct bit_depth_reduction_params *fmt_bit_depth,
-+ struct clamping_and_pixel_encoding_params *clamping);
-+
-+bool dce112_opp_construct(struct dce110_opp *opp110,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_opp_reg_offsets *offsets);
-+
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c
-new file mode 100644
-index 0000000..2d90721
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c
-@@ -0,0 +1,215 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+#include "dce112_opp.h"
-+
-+#define FMT_REG(reg)\
-+ (reg + opp110->offsets.fmt_offset)
-+#define FMT_MEM_REG(reg)\
-+ (reg + opp110->offsets.fmt_mem_offset)
-+
-+/**
-+ * 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
-+ */
-+
-+/**
-+ * set_pixel_encoding
-+ *
-+ * Set Pixel Encoding
-+ * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
-+ * 1: YCbCr 4:2:2
-+ * 2: YCbCr 4:2:0
-+ */
-+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);
-+
-+ /*00 - Pixels drop mode HW default*/
-+ set_reg_field_value(fmt_cntl_value,
-+ 0,
-+ FMT_CONTROL,
-+ FMT_SUBSAMPLING_MODE);
-+
-+ /* By default no bypass*/
-+ set_reg_field_value(fmt_cntl_value,
-+ 0,
-+ FMT_CONTROL,
-+ FMT_CBCR_BIT_REDUCTION_BYPASS);
-+
-+ if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
-+ set_reg_field_value(fmt_cntl_value,
-+ 1,
-+ FMT_CONTROL,
-+ FMT_PIXEL_ENCODING);
-+
-+ /*00 - Cb before Cr ,01 - Cr before Cb*/
-+ set_reg_field_value(fmt_cntl_value,
-+ 0,
-+ FMT_CONTROL,
-+ FMT_SUBSAMPLING_ORDER);
-+ }
-+
-+ if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
-+ set_reg_field_value(fmt_cntl_value,
-+ 2,
-+ FMT_CONTROL,
-+ FMT_PIXEL_ENCODING);
-+
-+ /* 02 - Subsampling mode, 3 taps*/
-+ set_reg_field_value(fmt_cntl_value,
-+ 2,
-+ FMT_CONTROL,
-+ FMT_SUBSAMPLING_MODE);
-+
-+ /* 00 - Enable CbCr bit reduction bypass to preserve precision*/
-+ set_reg_field_value(fmt_cntl_value,
-+ 1,
-+ FMT_CONTROL,
-+ FMT_CBCR_BIT_REDUCTION_BYPASS);
-+ }
-+ dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
-+
-+}
-+
-+void dce112_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);
-+
-+ dce110_opp_set_clamping(opp110, params);
-+ set_pixel_encoding(opp110, params);
-+}
-+
-+static void program_formatter_420_memory(struct output_pixel_processor *opp)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+ uint32_t fmt_cntl_value;
-+ uint32_t fmt_mem_cntl_value;
-+ uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL);
-+ uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL);
-+
-+ fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr);
-+ fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr);
-+ /* Program source select*/
-+ /* Use HW default source select for FMT_MEMORYx_CONTROL */
-+ /* Use that value for FMT_SRC_SELECT as well*/
-+ set_reg_field_value(fmt_cntl_value,
-+ get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL),
-+ FMT_CONTROL,
-+ FMT_SRC_SELECT);
-+ dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value);
-+
-+ /* Turn on the memory */
-+ set_reg_field_value(fmt_mem_cntl_value,
-+ 0,
-+ FMT_MEMORY0_CONTROL,
-+ FMT420_MEM0_PWR_FORCE);
-+ dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value);
-+}
-+
-+static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
-+{
-+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
-+ uint32_t value;
-+ uint32_t addr = FMT_REG(mmFMT_CONTROL);
-+ uint8_t counter = 10;
-+
-+
-+ value = dm_read_reg(opp110->base.ctx, addr);
-+
-+ /* clear previous phase lock status*/
-+ set_reg_field_value(value,
-+ 1,
-+ FMT_CONTROL,
-+ FMT_420_PIXEL_PHASE_LOCKED_CLEAR);
-+ dm_write_reg(opp110->base.ctx, addr, value);
-+
-+ /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
-+ while (counter > 0) {
-+ value = dm_read_reg(opp110->base.ctx, addr);
-+
-+ if (get_reg_field_value(
-+ value,
-+ FMT_CONTROL,
-+ FMT_420_PIXEL_PHASE_LOCKED) == 1)
-+ break;
-+
-+ msleep(10);
-+ counter--;
-+ }
-+
-+ if (counter == 0)
-+ dm_logger_write(opp->ctx->logger, LOG_ERROR,
-+ "%s:opp program formattter reset dig resync info time out.\n",
-+ __func__);
-+}
-+
-+void dce112_opp_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 */
-+
-+ if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-+ program_formatter_420_memory(opp);
-+
-+ dce110_opp_program_bit_depth_reduction(
-+ opp,
-+ fmt_bit_depth);
-+
-+ dce112_opp_program_clamping_and_pixel_encoding(
-+ opp,
-+ clamping);
-+
-+ if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-+ program_formatter_reset_dig_resync_fifo(opp);
-+
-+ return;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
-new file mode 100644
-index 0000000..bfb2c3f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
-@@ -0,0 +1,1418 @@
-+/*
-+* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce110/dce110_resource.h"
-+#include "dce110/dce110_timing_generator.h"
-+#include "dce112/dce112_mem_input.h"
-+
-+#include "irq/dce110/irq_service_dce110.h"
-+#include "dce/dce_transform.h"
-+#include "dce/dce_link_encoder.h"
-+#include "dce/dce_stream_encoder.h"
-+#include "dce/dce_audio.h"
-+#include "dce112/dce112_opp.h"
-+#include "dce110/dce110_ipp.h"
-+#include "dce/dce_clock_source.h"
-+
-+#include "dce/dce_hwseq.h"
-+#include "dce112/dce112_hw_sequencer.h"
-+
-+#include "reg_helper.h"
-+
-+#include "dce/dce_11_2_d.h"
-+#include "dce/dce_11_2_sh_mask.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
-+
-+#ifndef mmBIOS_SCRATCH_2
-+ #define mmBIOS_SCRATCH_2 0x05CB
-+ #define mmBIOS_SCRATCH_6 0x05CF
-+#endif
-+
-+#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
-+ #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
-+ #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC
-+ #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC
-+ #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC
-+ #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC
-+ #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC
-+ #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC
-+#endif
-+
-+#ifndef mmDP_DPHY_FAST_TRAINING
-+ #define mmDP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
-+ #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
-+ #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
-+ #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
-+ #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
-+ #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
-+ #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
-+#endif
-+
-+enum dce112_clk_src_array_id {
-+ DCE112_CLK_SRC_PLL0,
-+ DCE112_CLK_SRC_PLL1,
-+ DCE112_CLK_SRC_PLL2,
-+ DCE112_CLK_SRC_PLL3,
-+ DCE112_CLK_SRC_PLL4,
-+ DCE112_CLK_SRC_PLL5,
-+
-+ DCE112_CLK_SRC_TOTAL
-+};
-+
-+static const struct dce110_timing_generator_offsets dce112_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 dce112_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_ipp_reg_offsets 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),
-+}
-+};
-+
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define transform_regs(id)\
-+[id] = {\
-+ XFM_COMMON_REG_LIST_DCE110(id)\
-+}
-+
-+static const struct dce_transform_registers xfm_regs[] = {
-+ transform_regs(0),
-+ transform_regs(1),
-+ transform_regs(2),
-+ transform_regs(3),
-+ transform_regs(4),
-+ transform_regs(5)
-+};
-+
-+static const struct dce_transform_shift xfm_shift = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce_transform_mask xfm_mask = {
-+ XFM_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_REG_LIST(id)\
-+}
-+
-+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 hpd_regs(id)\
-+[id] = {\
-+ HPD_REG_LIST(id)\
-+}
-+
-+static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
-+ hpd_regs(0),
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5)
-+};
-+
-+#define link_regs(id)\
-+[id] = {\
-+ LE_DCE110_REG_LIST(id)\
-+}
-+
-+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] = {\
-+ SE_COMMON_REG_LIST(id),\
-+ .TMDS_CNTL = 0,\
-+}
-+
-+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)
-+};
-+
-+static const struct dce_stream_encoder_shift se_shift = {
-+ SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT)
-+};
-+
-+static const struct dce_stream_encoder_mask se_mask = {
-+ SE_COMMON_MASK_SH_LIST_DCE112(_MASK)
-+};
-+
-+#define audio_regs(id)\
-+[id] = {\
-+ AUD_COMMON_REG_LIST(id)\
-+}
-+
-+static const struct dce_audio_registers audio_regs[] = {
-+ audio_regs(0),
-+ audio_regs(1),
-+ audio_regs(2),
-+ audio_regs(3),
-+ audio_regs(4),
-+ audio_regs(5)
-+};
-+
-+static const struct dce_audio_shift audio_shift = {
-+ AUD_COMMON_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_aduio_mask audio_mask = {
-+ AUD_COMMON_MASK_SH_LIST(_MASK)
-+};
-+
-+
-+static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = {
-+{
-+ .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_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),
-+ .fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_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),
-+ .fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_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),
-+ .fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_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),
-+ .fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_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),
-+ .fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL),
-+ .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
-+ .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+}
-+};
-+
-+#define clk_src_regs(index, id)\
-+[index] = {\
-+ CS_COMMON_REG_LIST_DCE_112(id),\
-+}
-+
-+static const struct dce110_clk_src_regs clk_src_regs[] = {
-+ clk_src_regs(0, A),
-+ clk_src_regs(1, B),
-+ clk_src_regs(2, C),
-+ clk_src_regs(3, D),
-+ clk_src_regs(4, E),
-+ clk_src_regs(5, F)
-+};
-+
-+static const struct dce110_clk_src_shift cs_shift = {
-+ CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT)
-+};
-+
-+static const struct dce110_clk_src_mask cs_mask = {
-+ CS_COMMON_MASK_SH_LIST_DCE_112(_MASK)
-+};
-+
-+static const struct bios_registers bios_regs = {
-+ .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
-+};
-+
-+static const struct resource_caps polaris_10_resource_cap = {
-+ .num_timing_generator = 6,
-+ .num_audio = 6,
-+ .num_stream_encoder = 6,
-+ .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */
-+};
-+
-+static const struct resource_caps polaris_11_resource_cap = {
-+ .num_timing_generator = 5,
-+ .num_audio = 5,
-+ .num_stream_encoder = 5,
-+ .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */
-+};
-+
-+#define CTX ctx
-+#define REG(reg) mm ## reg
-+
-+#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 void read_dce_straps(
-+ struct dc_context *ctx,
-+ struct resource_straps *straps)
-+{
-+ REG_GET_2(CC_DC_HDMI_STRAPS,
-+ HDMI_DISABLE, &straps->hdmi_disable,
-+ AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
-+
-+ REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
-+}
-+
-+static struct audio *create_audio(
-+ struct dc_context *ctx, unsigned int inst)
-+{
-+ return dce_audio_create(ctx, inst,
-+ &audio_regs[inst], &audio_shift, &audio_mask);
-+}
-+
-+
-+static struct timing_generator *dce112_timing_generator_create(
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ struct dce110_timing_generator *tg110 =
-+ dm_alloc(sizeof(struct dce110_timing_generator));
-+
-+ if (!tg110)
-+ return NULL;
-+
-+ if (dce110_timing_generator_construct(tg110, ctx, instance, offsets))
-+ return &tg110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(tg110);
-+ return NULL;
-+}
-+
-+static struct stream_encoder *dce112_stream_encoder_create(
-+ enum engine_id eng_id,
-+ struct dc_context *ctx)
-+{
-+ struct dce110_stream_encoder *enc110 =
-+ dm_alloc(sizeof(struct dce110_stream_encoder));
-+
-+ if (!enc110)
-+ return NULL;
-+
-+ if (dce110_stream_encoder_construct(
-+ enc110, ctx, ctx->dc_bios, eng_id,
-+ &stream_enc_regs[eng_id], &se_shift, &se_mask))
-+ return &enc110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+#define SRII(reg_name, block, id)\
-+ .reg_name[id] = mm ## block ## id ## _ ## reg_name
-+
-+static const struct dce_hwseq_registers hwseq_reg = {
-+ HWSEQ_DCE112_REG_LIST()
-+};
-+
-+static const struct dce_hwseq_shift hwseq_shift = {
-+ HWSEQ_DCE112_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_hwseq_mask hwseq_mask = {
-+ HWSEQ_DCE112_MASK_SH_LIST(_MASK)
-+};
-+
-+static struct dce_hwseq *dce112_hwseq_create(
-+ struct dc_context *ctx)
-+{
-+ struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
-+
-+ if (hws) {
-+ hws->ctx = ctx;
-+ hws->regs = &hwseq_reg;
-+ hws->shifts = &hwseq_shift;
-+ hws->masks = &hwseq_mask;
-+ }
-+ return hws;
-+}
-+
-+static const struct resource_create_funcs res_create_funcs = {
-+ .read_dce_straps = read_dce_straps,
-+ .create_audio = create_audio,
-+ .create_stream_encoder = dce112_stream_encoder_create,
-+ .create_hwseq = dce112_hwseq_create,
-+};
-+
-+#define mi_inst_regs(id) { MI_REG_LIST(id) }
-+static const struct dce_mem_input_registers mi_regs[] = {
-+ mi_inst_regs(0),
-+ mi_inst_regs(1),
-+ mi_inst_regs(2),
-+ mi_inst_regs(3),
-+ mi_inst_regs(4),
-+ mi_inst_regs(5),
-+};
-+
-+static const struct dce_mem_input_shift mi_shifts = {
-+ MI_DCE_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_mem_input_mask mi_masks = {
-+ MI_DCE_MASK_SH_LIST(_MASK)
-+};
-+
-+static struct mem_input *dce112_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(sizeof(struct dce110_mem_input));
-+
-+ if (!mem_input110)
-+ return NULL;
-+
-+ if (dce112_mem_input_construct(mem_input110, ctx, inst, offset)) {
-+ struct mem_input *mi = &mem_input110->base;
-+
-+ mi->regs = &mi_regs[inst];
-+ mi->shifts = &mi_shifts;
-+ mi->masks = &mi_masks;
-+ return mi;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(mem_input110);
-+ return NULL;
-+}
-+
-+static void dce112_transform_destroy(struct transform **xfm)
-+{
-+ dm_free(TO_DCE_TRANSFORM(*xfm));
-+ *xfm = NULL;
-+}
-+
-+static struct transform *dce112_transform_create(
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ struct dce_transform *transform =
-+ dm_alloc(sizeof(struct dce_transform));
-+
-+ if (!transform)
-+ return NULL;
-+
-+ if (dce_transform_construct(transform, ctx, inst,
-+ &xfm_regs[inst], &xfm_shift, &xfm_mask)) {
-+ transform->lb_memory_size = 0x1404; /*5124*/
-+ return &transform->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(transform);
-+ return NULL;
-+}
-+struct link_encoder *dce112_link_encoder_create(
-+ const struct encoder_init_data *enc_init_data)
-+{
-+ struct dce110_link_encoder *enc110 =
-+ dm_alloc(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_hpd_regs[enc_init_data->hpd_source])) {
-+
-+ enc110->base.features.ycbcr420_supported = false;
-+ enc110->base.features.max_hdmi_pixel_clock = 600000;
-+ return &enc110->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+struct input_pixel_processor *dce112_ipp_create(
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_ipp_reg_offsets *offset)
-+{
-+ struct dce110_ipp *ipp =
-+ dm_alloc(sizeof(struct dce110_ipp));
-+
-+ if (!ipp)
-+ return NULL;
-+
-+ if (dce110_ipp_construct(ipp, ctx, inst, offset))
-+ return &ipp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(ipp);
-+ return NULL;
-+}
-+
-+void dce112_ipp_destroy(struct input_pixel_processor **ipp)
-+{
-+ dm_free(TO_DCE110_IPP(*ipp));
-+ *ipp = NULL;
-+}
-+
-+struct output_pixel_processor *dce112_opp_create(
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_opp_reg_offsets *offset)
-+{
-+ struct dce110_opp *opp =
-+ dm_alloc(sizeof(struct dce110_opp));
-+
-+ if (!opp)
-+ return NULL;
-+
-+ if (dce112_opp_construct(opp,
-+ ctx, inst, offset))
-+ return &opp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(opp);
-+ return NULL;
-+}
-+
-+void dce112_opp_destroy(struct output_pixel_processor **opp)
-+{
-+ struct dce110_opp *dce110_opp;
-+
-+ if (!opp || !*opp)
-+ return;
-+
-+ dce110_opp = FROM_DCE11_OPP(*opp);
-+
-+ dm_free(dce110_opp->regamma.coeff128_dx);
-+ dm_free(dce110_opp->regamma.coeff128_oem);
-+ dm_free(dce110_opp->regamma.coeff128);
-+ dm_free(dce110_opp->regamma.axis_x_1025);
-+ dm_free(dce110_opp->regamma.axis_x_256);
-+ dm_free(dce110_opp->regamma.coordinates_x);
-+ dm_free(dce110_opp->regamma.rgb_regamma);
-+ dm_free(dce110_opp->regamma.rgb_resulted);
-+ dm_free(dce110_opp->regamma.rgb_oem);
-+ dm_free(dce110_opp->regamma.rgb_user);
-+
-+ dm_free(dce110_opp);
-+ *opp = NULL;
-+}
-+
-+struct clock_source *dce112_clock_source_create(
-+ struct dc_context *ctx,
-+ struct dc_bios *bios,
-+ enum clock_source_id id,
-+ const struct dce110_clk_src_regs *regs,
-+ bool dp_clk_src)
-+{
-+ struct dce110_clk_src *clk_src =
-+ dm_alloc(sizeof(struct dce110_clk_src));
-+
-+ if (!clk_src)
-+ return NULL;
-+
-+ if (dce110_clk_src_construct(clk_src, ctx, bios, id,
-+ regs, &cs_shift, &cs_mask)) {
-+ clk_src->base.dp_clk_src = dp_clk_src;
-+ return &clk_src->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-+void dce112_clock_source_destroy(struct clock_source **clk_src)
-+{
-+ dm_free(TO_DCE110_CLK_SRC(*clk_src));
-+ *clk_src = NULL;
-+}
-+
-+static void destruct(struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ if (pool->base.opps[i] != NULL)
-+ dce112_opp_destroy(&pool->base.opps[i]);
-+
-+ if (pool->base.transforms[i] != NULL)
-+ dce112_transform_destroy(&pool->base.transforms[i]);
-+
-+ if (pool->base.ipps[i] != NULL)
-+ dce112_ipp_destroy(&pool->base.ipps[i]);
-+
-+ if (pool->base.mis[i] != NULL) {
-+ dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
-+ pool->base.mis[i] = NULL;
-+ }
-+
-+ if (pool->base.timing_generators[i] != NULL) {
-+ dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
-+ pool->base.timing_generators[i] = NULL;
-+ }
-+ }
-+
-+ for (i = 0; i < pool->base.stream_enc_count; i++) {
-+ if (pool->base.stream_enc[i] != NULL)
-+ dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] != NULL) {
-+ dce112_clock_source_destroy(&pool->base.clock_sources[i]);
-+ }
-+ }
-+
-+ if (pool->base.dp_clock_source != NULL)
-+ dce112_clock_source_destroy(&pool->base.dp_clock_source);
-+
-+ for (i = 0; i < pool->base.audio_count; i++) {
-+ if (pool->base.audios[i] != NULL) {
-+ dce_aud_destroy(&pool->base.audios[i]);
-+ }
-+ }
-+
-+ if (pool->base.display_clock != NULL) {
-+ dal_display_clock_destroy(&pool->base.display_clock);
-+ }
-+
-+ if (pool->base.irqs != NULL) {
-+ dal_irq_service_destroy(&pool->base.irqs);
-+ }
-+}
-+
-+static struct clock_source *find_matching_pll(struct resource_context *res_ctx,
-+ const struct core_stream *const stream)
-+{
-+ switch (stream->sink->link->link_enc->transmitter) {
-+ case TRANSMITTER_UNIPHY_A:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL0];
-+ case TRANSMITTER_UNIPHY_B:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL1];
-+ case TRANSMITTER_UNIPHY_C:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL2];
-+ case TRANSMITTER_UNIPHY_D:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL3];
-+ case TRANSMITTER_UNIPHY_E:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL4];
-+ case TRANSMITTER_UNIPHY_F:
-+ return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL5];
-+ default:
-+ return NULL;
-+ };
-+
-+ return 0;
-+}
-+
-+static enum dc_status validate_mapped_resource(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status status = DC_OK;
-+ uint8_t i, j, k;
-+
-+ 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 core_link *link = stream->sink->link;
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (!pipe_ctx->tg->funcs->validate_timing(
-+ pipe_ctx->tg, &stream->public.timing))
-+ return DC_FAIL_CONTROLLER_VALIDATE;
-+
-+ status = dce110_resource_build_pipe_hw_param(pipe_ctx);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ if (!link->link_enc->funcs->validate_output_with_stream(
-+ link->link_enc,
-+ pipe_ctx))
-+ return DC_FAIL_ENC_VALIDATE;
-+
-+ /* TODO: validate audio ASIC caps, encoder */
-+
-+ status = dc_link_validate_mode_timing(stream,
-+ link,
-+ &stream->public.timing);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ resource_build_info_frame(pipe_ctx);
-+
-+ /* do not need to validate non root pipes */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+enum dc_status dce112_validate_bandwidth(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ dm_logger_write(
-+ dc->ctx->logger, LOG_BANDWIDTH_CALCS,
-+ "%s: start",
-+ __func__);
-+
-+ if (!bw_calcs(
-+ dc->ctx,
-+ &dc->bw_dceip,
-+ &dc->bw_vbios,
-+ context->res_ctx.pipe_ctx,
-+ context->res_ctx.pool->pipe_count,
-+ &context->bw_results))
-+ result = DC_FAIL_BANDWIDTH_VALIDATE;
-+ else
-+ result = DC_OK;
-+
-+ if (result == DC_FAIL_BANDWIDTH_VALIDATE)
-+ dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
-+ "%s: Bandwidth validation failed!",
-+ __func__);
-+
-+ if (memcmp(&dc->current_context->bw_results,
-+ &context->bw_results, sizeof(context->bw_results))) {
-+ struct log_entry log_entry;
-+ dm_logger_open(
-+ dc->ctx->logger,
-+ &log_entry,
-+ LOG_BANDWIDTH_CALCS);
-+ dm_logger_append(&log_entry, "%s: finish,\n"
-+ "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
-+ "stutMark_b: %d stutMark_a: %d\n",
-+ __func__,
-+ 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);
-+ dm_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);
-+ dm_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);
-+ dm_logger_append(&log_entry,
-+ "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
-+ "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %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.blackout_recovery_time_us);
-+ dm_logger_close(&log_entry);
-+ }
-+ return result;
-+}
-+
-+enum dc_status resource_map_phy_clock_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ uint8_t i, j, k;
-+
-+ /* acquire new resources */
-+ 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]);
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (dc_is_dp_signal(pipe_ctx->stream->signal)
-+ || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
-+ pipe_ctx->clock_source =
-+ context->res_ctx.pool->dp_clock_source;
-+ else
-+ pipe_ctx->clock_source =
-+ find_matching_pll(&context->res_ctx,
-+ stream);
-+
-+ if (pipe_ctx->clock_source == NULL)
-+ return DC_NO_CLOCK_SOURCE_RESOURCE;
-+
-+ resource_reference_clock_source(
-+ &context->res_ctx,
-+ pipe_ctx->clock_source);
-+
-+ /* only one cs per stream regardless of mpo */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+static bool dce112_validate_surface_sets(
-+ const struct dc_validation_set set[],
-+ int set_count)
-+{
-+ int i;
-+
-+ for (i = 0; i < set_count; i++) {
-+ if (set[i].surface_count == 0)
-+ continue;
-+
-+ if (set[i].surface_count > 1)
-+ return false;
-+
-+ if (set[i].surfaces[0]->clip_rect.width
-+ != set[i].target->streams[0]->src.width
-+ || set[i].surfaces[0]->clip_rect.height
-+ != set[i].target->streams[0]->src.height)
-+ return false;
-+ if (set[i].surfaces[0]->format
-+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+enum dc_status dce112_validate_with_context(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context)
-+{
-+ struct dc_context *dc_ctx = dc->ctx;
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ int i;
-+
-+ if (!dce112_validate_surface_sets(set, set_count))
-+ return DC_FAIL_SURFACE_VALIDATE;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ for (i = 0; i < set_count; i++) {
-+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
-+ dc_target_retain(&context->targets[i]->public);
-+ context->target_count++;
-+ }
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_phy_clock_resources(dc, context);
-+
-+ if (!resource_validate_attach_surfaces(
-+ set, set_count, dc->current_context, context)) {
-+ DC_ERROR("Failed to attach surface to target!\n");
-+ return DC_FAIL_ATTACH_SURFACES;
-+ }
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_build_scaling_params_for_context(dc, context);
-+
-+ if (result == DC_OK)
-+ result = dce112_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+enum dc_status dce112_validate_guaranteed(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ context->targets[0] = DC_TARGET_TO_CORE(dc_target);
-+ dc_target_retain(&context->targets[0]->public);
-+ context->target_count++;
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_phy_clock_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK) {
-+ validate_guaranteed_copy_target(
-+ context, dc->public.caps.max_targets);
-+ result = resource_build_scaling_params_for_context(dc, context);
-+ }
-+
-+ if (result == DC_OK)
-+ result = dce112_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+static void dce112_destroy_resource_pool(struct resource_pool **pool)
-+{
-+ struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
-+
-+ destruct(dce110_pool);
-+ dm_free(dce110_pool);
-+ *pool = NULL;
-+}
-+
-+static const struct resource_funcs dce112_res_pool_funcs = {
-+ .destroy = dce112_destroy_resource_pool,
-+ .link_enc_create = dce112_link_encoder_create,
-+ .validate_with_context = dce112_validate_with_context,
-+ .validate_guaranteed = dce112_validate_guaranteed,
-+ .validate_bandwidth = dce112_validate_bandwidth
-+};
-+
-+static void bw_calcs_data_update_from_pplib(struct core_dc *dc)
-+{
-+ struct dm_pp_clock_levels_with_latency eng_clks = {0};
-+ struct dm_pp_clock_levels_with_latency mem_clks = {0};
-+ struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0};
-+ struct dm_pp_clock_levels clks = {0};
-+
-+ /*do system clock TODO PPLIB: after PPLIB implement,
-+ * then remove old way
-+ */
-+ if (!dm_pp_get_clock_levels_by_type_with_latency(
-+ dc->ctx,
-+ DM_PP_CLOCK_TYPE_ENGINE_CLK,
-+ &eng_clks)) {
-+
-+ /* This is only for temporary */
-+ dm_pp_get_clock_levels_by_type(
-+ dc->ctx,
-+ DM_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.mid1_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels/8], 1000);
-+ dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*2/8], 1000);
-+ dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*3/8], 1000);
-+ dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*4/8], 1000);
-+ dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*5/8], 1000);
-+ dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[clks.num_levels*6/8], 1000);
-+ dc->bw_vbios.low_sclk = bw_frc_to_fixed(
-+ clks.clocks_in_khz[0], 1000);
-+
-+ /*do memory clock*/
-+ dm_pp_get_clock_levels_by_type(
-+ dc->ctx,
-+ DM_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);
-+
-+ return;
-+ }
-+
-+ /* convert all the clock fro kHz to fix point mHz TODO: wloop data */
-+ dc->bw_vbios.high_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid1_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
-+ eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000);
-+ dc->bw_vbios.low_sclk = bw_frc_to_fixed(
-+ eng_clks.data[0].clocks_in_khz, 1000);
-+
-+ /*do memory clock*/
-+ dm_pp_get_clock_levels_by_type_with_latency(
-+ dc->ctx,
-+ DM_PP_CLOCK_TYPE_MEMORY_CLK,
-+ &mem_clks);
-+
-+ /* we don't need to call PPLIB for validation clock since they
-+ * also give us the highest sclk and highest mclk (UMA clock).
-+ * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula):
-+ * YCLK = UMACLK*m_memoryTypeMultiplier
-+ */
-+ dc->bw_vbios.low_yclk = bw_frc_to_fixed(
-+ mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000);
-+ dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
-+ mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER,
-+ 1000);
-+ dc->bw_vbios.high_yclk = bw_frc_to_fixed(
-+ mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER,
-+ 1000);
-+
-+ /* Now notify PPLib/SMU about which Watermarks sets they should select
-+ * depending on DPM state they are in. And update BW MGR GFX Engine and
-+ * Memory clock member variables for Watermarks calculations for each
-+ * Watermark Set
-+ */
-+ clk_ranges.num_wm_sets = 4;
-+ clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A;
-+ clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz =
-+ eng_clks.data[0].clocks_in_khz;
-+ clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz =
-+ eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;
-+ clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz =
-+ mem_clks.data[0].clocks_in_khz;
-+ clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz =
-+ mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;
-+
-+ clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B;
-+ clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz =
-+ eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;
-+ /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */
-+ clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000;
-+ clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz =
-+ mem_clks.data[0].clocks_in_khz;
-+ clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz =
-+ mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;
-+
-+ clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C;
-+ clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz =
-+ eng_clks.data[0].clocks_in_khz;
-+ clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz =
-+ eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;
-+ clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz =
-+ mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;
-+ /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */
-+ clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000;
-+
-+ clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D;
-+ clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz =
-+ eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;
-+ /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */
-+ clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000;
-+ clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz =
-+ mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;
-+ /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */
-+ clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000;
-+
-+ /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
-+ dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges);
-+}
-+
-+const struct resource_caps *dce112_resource_cap(
-+ struct hw_asic_id *asic_id)
-+{
-+ if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev))
-+ return &polaris_11_resource_cap;
-+ else
-+ return &polaris_10_resource_cap;
-+}
-+
-+static bool construct(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+ struct dc_context *ctx = dc->ctx;
-+ struct dm_pp_static_clock_info static_clk_info = {0};
-+
-+ ctx->dc_bios->regs = &bios_regs;
-+
-+ pool->base.res_cap = dce112_resource_cap(&ctx->asic_id);
-+ pool->base.funcs = &dce112_res_pool_funcs;
-+
-+ /*************************************************
-+ * Resource + asic cap harcoding *
-+ *************************************************/
-+ pool->base.underlay_pipe_index = -1;
-+ pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
-+ dc->public.caps.max_downscale_ratio = 200;
-+ dc->public.caps.i2c_speed_in_khz = 100;
-+
-+ /*************************************************
-+ * Create resources *
-+ *************************************************/
-+
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL0] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL0,
-+ &clk_src_regs[0], false);
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL1] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL1,
-+ &clk_src_regs[1], false);
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL2] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL2,
-+ &clk_src_regs[2], false);
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL3] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL3,
-+ &clk_src_regs[3], false);
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL4] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL4,
-+ &clk_src_regs[4], false);
-+ pool->base.clock_sources[DCE112_CLK_SRC_PLL5] =
-+ dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_COMBO_PHY_PLL5,
-+ &clk_src_regs[5], false);
-+ pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL;
-+
-+ pool->base.dp_clock_source = dce112_clock_source_create(
-+ ctx, ctx->dc_bios,
-+ CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true);
-+
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] == NULL) {
-+ dm_error("DC: failed to create clock sources!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ pool->base.display_clock = dal_display_clock_dce112_create(
-+ ctx);
-+
-+ if (pool->base.display_clock == NULL) {
-+ dm_error("DC: failed to create display clock!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+
-+ /* get static clock information for PPLIB or firmware, save
-+ * max_clock_state
-+ */
-+ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) {
-+ enum clocks_state max_clocks_state =
-+ dce110_resource_convert_clock_state_pp_to_dc(
-+ static_clk_info.max_clocks_state);
-+
-+ dal_display_clock_store_max_clocks_state(
-+ pool->base.display_clock, max_clocks_state);
-+ }
-+
-+ {
-+ struct irq_service_init_data init_data;
-+ init_data.ctx = dc->ctx;
-+ pool->base.irqs = dal_irq_service_dce110_create(&init_data);
-+ if (!pool->base.irqs)
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ pool->base.timing_generators[i] =
-+ dce112_timing_generator_create(
-+ ctx,
-+ i,
-+ &dce112_tg_offsets[i]);
-+ if (pool->base.timing_generators[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create tg!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.mis[i] = dce112_mem_input_create(
-+ ctx,
-+ i,
-+ &dce112_mi_reg_offsets[i]);
-+ if (pool->base.mis[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create memory input!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.ipps[i] = dce112_ipp_create(
-+ ctx,
-+ i,
-+ &ipp_reg_offsets[i]);
-+ if (pool->base.ipps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC:failed to create input pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.transforms[i] = dce112_transform_create(ctx, i);
-+ if (pool->base.transforms[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC: failed to create transform!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.opps[i] = dce112_opp_create(
-+ ctx,
-+ i,
-+ &dce112_opp_reg_offsets[i]);
-+ if (pool->base.opps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error(
-+ "DC:failed to create output pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ if (!resource_construct(num_virtual_links, dc, &pool->base,
-+ &res_create_funcs))
-+ goto res_create_fail;
-+
-+ /* Create hardware sequencer */
-+ if (!dce112_hw_sequencer_construct(dc))
-+ goto res_create_fail;
-+
-+ bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_POLARIS11);
-+
-+ bw_calcs_data_update_from_pplib(dc);
-+
-+ return true;
-+
-+res_create_fail:
-+ destruct(pool);
-+ return false;
-+}
-+
-+struct resource_pool *dce112_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc)
-+{
-+ struct dce110_resource_pool *pool =
-+ dm_alloc(sizeof(struct dce110_resource_pool));
-+
-+ if (!pool)
-+ return NULL;
-+
-+ if (construct(num_virtual_links, dc, pool))
-+ return &pool->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h
-new file mode 100644
-index 0000000..f21eb57
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.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 __DC_RESOURCE_DCE112_H__
-+#define __DC_RESOURCE_DCE112_H__
-+
-+#include "core_types.h"
-+
-+struct core_dc;
-+struct resource_pool;
-+
-+struct resource_pool *dce112_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc);
-+
-+enum dc_status dce112_validate_with_context(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context);
-+
-+enum dc_status dce112_validate_guaranteed(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context);
-+
-+enum dc_status dce112_validate_bandwidth(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+
-+#endif /* __DC_RESOURCE_DCE112_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
-new file mode 100644
-index 0000000..9979b84
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
-@@ -0,0 +1,16 @@
-+#
-+# Makefile for the 'controller' sub-component of DAL.
-+# It provides the control and status of HW CRTC block.
-+
-+DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \
-+ dce80_opp_formatter.o dce80_opp_regamma.o \
-+ dce80_timing_generator.o dce80_opp_csc.o\
-+ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \
-+ dce80_resource.o
-+
-+AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_DCE80)
-+
-+
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c
-new file mode 100644
-index 0000000..eeedb7c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c
-@@ -0,0 +1,839 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+#include "gmc/gmc_7_1_sh_mask.h"
-+#include "gmc/gmc_7_1_d.h"
-+
-+#include "include/logger_interface.h"
-+#include "dce80_compressor.h"
-+
-+#define DCP_REG(reg)\
-+ (reg + cp80->offsets.dcp_offset)
-+#define DMIF_REG(reg)\
-+ (reg + cp80->offsets.dmif_offset)
-+
-+static const struct dce80_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),
-+},
-+{
-+ .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+ .dmif_offset = (mmDMIF_PG3_DPG_PIPE_DPM_CONTROL
-+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+ .dmif_offset = (mmDMIF_PG4_DPG_PIPE_DPM_CONTROL
-+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+ .dmif_offset = (mmDMIF_PG5_DPG_PIPE_DPM_CONTROL
-+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
-+}
-+};
-+
-+static const uint32_t dce8_one_lpt_channel_max_resolution = 2048 * 1200;
-+
-+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 dce80_compressor *cp80)
-+{
-+ /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
-+ return cp80->base.raw_size * cp80->base.banks_num *
-+ cp80->base.dram_channels_num;
-+}
-+
-+static uint32_t lpt_memory_control_config(struct dce80_compressor *cp80,
-+ uint32_t lpt_control)
-+{
-+ /*LPT MC Config */
-+ if (cp80->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 (cp80->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:
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%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 (cp80->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:
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%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 (cp80->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:
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%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 (cp80->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:
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%s: Invalid LPT ROW_SIZE!!!",
-+ __func__);
-+ break;
-+ }
-+ } else {
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%s: LPT MC Configuration is not provided",
-+ __func__);
-+ }
-+
-+ return lpt_control;
-+}
-+
-+static bool is_source_bigger_than_epanel_size(
-+ struct dce80_compressor *cp80,
-+ uint32_t source_view_width,
-+ uint32_t source_view_height)
-+{
-+ if (cp80->base.embedded_panel_h_size != 0 &&
-+ cp80->base.embedded_panel_v_size != 0 &&
-+ ((source_view_width * source_view_height) >
-+ (cp80->base.embedded_panel_h_size *
-+ cp80->base.embedded_panel_v_size)))
-+ return true;
-+
-+ return false;
-+}
-+
-+static uint32_t align_to_chunks_number_per_line(
-+ struct dce80_compressor *cp80,
-+ uint32_t pixels)
-+{
-+ return 256 * ((pixels + 255) / 256);
-+}
-+
-+static void wait_for_fbc_state_changed(
-+ struct dce80_compressor *cp80,
-+ bool enabled)
-+{
-+ uint8_t counter = 0;
-+ uint32_t addr = mmFBC_STATUS;
-+ uint32_t value;
-+
-+ while (counter < 10) {
-+ value = dm_read_reg(cp80->base.ctx, addr);
-+ if (get_reg_field_value(
-+ value,
-+ FBC_STATUS,
-+ FBC_ENABLE_STATUS) == enabled)
-+ break;
-+ udelay(10);
-+ counter++;
-+ }
-+
-+ if (counter == 10) {
-+ dm_logger_write(
-+ cp80->base.ctx->logger, LOG_WARNING,
-+ "%s: wait counter exceeded, changes to HW not applied",
-+ __func__);
-+ }
-+}
-+
-+void dce80_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);
-+ 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 dce80_compressor_enable_fbc(
-+ struct compressor *compressor,
-+ uint32_t paths_num,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor);
-+
-+ if (compressor->options.bits.FBC_SUPPORT &&
-+ (compressor->options.bits.DUMMY_BACKEND == 0) &&
-+ (!dce80_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
-+ (!is_source_bigger_than_epanel_size(
-+ cp80,
-+ 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 <=
-+ dce8_one_lpt_channel_max_resolution)) {
-+ dce80_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;
-+ cp80->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(cp80, true);
-+ }
-+}
-+
-+void dce80_compressor_disable_fbc(struct compressor *compressor)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor);
-+
-+ if (compressor->options.bits.FBC_SUPPORT &&
-+ dce80_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)
-+ dce80_compressor_disable_lpt(compressor);
-+
-+ wait_for_fbc_state_changed(cp80, false);
-+ }
-+}
-+
-+bool dce80_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_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 dce80_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 dce80_compressor_program_compressed_surface_address_and_pitch(
-+ struct compressor *compressor,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_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(cp80);
-+
-+ 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(
-+ cp80,
-+ params->source_view_width);
-+
-+ if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
-+ fbc_pitch = fbc_pitch / 8;
-+ else
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%s: Unexpected DCE8 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 dce80_compressor_disable_lpt(struct compressor *compressor)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_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 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 dce80_compressor_enable_lpt(struct compressor *compressor)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_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);
-+
-+ /* 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 dce80_compressor_program_lpt_control(
-+ struct compressor *compressor,
-+ struct compr_addr_and_pitch_params *params)
-+{
-+ struct dce80_compressor *cp80 = TO_DCE80_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:
-+ dm_logger_write(
-+ compressor->ctx->logger, LOG_WARNING,
-+ "%s: Invalid selected DRAM channels for LPT!!!",
-+ __func__);
-+ break;
-+ }
-+
-+ lpt_control = lpt_memory_control_config(cp80, 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(cp80);
-+ source_view_width =
-+ align_to_chunks_number_per_line(
-+ cp80,
-+ 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 dce80_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 DCE8:
-+ * - 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, DCE8.1 also needs to set new DCE8.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 dce80_compressor_construct(struct dce80_compressor *compressor,
-+ struct dc_context *ctx)
-+{
-+ struct dc_bios *bp = ctx->dc_bios;
-+ struct embedded_panel_info panel_info;
-+
-+ compressor->base.options.bits.FBC_SUPPORT = true;
-+ compressor->base.options.bits.LPT_SUPPORT = true;
-+ /* For DCE 11 always use one DRAM channel for LPT */
-+ compressor->base.lpt_channels_num = 1;
-+ compressor->base.options.bits.DUMMY_BACKEND = false;
-+
-+ /* 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;
-+
-+ compressor->base.options.bits.CLK_GATING_DISABLED = false;
-+
-+ compressor->base.ctx = ctx;
-+ compressor->base.embedded_panel_h_size = 0;
-+ compressor->base.embedded_panel_v_size = 0;
-+ compressor->base.memory_bus_width = ctx->asic_id.vram_width;
-+ 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 (BP_RESULT_OK ==
-+ bp->funcs->get_embedded_panel_info(bp, &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 *dce80_compressor_create(struct dc_context *ctx)
-+{
-+ struct dce80_compressor *cp80 =
-+ dm_alloc(sizeof(struct dce80_compressor));
-+
-+ if (!cp80)
-+ return NULL;
-+
-+ if (dce80_compressor_construct(cp80, ctx))
-+ return &cp80->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(cp80);
-+ return NULL;
-+}
-+
-+void dce80_compressor_destroy(struct compressor **compressor)
-+{
-+ dm_free(TO_DCE80_COMPRESSOR(*compressor));
-+ *compressor = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h
-new file mode 100644
-index 0000000..0129096
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h
-@@ -0,0 +1,78 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_DCE80_H__
-+#define __DC_COMPRESSOR_DCE80_H__
-+
-+#include "../inc/compressor.h"
-+
-+#define TO_DCE80_COMPRESSOR(compressor)\
-+ container_of(compressor, struct dce80_compressor, base)
-+
-+struct dce80_compressor_reg_offsets {
-+ uint32_t dcp_offset;
-+ uint32_t dmif_offset;
-+};
-+
-+struct dce80_compressor {
-+ struct compressor base;
-+ struct dce80_compressor_reg_offsets offsets;
-+};
-+
-+struct compressor *dce80_compressor_create(struct dc_context *ctx);
-+
-+bool dce80_compressor_construct(struct dce80_compressor *cp80,
-+ struct dc_context *ctx);
-+
-+void dce80_compressor_destroy(struct compressor **cp);
-+
-+/* FBC RELATED */
-+void dce80_compressor_power_up_fbc(struct compressor *cp);
-+
-+void dce80_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num,
-+ struct compr_addr_and_pitch_params *params);
-+
-+void dce80_compressor_disable_fbc(struct compressor *cp);
-+
-+void dce80_compressor_set_fbc_invalidation_triggers(struct compressor *cp,
-+ uint32_t fbc_trigger);
-+
-+void dce80_compressor_program_compressed_surface_address_and_pitch(
-+ struct compressor *cp,
-+ struct compr_addr_and_pitch_params *params);
-+
-+bool dce80_compressor_is_fbc_enabled_in_hw(struct compressor *cp,
-+ uint32_t *fbc_mapped_crtc_id);
-+
-+/* LPT RELATED */
-+void dce80_compressor_enable_lpt(struct compressor *cp);
-+
-+void dce80_compressor_disable_lpt(struct compressor *cp);
-+
-+void dce80_compressor_program_lpt_control(struct compressor *cp,
-+ struct compr_addr_and_pitch_params *params);
-+
-+bool dce80_compressor_is_lpt_enabled_in_hw(struct compressor *cp);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
-new file mode 100644
-index 0000000..c7a2b76
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
-@@ -0,0 +1,141 @@
-+/*
-+ * 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 "dce80_hw_sequencer.h"
-+
-+#include "dce/dce_hwseq.h"
-+#include "dce110/dce110_hw_sequencer.h"
-+
-+/* include DCE8 register header files */
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+struct dce80_hw_seq_reg_offsets {
-+ uint32_t crtc;
-+};
-+
-+static const struct dce80_hw_seq_reg_offsets reg_offsets[] = {
-+{
-+ .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
-+}
-+};
-+
-+#define HW_REG_CRTC(reg, id)\
-+ (reg + reg_offsets[id].crtc)
-+
-+/*******************************************************************************
-+ * Private definitions
-+ ******************************************************************************/
-+
-+/***************************PIPE_CONTROL***********************************/
-+
-+static bool dce80_enable_display_power_gating(
-+ struct core_dc *dc,
-+ 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;
-+ struct dc_context *ctx = dc->ctx;
-+
-+ 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);
-+
-+ /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
-+ * by default when command table is called
-+ */
-+ dm_write_reg(ctx,
-+ HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id),
-+ 0);
-+ }
-+
-+ if (bp_result == BP_RESULT_OK)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+
-+static void set_display_mark_for_pipe_if_needed(struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+static void set_displaymarks(
-+ const struct core_dc *dc, struct validate_context *context)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+static void set_bandwidth(struct core_dc *dc)
-+{
-+ /* Do nothing until we have proper bandwitdth calcs */
-+}
-+
-+
-+bool dce80_hw_sequencer_construct(struct core_dc *dc)
-+{
-+ dce110_hw_sequencer_construct(dc);
-+
-+ dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating;
-+ dc->hwss.pipe_control_lock = dce_pipe_control_lock;
-+ dc->hwss.set_displaymarks = set_displaymarks;
-+ dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed;
-+ dc->hwss.set_bandwidth = set_bandwidth;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h
-new file mode 100644
-index 0000000..7cc203f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_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_DCE80_H__
-+#define __DC_HWSS_DCE80_H__
-+
-+#include "core_types.h"
-+
-+struct core_dc;
-+
-+bool dce80_hw_sequencer_construct(struct core_dc *dc);
-+
-+#endif /* __DC_HWSS_DCE80_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
-new file mode 100644
-index 0000000..86826c2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
-@@ -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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "include/logger_interface.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dce80_ipp.h"
-+
-+#include "dce110/dce110_ipp.h"
-+
-+static const 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,
-+};
-+
-+bool dce80_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 dce80_ipp_destroy(struct input_pixel_processor **ipp)
-+{
-+ dm_free(TO_DCE80_IPP(*ipp));
-+ *ipp = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h
-new file mode 100644
-index 0000000..d350138
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.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 __DC_IPP_DCE80_H__
-+#define __DC_IPP_DCE80_H__
-+
-+#include "ipp.h"
-+
-+#define TO_DCE80_IPP(input_pixel_processor)\
-+ container_of(input_pixel_processor, struct dce110_ipp, base)
-+
-+struct dce110_ipp;
-+struct dce110_ipp_reg_offsets;
-+struct gamma_parameters;
-+struct dev_c_lut;
-+
-+bool dce80_ipp_construct(
-+ struct dce110_ipp *ipp,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_ipp_reg_offsets *offset);
-+
-+void dce80_ipp_destroy(struct input_pixel_processor **ipp);
-+
-+#endif /*__DC_IPP_DCE80_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
-new file mode 100644
-index 0000000..eacb14e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
-@@ -0,0 +1,76 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dce80_ipp.h"
-+#include "dce110/dce110_ipp.h"
-+#include "gamma_types.h"
-+
-+#define DCP_REG(reg)\
-+ (reg + ipp80->offsets.dcp_offset)
-+
-+enum {
-+ MAX_INPUT_LUT_ENTRY = 256
-+};
-+
-+/*PROTOTYPE DECLARATIONS*/
-+
-+static void set_legacy_input_gamma_mode(
-+ struct dce110_ipp *ipp80,
-+ bool is_legacy);
-+
-+void dce80_ipp_set_legacy_input_gamma_mode(
-+ struct input_pixel_processor *ipp,
-+ bool is_legacy)
-+{
-+ struct dce110_ipp *ipp80 = TO_DCE80_IPP(ipp);
-+
-+ set_legacy_input_gamma_mode(ipp80, is_legacy);
-+}
-+
-+static void set_legacy_input_gamma_mode(
-+ struct dce110_ipp *ipp80,
-+ bool is_legacy)
-+{
-+ const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL);
-+ uint32_t value = dm_read_reg(ipp80->base.ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ !is_legacy,
-+ INPUT_GAMMA_CONTROL,
-+ GRPH_INPUT_GAMMA_MODE);
-+
-+ dm_write_reg(ipp80->base.ctx, addr, value);
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c
-new file mode 100644
-index 0000000..ebb8df3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c
-@@ -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
-+ *
-+ */
-+#include "dm_services.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+/* TODO: this needs to be looked at, used by Stella's workaround*/
-+#include "gmc/gmc_7_1_d.h"
-+#include "gmc/gmc_7_1_sh_mask.h"
-+
-+#include "include/logger_interface.h"
-+#include "inc/bandwidth_calcs.h"
-+
-+#include "../dce110/dce110_mem_input.h"
-+#include "dce80_mem_input.h"
-+
-+#define MAX_WATERMARK 0xFFFF
-+#define SAFE_NBP_MARK 0x7FFF
-+
-+#define DCP_REG(reg) (reg + mem_input80->offsets.dcp)
-+#define DMIF_REG(reg) (reg + mem_input80->offsets.dmif)
-+#define PIPE_REG(reg) (reg + mem_input80->offsets.pipe)
-+
-+static struct mem_input_funcs dce80_mem_input_funcs = {
-+ .mem_input_program_display_marks =
-+ dce110_mem_input_program_display_marks,
-+ .allocate_mem_input = dce_mem_input_allocate_dmif,
-+ .free_mem_input = dce_mem_input_free_dmif,
-+ .mem_input_program_surface_flip_and_addr =
-+ dce110_mem_input_program_surface_flip_and_addr,
-+ .mem_input_program_surface_config =
-+ dce_mem_input_program_surface_config,
-+ .mem_input_is_flip_pending =
-+ dce110_mem_input_is_flip_pending,
-+ .mem_input_update_dchub = NULL
-+};
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce80_mem_input_construct(
-+ struct dce110_mem_input *mem_input80,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_mem_input_reg_offsets *offsets)
-+{
-+ /* supported stutter method
-+ * STUTTER_MODE_ENHANCED
-+ * STUTTER_MODE_QUAD_DMIF_BUFFER
-+ */
-+ mem_input80->base.funcs = &dce80_mem_input_funcs;
-+ mem_input80->base.ctx = ctx;
-+
-+ mem_input80->base.inst = inst;
-+
-+ mem_input80->offsets = *offsets;
-+
-+ return true;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h
-new file mode 100644
-index 0000000..357b9e2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.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_MEM_INPUT_DCE80_H__
-+#define __DC_MEM_INPUT_DCE80_H__
-+
-+#include "mem_input.h"
-+
-+bool dce80_mem_input_construct(
-+ struct dce110_mem_input *mem_input80,
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_mem_input_reg_offsets *offsets);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c
-new file mode 100644
-index 0000000..b69e8a5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c
-@@ -0,0 +1,136 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 DCE8 register header files */
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dce80_opp.h"
-+
-+#define FROM_OPP(opp)\
-+ container_of(opp, struct dce80_opp, base)
-+
-+enum {
-+ MAX_LUT_ENTRY = 256,
-+ MAX_NUMBER_OF_ENTRIES = 256
-+};
-+
-+static const struct dce80_opp_reg_offsets reg_offsets[] = {
-+{
-+ .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
-+ .crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL -
-+ mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+}
-+};
-+
-+static const struct opp_funcs funcs = {
-+ .opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut,
-+ .opp_set_csc_adjustment = dce80_opp_set_csc_adjustment,
-+ .opp_set_csc_default = dce80_opp_set_csc_default,
-+ .opp_set_dyn_expansion = dce80_opp_set_dyn_expansion,
-+ .opp_program_regamma_pwl = dce80_opp_program_regamma_pwl,
-+ .opp_set_regamma_mode = dce80_opp_set_regamma_mode,
-+ .opp_destroy = dce80_opp_destroy,
-+ .opp_program_fmt = dce110_opp_program_fmt,
-+};
-+
-+/*****************************************/
-+/* Constructor, Destructor */
-+/*****************************************/
-+
-+bool dce80_opp_construct(struct dce80_opp *opp80,
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ if (inst >= ARRAY_SIZE(reg_offsets))
-+ return false;
-+
-+ opp80->base.funcs = &funcs;
-+
-+ opp80->base.ctx = ctx;
-+
-+ opp80->base.inst = inst;
-+
-+ opp80->offsets = reg_offsets[inst];
-+
-+ return true;
-+}
-+
-+void dce80_opp_destroy(struct output_pixel_processor **opp)
-+{
-+ dm_free(FROM_OPP(*opp));
-+ *opp = NULL;
-+}
-+
-+struct output_pixel_processor *dce80_opp_create(
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ struct dce80_opp *opp =
-+ dm_alloc(sizeof(struct dce80_opp));
-+
-+ if (!opp)
-+ return NULL;
-+
-+ if (dce80_opp_construct(opp,
-+ ctx, inst))
-+ return &opp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(opp);
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h
-new file mode 100644
-index 0000000..965cce3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h
-@@ -0,0 +1,130 @@
-+/* Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_DCE80_H__
-+#define __DC_OPP_DCE80_H__
-+
-+#include "dc_types.h"
-+#include "opp.h"
-+#include "gamma_types.h"
-+#include "../dce110/dce110_opp.h"
-+
-+struct gamma_parameters;
-+
-+struct dce80_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;
-+ 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_DCE80_OPP(opp)\
-+ container_of(opp, struct dce80_opp, base)
-+
-+struct dce80_opp_reg_offsets {
-+ uint32_t fmt_offset;
-+ uint32_t dcp_offset;
-+ uint32_t crtc_offset;
-+};
-+
-+struct dce80_opp {
-+ struct output_pixel_processor base;
-+ struct dce80_opp_reg_offsets offsets;
-+ struct dce80_regamma regamma;
-+};
-+
-+bool dce80_opp_construct(struct dce80_opp *opp80,
-+ struct dc_context *ctx,
-+ uint32_t inst);
-+
-+void dce80_opp_destroy(struct output_pixel_processor **opp);
-+
-+struct output_pixel_processor *dce80_opp_create(
-+ struct dc_context *ctx,
-+ uint32_t inst);
-+
-+/* REGAMMA RELATED */
-+void dce80_opp_power_on_regamma_lut(
-+ struct output_pixel_processor *opp,
-+ bool power_on);
-+
-+bool dce80_opp_program_regamma_pwl(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *pamras);
-+
-+void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp,
-+ enum opp_regamma mode);
-+
-+void dce80_opp_set_csc_adjustment(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry);
-+
-+void dce80_opp_set_csc_default(
-+ struct output_pixel_processor *opp,
-+ const struct default_adjustment *default_adjust);
-+
-+/* FORMATTER RELATED */
-+void dce80_opp_program_bit_depth_reduction(
-+ struct output_pixel_processor *opp,
-+ const struct bit_depth_reduction_params *params);
-+
-+void dce80_opp_program_clamping_and_pixel_encoding(
-+ struct output_pixel_processor *opp,
-+ const struct clamping_and_pixel_encoding_params *params);
-+
-+void dce80_opp_set_dyn_expansion(
-+ struct output_pixel_processor *opp,
-+ enum dc_color_space color_sp,
-+ enum dc_color_depth color_dpth,
-+ enum signal_type signal);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c
-new file mode 100644
-index 0000000..bdb9e0a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c
-@@ -0,0 +1,363 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce80_opp.h"
-+#include "basics/conversion.h"
-+
-+/* include DCE8 register header files */
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#define DCP_REG(reg)\
-+ (reg + opp80->offsets.dcp_offset)
-+
-+enum {
-+ OUTPUT_CSC_MATRIX_SIZE = 12
-+};
-+
-+static const struct out_csc_color_matrix global_color_matrix[] = {
-+{ COLOR_SPACE_SRGB,
-+ { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-+{ COLOR_SPACE_SRGB_LIMITED,
-+ { 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} },
-+/* TODO: correct values below */
-+{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
-+ 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
-+{ COLOR_SPACE_YCBCR709_LIMITED, { 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 dce80_opp *opp80,
-+ const struct out_csc_color_matrix *tbl_entry,
-+ enum grph_color_adjust_option options)
-+{
-+ struct dc_context *ctx = opp80->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);
-+ }
-+}
-+
-+static bool configure_graphics_mode(
-+ struct dce80_opp *opp80,
-+ enum csc_color_mode config,
-+ enum graphics_csc_adjust_type csc_adjust_type,
-+ enum dc_color_space color_space)
-+{
-+ struct dc_context *ctx = opp80->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:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_GRPH_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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:
-+ /* by pass */
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ OUTPUT_CSC_CONTROL,
-+ OUTPUT_CSC_GRPH_MODE);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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_LIMITED:
-+ /* 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 dce80_opp_set_csc_adjustment(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+ enum csc_color_mode config =
-+ CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
-+
-+ program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
-+
-+ /* We did everything ,now program DxOUTPUT_CSC_CONTROL */
-+ configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
-+ tbl_entry->color_space);
-+}
-+
-+void dce80_opp_set_csc_default(
-+ struct output_pixel_processor *opp,
-+ const struct default_adjustment *default_adjust)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_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->out_color_space)
-+ continue;
-+ /* program the matrix with default values from this
-+ * file */
-+ program_color_matrix(opp80, 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(opp80, config,
-+ default_adjust->csc_adjust_type,
-+ default_adjust->out_color_space);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c
-new file mode 100644
-index 0000000..433296a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c
-@@ -0,0 +1,577 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dce80_opp.h"
-+
-+#define FMT_REG(reg)\
-+ (reg + opp80->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 DCE8 power saving reason.
-+ */
-+static void set_truncation(
-+ struct dce80_opp *opp80,
-+ 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(opp80->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(opp80->base.ctx, addr, value);
-+
-+ /* no 10bpc trunc on DCE8*/
-+ 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(opp80->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 dce80_opp *opp80,
-+ const struct bit_depth_reduction_params *params)
-+{
-+ uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
-+ uint32_t depth_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(opp80->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(opp80->base.ctx, addr, depth_cntl_value);
-+
-+ /* no 10bpc on DCE8*/
-+ if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
-+ params->flags.SPATIAL_DITHER_DEPTH == 2)
-+ return;
-+
-+ /*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(opp80->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(opp80->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(opp80->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_FRAME_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(opp80->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 dce80_opp *opp80,
-+ 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(opp80->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(opp80->base.ctx, addr, value);
-+
-+ /* no 10bpc dither on DCE8*/
-+ 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(opp80->base.ctx, addr, 0);
-+ /*Set s matrix*/
-+ addr = FMT_REG(
-+ mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
-+ dm_write_reg(opp80->base.ctx, addr, 0);
-+ /*Set t matrix*/
-+ addr = FMT_REG(
-+ mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
-+ dm_write_reg(opp80->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(opp80->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 dce80_opp *opp80,
-+ 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(opp80->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(opp80->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(opp80->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(opp80->base.ctx, addr, blue_clamp_value);
-+
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ addr = FMT_REG(mmFMT_CLAMP_CNTL);
-+ /*Set clamp control*/
-+ dm_write_reg(opp80->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 dce80_opp *opp80,
-+ 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(opp80->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(opp80->base.ctx, addr, fmt_cntl_value);
-+
-+}
-+
-+void dce80_opp_program_bit_depth_reduction(
-+ struct output_pixel_processor *opp,
-+ const struct bit_depth_reduction_params *params)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+
-+ set_truncation(opp80, params);
-+ set_spatial_dither(opp80, params);
-+ set_temporal_dither(opp80, params);
-+}
-+
-+void dce80_opp_program_clamping_and_pixel_encoding(
-+ struct output_pixel_processor *opp,
-+ const struct clamping_and_pixel_encoding_params *params)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+
-+ set_clamping(opp80, params);
-+ set_pixel_encoding(opp80, params);
-+}
-+
-+void dce80_opp_set_dyn_expansion(
-+ struct output_pixel_processor *opp,
-+ enum dc_color_space color_sp,
-+ enum dc_color_depth color_dpth,
-+ enum signal_type signal)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_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)
-+ 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/display/dc/dce80/dce80_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c
-new file mode 100644
-index 0000000..648e3ef
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c
-@@ -0,0 +1,543 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 DCE8 register header files */
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dce80_opp.h"
-+#include "gamma_types.h"
-+
-+#define DCP_REG(reg)\
-+ (reg + opp80->offsets.dcp_offset)
-+
-+#define DCFE_REG(reg)\
-+ (reg + opp80->offsets.crtc_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;
-+};
-+
-+/*
-+ *****************************************************************************
-+ * 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 dce80_opp *opp80, const struct pwl_params *params)
-+{
-+ const struct gamma_curve *curve;
-+ uint32_t value = 0;
-+
-+ {
-+ set_reg_field_value(
-+ value,
-+ params->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(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
-+ value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[0].custom_float_slope,
-+ REGAMMA_CNTLA_SLOPE_CNTL,
-+ REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
-+
-+ dm_write_reg(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[1].custom_float_x,
-+ REGAMMA_CNTLA_END_CNTL1,
-+ REGAMMA_CNTLA_EXP_REGION_END);
-+
-+ dm_write_reg(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
-+ }
-+ {
-+ value = 0;
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[2].custom_float_slope,
-+ REGAMMA_CNTLA_END_CNTL2,
-+ REGAMMA_CNTLA_EXP_REGION_END_BASE);
-+
-+ set_reg_field_value(
-+ value,
-+ params->arr_points[1].custom_float_y,
-+ REGAMMA_CNTLA_END_CNTL2,
-+ REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
-+
-+ dm_write_reg(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
-+ }
-+
-+ curve = params->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(
-+ opp80->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(opp80->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(opp80->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(opp80->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(opp80->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(opp80->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(opp80->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(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
-+ value);
-+ }
-+}
-+
-+static void program_pwl(
-+ struct dce80_opp *opp80,
-+ const struct pwl_params *params)
-+{
-+ uint32_t value;
-+
-+ {
-+ uint8_t max_tries = 10;
-+ uint8_t counter = 0;
-+
-+ /* Power on LUT memory */
-+ value = dm_read_reg(opp80->base.ctx,
-+ DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ DCFE_MEM_LIGHT_SLEEP_CNTL,
-+ REGAMMA_LUT_LIGHT_SLEEP_DIS);
-+
-+ dm_write_reg(opp80->base.ctx,
-+ DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value);
-+
-+ while (counter < max_tries) {
-+ value =
-+ dm_read_reg(
-+ opp80->base.ctx,
-+ DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
-+
-+ if (get_reg_field_value(
-+ value,
-+ DCFE_MEM_LIGHT_SLEEP_CNTL,
-+ REGAMMA_LUT_MEM_PWR_STATE) == 0)
-+ break;
-+
-+ ++counter;
-+ }
-+
-+ if (counter == max_tries) {
-+ dm_logger_write(opp80->base.ctx->logger, LOG_WARNING,
-+ "%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(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
-+ dm_write_reg(opp80->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;
-+
-+ const struct pwl_result_data *rgb =
-+ params->rgb_resulted;
-+
-+ while (i != params->hw_points_num) {
-+ dm_write_reg(opp80->base.ctx, addr, rgb->red_reg);
-+ dm_write_reg(opp80->base.ctx, addr, rgb->green_reg);
-+ dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg);
-+
-+ dm_write_reg(opp80->base.ctx, addr,
-+ rgb->delta_red_reg);
-+ dm_write_reg(opp80->base.ctx, addr,
-+ rgb->delta_green_reg);
-+ dm_write_reg(opp80->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(opp80->base.ctx,
-+ DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ DCFE_MEM_LIGHT_SLEEP_CNTL,
-+ REGAMMA_LUT_LIGHT_SLEEP_DIS);
-+
-+ dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL),
-+ value);
-+}
-+
-+void dce80_opp_power_on_regamma_lut(
-+ struct output_pixel_processor *opp,
-+ bool power_on)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+
-+ uint32_t value =
-+ dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
-+
-+ set_reg_field_value(
-+ value,
-+ power_on,
-+ DCFE_MEM_LIGHT_SLEEP_CNTL,
-+ REGAMMA_LUT_LIGHT_SLEEP_DIS);
-+
-+ set_reg_field_value(
-+ value,
-+ power_on,
-+ DCFE_MEM_LIGHT_SLEEP_CNTL,
-+ DCP_LUT_LIGHT_SLEEP_DIS);
-+
-+ dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value);
-+}
-+
-+bool dce80_opp_program_regamma_pwl(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params)
-+{
-+
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+
-+ regamma_config_regions_and_segments(opp80, params);
-+
-+ program_pwl(opp80, params);
-+
-+ return true;
-+}
-+
-+void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp,
-+ enum opp_regamma mode)
-+{
-+ struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
-+ uint32_t value = dm_read_reg(opp80->base.ctx,
-+ DCP_REG(mmREGAMMA_CONTROL));
-+
-+ set_reg_field_value(
-+ value,
-+ mode,
-+ REGAMMA_CONTROL,
-+ GRPH_REGAMMA_MODE);
-+
-+ dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
-new file mode 100644
-index 0000000..0672040
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
-@@ -0,0 +1,1063 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dm_services.h"
-+
-+#include "link_encoder.h"
-+#include "stream_encoder.h"
-+
-+#include "resource.h"
-+#include "include/irq_service_interface.h"
-+#include "irq/dce80/irq_service_dce80.h"
-+#include "dce110/dce110_timing_generator.h"
-+#include "dce110/dce110_mem_input.h"
-+#include "dce110/dce110_resource.h"
-+#include "dce80/dce80_timing_generator.h"
-+#include "dce/dce_link_encoder.h"
-+#include "dce/dce_stream_encoder.h"
-+#include "dce80/dce80_mem_input.h"
-+#include "dce80/dce80_ipp.h"
-+#include "dce/dce_transform.h"
-+#include "dce80/dce80_opp.h"
-+#include "dce110/dce110_ipp.h"
-+#include "dce/dce_clock_source.h"
-+#include "dce/dce_audio.h"
-+#include "dce/dce_hwseq.h"
-+#include "dce80/dce80_hw_sequencer.h"
-+
-+#include "reg_helper.h"
-+
-+/* TODO remove this include */
-+
-+#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
-+#include "gmc/gmc_7_1_d.h"
-+#include "gmc/gmc_7_1_sh_mask.h"
-+#endif
-+
-+#ifndef mmDP_DPHY_INTERNAL_CTRL
-+#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE
-+#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE
-+#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE
-+#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE
-+#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE
-+#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE
-+#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE
-+#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE
-+#endif
-+
-+
-+#ifndef mmBIOS_SCRATCH_2
-+ #define mmBIOS_SCRATCH_2 0x05CB
-+ #define mmBIOS_SCRATCH_6 0x05CF
-+#endif
-+
-+#ifndef mmDP_DPHY_FAST_TRAINING
-+ #define mmDP_DPHY_FAST_TRAINING 0x1CCE
-+ #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE
-+ #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE
-+ #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE
-+ #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE
-+ #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE
-+ #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE
-+ #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE
-+#endif
-+
-+
-+#ifndef mmHPD_DC_HPD_CONTROL
-+ #define mmHPD_DC_HPD_CONTROL 0x189A
-+ #define mmHPD0_DC_HPD_CONTROL 0x189A
-+ #define mmHPD1_DC_HPD_CONTROL 0x18A2
-+ #define mmHPD2_DC_HPD_CONTROL 0x18AA
-+ #define mmHPD3_DC_HPD_CONTROL 0x18B2
-+ #define mmHPD4_DC_HPD_CONTROL 0x18BA
-+ #define mmHPD5_DC_HPD_CONTROL 0x18C2
-+#endif
-+
-+#define DCE11_DIG_FE_CNTL 0x4a00
-+#define DCE11_DIG_BE_CNTL 0x4a47
-+#define DCE11_DP_SEC 0x4ac3
-+
-+static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = {
-+ {
-+ .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ },
-+ {
-+ .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ },
-+ {
-+ .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ },
-+ {
-+ .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ },
-+ {
-+ .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ },
-+ {
-+ .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
-+ .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
-+ .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
-+ - mmDPG_WATERMARK_MASK_CONTROL),
-+ }
-+};
-+
-+static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = {
-+ {
-+ .dcp = (mmGRPH_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_ipp_reg_offsets ipp_reg_offsets[] = {
-+{
-+ .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+},
-+{
-+ .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL),
-+}
-+};
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define transform_regs(id)\
-+[id] = {\
-+ XFM_COMMON_REG_LIST_DCE_BASE(id)\
-+}
-+
-+static const struct dce_transform_registers xfm_regs[] = {
-+ transform_regs(0),
-+ transform_regs(1),
-+ transform_regs(2),
-+ transform_regs(3),
-+ transform_regs(4),
-+ transform_regs(5)
-+};
-+
-+static const struct dce_transform_shift xfm_shift = {
-+ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
-+};
-+
-+static const struct dce_transform_mask xfm_mask = {
-+ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
-+};
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_REG_LIST(id)\
-+}
-+
-+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 hpd_regs(id)\
-+[id] = {\
-+ HPD_REG_LIST(id)\
-+}
-+
-+static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
-+ hpd_regs(0),
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5)
-+};
-+
-+#define link_regs(id)\
-+[id] = {\
-+ LE_DCE80_REG_LIST(id)\
-+}
-+
-+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] = {\
-+ SE_COMMON_REG_LIST_DCE_BASE(id),\
-+ .AFMT_CNTL = 0,\
-+}
-+
-+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)
-+};
-+
-+static const struct dce_stream_encoder_shift se_shift = {
-+ SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT)
-+};
-+
-+static const struct dce_stream_encoder_mask se_mask = {
-+ SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK)
-+};
-+
-+#define audio_regs(id)\
-+[id] = {\
-+ AUD_COMMON_REG_LIST(id)\
-+}
-+
-+static const struct dce_audio_registers audio_regs[] = {
-+ audio_regs(0),
-+ audio_regs(1),
-+ audio_regs(2),
-+ audio_regs(3),
-+ audio_regs(4),
-+ audio_regs(5),
-+ audio_regs(6),
-+};
-+
-+static const struct dce_audio_shift audio_shift = {
-+ AUD_COMMON_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_aduio_mask audio_mask = {
-+ AUD_COMMON_MASK_SH_LIST(_MASK)
-+};
-+
-+#define clk_src_regs(id)\
-+[id] = {\
-+ CS_COMMON_REG_LIST_DCE_80(id),\
-+}
-+
-+
-+static const struct dce110_clk_src_regs clk_src_regs[] = {
-+ clk_src_regs(0),
-+ clk_src_regs(1),
-+ clk_src_regs(2)
-+};
-+
-+static const struct dce110_clk_src_shift cs_shift = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
-+};
-+
-+static const struct dce110_clk_src_mask cs_mask = {
-+ CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
-+};
-+
-+static const struct bios_registers bios_regs = {
-+ .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
-+};
-+
-+static const struct resource_caps res_cap = {
-+ .num_timing_generator = 6,
-+ .num_audio = 6,
-+ .num_stream_encoder = 6,
-+ .num_pll = 3,
-+};
-+
-+#define CTX ctx
-+#define REG(reg) mm ## reg
-+
-+#ifndef mmCC_DC_HDMI_STRAPS
-+#define mmCC_DC_HDMI_STRAPS 0x1918
-+#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 void read_dce_straps(
-+ struct dc_context *ctx,
-+ struct resource_straps *straps)
-+{
-+ REG_GET_2(CC_DC_HDMI_STRAPS,
-+ HDMI_DISABLE, &straps->hdmi_disable,
-+ AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
-+
-+ REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
-+}
-+
-+static struct audio *create_audio(
-+ struct dc_context *ctx, unsigned int inst)
-+{
-+ return dce_audio_create(ctx, inst,
-+ &audio_regs[inst], &audio_shift, &audio_mask);
-+}
-+
-+static struct timing_generator *dce80_timing_generator_create(
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ struct dce110_timing_generator *tg110 =
-+ dm_alloc(sizeof(struct dce110_timing_generator));
-+
-+ if (!tg110)
-+ return NULL;
-+
-+ if (dce80_timing_generator_construct(tg110, ctx, instance, offsets))
-+ return &tg110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(tg110);
-+ return NULL;
-+}
-+
-+static struct stream_encoder *dce80_stream_encoder_create(
-+ enum engine_id eng_id,
-+ struct dc_context *ctx)
-+{
-+ struct dce110_stream_encoder *enc110 =
-+ dm_alloc(sizeof(struct dce110_stream_encoder));
-+
-+ if (!enc110)
-+ return NULL;
-+
-+ if (dce110_stream_encoder_construct(
-+ enc110, ctx, ctx->dc_bios, eng_id,
-+ &stream_enc_regs[eng_id], &se_shift, &se_mask))
-+ return &enc110->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+#define SRII(reg_name, block, id)\
-+ .reg_name[id] = mm ## block ## id ## _ ## reg_name
-+
-+static const struct dce_hwseq_registers hwseq_reg = {
-+ HWSEQ_DCE8_REG_LIST()
-+};
-+
-+static const struct dce_hwseq_shift hwseq_shift = {
-+ HWSEQ_DCE8_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct dce_hwseq_mask hwseq_mask = {
-+ HWSEQ_DCE8_MASK_SH_LIST(_MASK)
-+};
-+
-+static struct dce_hwseq *dce80_hwseq_create(
-+ struct dc_context *ctx)
-+{
-+ struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
-+
-+ if (hws) {
-+ hws->ctx = ctx;
-+ hws->regs = &hwseq_reg;
-+ hws->shifts = &hwseq_shift;
-+ hws->masks = &hwseq_mask;
-+ }
-+ return hws;
-+}
-+
-+static const struct resource_create_funcs res_create_funcs = {
-+ .read_dce_straps = read_dce_straps,
-+ .create_audio = create_audio,
-+ .create_stream_encoder = dce80_stream_encoder_create,
-+ .create_hwseq = dce80_hwseq_create,
-+};
-+
-+#define mi_inst_regs(id) { \
-+ MI_REG_LIST(id), \
-+ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
-+}
-+static const struct dce_mem_input_registers mi_regs[] = {
-+ mi_inst_regs(0),
-+ mi_inst_regs(1),
-+ mi_inst_regs(2),
-+ mi_inst_regs(3),
-+ mi_inst_regs(4),
-+ mi_inst_regs(5),
-+};
-+
-+static const struct dce_mem_input_shift mi_shifts = {
-+ MI_DCE_MASK_SH_LIST(__SHIFT),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
-+};
-+
-+static const struct dce_mem_input_mask mi_masks = {
-+ MI_DCE_MASK_SH_LIST(_MASK),
-+ .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
-+};
-+
-+static struct mem_input *dce80_mem_input_create(
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_mem_input_reg_offsets *offsets)
-+{
-+ struct dce110_mem_input *mem_input80 =
-+ dm_alloc(sizeof(struct dce110_mem_input));
-+
-+ if (!mem_input80)
-+ return NULL;
-+
-+ if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) {
-+ struct mem_input *mi = &mem_input80->base;
-+
-+ mi->regs = &mi_regs[inst];
-+ mi->shifts = &mi_shifts;
-+ mi->masks = &mi_masks;
-+ mi->wa.single_head_rdreq_dmif_limit = 2;
-+ return mi;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(mem_input80);
-+ return NULL;
-+}
-+
-+static void dce80_transform_destroy(struct transform **xfm)
-+{
-+ dm_free(TO_DCE_TRANSFORM(*xfm));
-+ *xfm = NULL;
-+}
-+
-+static struct transform *dce80_transform_create(
-+ struct dc_context *ctx,
-+ uint32_t inst)
-+{
-+ struct dce_transform *transform =
-+ dm_alloc(sizeof(struct dce_transform));
-+
-+ if (!transform)
-+ return NULL;
-+
-+ if (dce_transform_construct(transform, ctx, inst,
-+ &xfm_regs[inst], &xfm_shift, &xfm_mask)) {
-+ transform->prescaler_on = false;
-+ return &transform->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(transform);
-+ return NULL;
-+}
-+
-+static struct input_pixel_processor *dce80_ipp_create(
-+ struct dc_context *ctx,
-+ uint32_t inst,
-+ const struct dce110_ipp_reg_offsets *offset)
-+{
-+ struct dce110_ipp *ipp =
-+ dm_alloc(sizeof(struct dce110_ipp));
-+
-+ if (!ipp)
-+ return NULL;
-+
-+ if (dce80_ipp_construct(ipp, ctx, inst, offset))
-+ return &ipp->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(ipp);
-+ return NULL;
-+}
-+
-+struct link_encoder *dce80_link_encoder_create(
-+ const struct encoder_init_data *enc_init_data)
-+{
-+ struct dce110_link_encoder *enc110 =
-+ dm_alloc(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_hpd_regs[enc_init_data->hpd_source])) {
-+
-+ enc110->base.features.ycbcr420_supported = false;
-+ enc110->base.features.max_hdmi_pixel_clock = 297000;
-+ return &enc110->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc110);
-+ return NULL;
-+}
-+
-+struct clock_source *dce80_clock_source_create(
-+ struct dc_context *ctx,
-+ struct dc_bios *bios,
-+ enum clock_source_id id,
-+ const struct dce110_clk_src_regs *regs,
-+ bool dp_clk_src)
-+{
-+ struct dce110_clk_src *clk_src =
-+ dm_alloc(sizeof(struct dce110_clk_src));
-+
-+ if (!clk_src)
-+ return NULL;
-+
-+ if (dce110_clk_src_construct(clk_src, ctx, bios, id,
-+ regs, &cs_shift, &cs_mask)) {
-+ clk_src->base.dp_clk_src = dp_clk_src;
-+ return &clk_src->base;
-+ }
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-+void dce80_clock_source_destroy(struct clock_source **clk_src)
-+{
-+ dm_free(TO_DCE110_CLK_SRC(*clk_src));
-+ *clk_src = NULL;
-+}
-+
-+static void destruct(struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ if (pool->base.opps[i] != NULL)
-+ dce80_opp_destroy(&pool->base.opps[i]);
-+
-+ if (pool->base.transforms[i] != NULL)
-+ dce80_transform_destroy(&pool->base.transforms[i]);
-+
-+ if (pool->base.ipps[i] != NULL)
-+ dce80_ipp_destroy(&pool->base.ipps[i]);
-+
-+ if (pool->base.mis[i] != NULL) {
-+ dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
-+ pool->base.mis[i] = NULL;
-+ }
-+
-+ if (pool->base.timing_generators[i] != NULL) {
-+ dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
-+ pool->base.timing_generators[i] = NULL;
-+ }
-+ }
-+
-+ for (i = 0; i < pool->base.stream_enc_count; i++) {
-+ if (pool->base.stream_enc[i] != NULL)
-+ dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] != NULL) {
-+ dce80_clock_source_destroy(&pool->base.clock_sources[i]);
-+ }
-+ }
-+
-+ if (pool->base.dp_clock_source != NULL)
-+ dce80_clock_source_destroy(&pool->base.dp_clock_source);
-+
-+ for (i = 0; i < pool->base.audio_count; i++) {
-+ if (pool->base.audios[i] != NULL) {
-+ dce_aud_destroy(&pool->base.audios[i]);
-+ }
-+ }
-+
-+ if (pool->base.display_clock != NULL) {
-+ dal_display_clock_destroy(&pool->base.display_clock);
-+ }
-+
-+ if (pool->base.irqs != NULL) {
-+ dal_irq_service_destroy(&pool->base.irqs);
-+ }
-+}
-+
-+static enum dc_status validate_mapped_resource(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ enum dc_status status = DC_OK;
-+ uint8_t i, j, k;
-+
-+ 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 core_link *link = stream->sink->link;
-+
-+ if (resource_is_stream_unchanged(dc->current_context, stream))
-+ continue;
-+
-+ for (k = 0; k < MAX_PIPES; k++) {
-+ struct pipe_ctx *pipe_ctx =
-+ &context->res_ctx.pipe_ctx[k];
-+
-+ if (context->res_ctx.pipe_ctx[k].stream != stream)
-+ continue;
-+
-+ if (!pipe_ctx->tg->funcs->validate_timing(
-+ pipe_ctx->tg, &stream->public.timing))
-+ return DC_FAIL_CONTROLLER_VALIDATE;
-+
-+ status = dce110_resource_build_pipe_hw_param(pipe_ctx);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ if (!link->link_enc->funcs->validate_output_with_stream(
-+ link->link_enc,
-+ pipe_ctx))
-+ return DC_FAIL_ENC_VALIDATE;
-+
-+ /* TODO: validate audio ASIC caps, encoder */
-+
-+ status = dc_link_validate_mode_timing(stream,
-+ link,
-+ &stream->public.timing);
-+
-+ if (status != DC_OK)
-+ return status;
-+
-+ resource_build_info_frame(pipe_ctx);
-+
-+ /* do not need to validate non root pipes */
-+ break;
-+ }
-+ }
-+ }
-+
-+ return DC_OK;
-+}
-+
-+enum dc_status dce80_validate_bandwidth(
-+ const struct core_dc *dc,
-+ struct validate_context *context)
-+{
-+ /* TODO implement when needed but for now hardcode max value*/
-+ context->bw_results.dispclk_khz = 681000;
-+ context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER;
-+
-+ return DC_OK;
-+}
-+
-+static bool dce80_validate_surface_sets(
-+ const struct dc_validation_set set[],
-+ int set_count)
-+{
-+ int i;
-+
-+ for (i = 0; i < set_count; i++) {
-+ if (set[i].surface_count == 0)
-+ continue;
-+
-+ if (set[i].surface_count > 1)
-+ return false;
-+
-+ if (set[i].surfaces[0]->clip_rect.width
-+ != set[i].target->streams[0]->src.width
-+ || set[i].surfaces[0]->clip_rect.height
-+ != set[i].target->streams[0]->src.height)
-+ return false;
-+ if (set[i].surfaces[0]->format
-+ >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+enum dc_status dce80_validate_with_context(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context)
-+{
-+ struct dc_context *dc_ctx = dc->ctx;
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+ int i;
-+
-+ if (!dce80_validate_surface_sets(set, set_count))
-+ return DC_FAIL_SURFACE_VALIDATE;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ for (i = 0; i < set_count; i++) {
-+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
-+ dc_target_retain(&context->targets[i]->public);
-+ context->target_count++;
-+ }
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (!resource_validate_attach_surfaces(
-+ set, set_count, dc->current_context, context)) {
-+ DC_ERROR("Failed to attach surface to target!\n");
-+ return DC_FAIL_ATTACH_SURFACES;
-+ }
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_build_scaling_params_for_context(dc, context);
-+
-+ if (result == DC_OK)
-+ result = dce80_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+enum dc_status dce80_validate_guaranteed(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context)
-+{
-+ enum dc_status result = DC_ERROR_UNEXPECTED;
-+
-+ context->res_ctx.pool = dc->res_pool;
-+
-+ context->targets[0] = DC_TARGET_TO_CORE(dc_target);
-+ dc_target_retain(&context->targets[0]->public);
-+ context->target_count++;
-+
-+ result = resource_map_pool_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = resource_map_clock_resources(dc, context);
-+
-+ if (result == DC_OK)
-+ result = validate_mapped_resource(dc, context);
-+
-+ if (result == DC_OK) {
-+ validate_guaranteed_copy_target(
-+ context, dc->public.caps.max_targets);
-+ result = resource_build_scaling_params_for_context(dc, context);
-+ }
-+
-+ if (result == DC_OK)
-+ result = dce80_validate_bandwidth(dc, context);
-+
-+ return result;
-+}
-+
-+static void dce80_destroy_resource_pool(struct resource_pool **pool)
-+{
-+ struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
-+
-+ destruct(dce110_pool);
-+ dm_free(dce110_pool);
-+ *pool = NULL;
-+}
-+
-+static const struct resource_funcs dce80_res_pool_funcs = {
-+ .destroy = dce80_destroy_resource_pool,
-+ .link_enc_create = dce80_link_encoder_create,
-+ .validate_with_context = dce80_validate_with_context,
-+ .validate_guaranteed = dce80_validate_guaranteed,
-+ .validate_bandwidth = dce80_validate_bandwidth
-+};
-+
-+static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc(
-+ enum dm_pp_clocks_state pp_clock_state)
-+{
-+ enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID;
-+
-+ switch (pp_clock_state) {
-+ case DM_PP_CLOCKS_STATE_INVALID:
-+ dc_clocks_state = CLOCKS_STATE_INVALID;
-+ break;
-+ case DM_PP_CLOCKS_STATE_ULTRA_LOW:
-+ dc_clocks_state = CLOCKS_STATE_ULTRA_LOW;
-+ break;
-+ case DM_PP_CLOCKS_STATE_LOW:
-+ dc_clocks_state = CLOCKS_STATE_LOW;
-+ break;
-+ case DM_PP_CLOCKS_STATE_NOMINAL:
-+ dc_clocks_state = CLOCKS_STATE_NOMINAL;
-+ break;
-+ case DM_PP_CLOCKS_STATE_PERFORMANCE:
-+ dc_clocks_state = CLOCKS_STATE_PERFORMANCE;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_4:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_5:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_6:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6;
-+ break;
-+ case DM_PP_CLOCKS_DPM_STATE_LEVEL_7:
-+ dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7;
-+ break;
-+ default:
-+ dc_clocks_state = CLOCKS_STATE_INVALID;
-+ break;
-+ }
-+
-+ return dc_clocks_state;
-+}
-+
-+static bool construct(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc,
-+ struct dce110_resource_pool *pool)
-+{
-+ unsigned int i;
-+ struct dc_context *ctx = dc->ctx;
-+ struct firmware_info info;
-+ struct dc_bios *bp;
-+ struct dm_pp_static_clock_info static_clk_info = {0};
-+
-+ ctx->dc_bios->regs = &bios_regs;
-+
-+ pool->base.res_cap = &res_cap;
-+ pool->base.funcs = &dce80_res_pool_funcs;
-+
-+
-+ /*************************************************
-+ * Resource + asic cap harcoding *
-+ *************************************************/
-+ pool->base.underlay_pipe_index = -1;
-+ pool->base.pipe_count = res_cap.num_timing_generator;
-+ dc->public.caps.max_downscale_ratio = 200;
-+ dc->public.caps.i2c_speed_in_khz = 40;
-+
-+ /*************************************************
-+ * Create resources *
-+ *************************************************/
-+
-+ bp = ctx->dc_bios;
-+
-+ if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
-+ info.external_clock_source_frequency_for_dp != 0) {
-+ pool->base.dp_clock_source =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
-+
-+ pool->base.clock_sources[0] =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
-+ pool->base.clock_sources[1] =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
-+ pool->base.clock_sources[2] =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
-+ pool->base.clk_src_count = 3;
-+
-+ } else {
-+ pool->base.dp_clock_source =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
-+
-+ pool->base.clock_sources[0] =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
-+ pool->base.clock_sources[1] =
-+ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
-+ pool->base.clk_src_count = 2;
-+ }
-+
-+ if (pool->base.dp_clock_source == NULL) {
-+ dm_error("DC: failed to create dp clock source!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.clk_src_count; i++) {
-+ if (pool->base.clock_sources[i] == NULL) {
-+ dm_error("DC: failed to create clock sources!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ pool->base.display_clock = dal_display_clock_dce80_create(ctx);
-+ if (pool->base.display_clock == NULL) {
-+ dm_error("DC: failed to create display clock!\n");
-+ BREAK_TO_DEBUGGER();
-+ goto res_create_fail;
-+ }
-+
-+
-+ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) {
-+ enum clocks_state max_clocks_state =
-+ dce80_resource_convert_clock_state_pp_to_dc(
-+ static_clk_info.max_clocks_state);
-+
-+ dal_display_clock_store_max_clocks_state(
-+ pool->base.display_clock, max_clocks_state);
-+ }
-+
-+ {
-+ struct irq_service_init_data init_data;
-+ init_data.ctx = dc->ctx;
-+ pool->base.irqs = dal_irq_service_dce80_create(&init_data);
-+ if (!pool->base.irqs)
-+ goto res_create_fail;
-+ }
-+
-+ for (i = 0; i < pool->base.pipe_count; i++) {
-+ pool->base.timing_generators[i] = dce80_timing_generator_create(
-+ ctx, i, &dce80_tg_offsets[i]);
-+ if (pool->base.timing_generators[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create tg!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.mis[i] = dce80_mem_input_create(ctx, i,
-+ &dce80_mi_reg_offsets[i]);
-+ if (pool->base.mis[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create memory input!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]);
-+ if (pool->base.ipps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create input pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.transforms[i] = dce80_transform_create(ctx, i);
-+ if (pool->base.transforms[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create transform!\n");
-+ goto res_create_fail;
-+ }
-+
-+ pool->base.opps[i] = dce80_opp_create(ctx, i);
-+ if (pool->base.opps[i] == NULL) {
-+ BREAK_TO_DEBUGGER();
-+ dm_error("DC: failed to create output pixel processor!\n");
-+ goto res_create_fail;
-+ }
-+ }
-+
-+ if (!resource_construct(num_virtual_links, dc, &pool->base,
-+ &res_create_funcs))
-+ goto res_create_fail;
-+
-+ /* Create hardware sequencer */
-+ if (!dce80_hw_sequencer_construct(dc))
-+ goto res_create_fail;
-+
-+ return true;
-+
-+res_create_fail:
-+ destruct(pool);
-+ return false;
-+}
-+
-+struct resource_pool *dce80_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc)
-+{
-+ struct dce110_resource_pool *pool =
-+ dm_alloc(sizeof(struct dce110_resource_pool));
-+
-+ if (!pool)
-+ return NULL;
-+
-+ if (construct(num_virtual_links, dc, pool))
-+ return &pool->base;
-+
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h
-new file mode 100644
-index 0000000..2a0cdcc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.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_RESOURCE_DCE80_H__
-+#define __DC_RESOURCE_DCE80_H__
-+
-+#include "core_types.h"
-+
-+struct core_dc;
-+struct resource_pool;
-+
-+struct resource_pool *dce80_create_resource_pool(
-+ uint8_t num_virtual_links,
-+ struct core_dc *dc);
-+
-+#endif /* __DC_RESOURCE_DCE80_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
-new file mode 100644
-index 0000000..e8fae0a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
-@@ -0,0 +1,241 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 DCE8 register header files */
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "dc_types.h"
-+
-+#include "include/grph_object_id.h"
-+#include "include/logger_interface.h"
-+#include "../dce110/dce110_timing_generator.h"
-+#include "dce80_timing_generator.h"
-+
-+#include "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
-+};
-+
-+static const struct dce110_timing_generator_offsets reg_offsets[] = {
-+{
-+ .crtc = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+},
-+{
-+ .crtc = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
-+ .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
-+}
-+};
-+
-+#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)
-+#define DMIF_REG(reg) (reg + tg110->offsets.dmif)
-+
-+void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_khz)
-+{
-+ uint64_t pix_dur;
-+ uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1
-+ + DCE110TG_FROM_TG(tg)->offsets.dmif;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ if (pix_clk_khz == 0)
-+ return;
-+
-+ pix_dur = 1000000000 / pix_clk_khz;
-+
-+ set_reg_field_value(
-+ value,
-+ pix_dur,
-+ DPG_PIPE_ARBITRATION_CONTROL1,
-+ PIXEL_DURATION);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static void program_timing(struct timing_generator *tg,
-+ const struct dc_crtc_timing *timing,
-+ bool use_vbios)
-+{
-+ if (!use_vbios)
-+ program_pix_dur(tg, timing->pix_clk_khz);
-+
-+ dce110_tg_program_timing(tg, timing, use_vbios);
-+}
-+
-+static const struct timing_generator_funcs dce80_tg_funcs = {
-+ .validate_timing = dce110_tg_validate_timing,
-+ .program_timing = 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,
-+ .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
-+ .set_early_control = dce110_timing_generator_set_early_control,
-+ .wait_for_state = dce110_tg_wait_for_state,
-+ .set_blank = dce110_tg_set_blank,
-+ .is_blanked = dce110_tg_is_blanked,
-+ .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,
-+
-+ /* DCE8.0 overrides */
-+ .enable_advanced_request =
-+ dce80_timing_generator_enable_advanced_request,
-+ .set_drr =
-+ dce110_timing_generator_set_drr,
-+};
-+
-+bool dce80_timing_generator_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets)
-+{
-+ if (!tg110)
-+ return false;
-+
-+ tg110->controller_id = CONTROLLER_ID_D0 + instance;
-+ tg110->base.inst = instance;
-+ tg110->offsets = *offsets;
-+ tg110->derived_offsets = reg_offsets[instance];
-+
-+ tg110->base.funcs = &dce80_tg_funcs;
-+
-+ tg110->base.ctx = ctx;
-+ tg110->base.bp = ctx->dc_bios;
-+
-+ 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;
-+}
-+
-+void dce80_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) {
-+ 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);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h
-new file mode 100644
-index 0000000..6e4722a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.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 __DC_TIMING_GENERATOR_DCE80_H__
-+#define __DC_TIMING_GENERATOR_DCE80_H__
-+
-+#include "timing_generator.h"
-+#include "../include/grph_object_id.h"
-+
-+/* DCE8.0 implementation inherits from DCE11.0 */
-+bool dce80_timing_generator_construct(
-+ struct dce110_timing_generator *tg,
-+ struct dc_context *ctx,
-+ uint32_t instance,
-+ const struct dce110_timing_generator_offsets *offsets);
-+
-+/******** HW programming ************/
-+void dce80_timing_generator_enable_advanced_request(
-+ struct timing_generator *tg,
-+ bool enable,
-+ const struct dc_crtc_timing *timing);
-+
-+#endif /* __DC_TIMING_GENERATOR_DCE80_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
-new file mode 100644
-index 0000000..d6c52d3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
-@@ -0,0 +1,101 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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);
-+
-+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/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
-new file mode 100644
-index 0000000..7a3f103
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
-@@ -0,0 +1,424 @@
-+/*
-+ * 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 "link_service_types.h"
-+
-+#undef DEPRECATED
-+
-+/*
-+ *
-+ * 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_DC)
-+#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 */
-+
-+#define DC_ERR(...) do { \
-+ dm_error(__VA_ARGS__); \
-+ BREAK_TO_DEBUGGER(); \
-+} while (0)
-+
-+#define dm_alloc(size) kzalloc(size, GFP_KERNEL)
-+#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL)
-+#define dm_free(ptr) kfree(ptr)
-+
-+irq_handler_idx dm_register_interrupt(
-+ struct dc_context *ctx,
-+ struct dc_interrupt_params *int_params,
-+ interrupt_handler ih,
-+ void *handler_args);
-+
-+
-+/*
-+ *
-+ * 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;
-+
-+ if (address == 0) {
-+ DC_ERR("invalid register read. address = 0");
-+ return 0;
-+ }
-+
-+ 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
-+
-+ if (address == 0) {
-+ DC_ERR("invalid register write. address = 0");
-+ return;
-+ }
-+ 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)
-+
-+uint32_t generic_reg_update_ex(const struct dc_context *ctx,
-+ uint32_t addr, uint32_t reg_val, int n,
-+ uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...);
-+
-+#define FD(reg_field) reg_field ## __SHIFT, \
-+ reg_field ## _MASK
-+
-+/*
-+ * return number of poll before condition is met
-+ * return 0 if condition is not meet after specified time out tries
-+ */
-+unsigned int generic_reg_wait(const struct dc_context *ctx,
-+ uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value,
-+ unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
-+ const char *func_name);
-+
-+/**************************************
-+ * Power Play (PP) interfaces
-+ **************************************/
-+
-+/* 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 dm_pp_gpu_clock_range *requested_state,
-+ struct dm_pp_gpu_clock_range *actual_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 dm_pp_gpu_clock_range *sys_clks);
-+
-+/* 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 dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels *clk_level_info);
-+
-+bool dm_pp_get_clock_levels_by_type_with_latency(
-+ const struct dc_context *ctx,
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels_with_latency *clk_level_info);
-+
-+bool dm_pp_get_clock_levels_by_type_with_voltage(
-+ const struct dc_context *ctx,
-+ enum dm_pp_clock_type clk_type,
-+ struct dm_pp_clock_levels_with_voltage *clk_level_info);
-+
-+bool dm_pp_notify_wm_clock_changes(
-+ const struct dc_context *ctx,
-+ struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges);
-+
-+/* 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 dm_pp_display_configuration *pp_display_cfg);
-+
-+bool dm_pp_apply_power_level_change_request(
-+ const struct dc_context *ctx,
-+ struct dm_pp_power_level_change_request *level_change_req);
-+
-+bool dm_pp_apply_clock_for_voltage_request(
-+ const struct dc_context *ctx,
-+ struct dm_pp_clock_for_voltage_req *clock_for_voltage_req);
-+
-+bool dm_pp_get_static_clocks(
-+ const struct dc_context *ctx,
-+ struct dm_pp_static_clock_info *static_clk_info);
-+
-+/****** end of PP interfaces ******/
-+
-+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);
-+
-+struct persistent_data_flag {
-+ bool save_per_link;
-+ bool save_per_edid;
-+};
-+
-+/* Call to write data in registry editor for persistent data storage.
-+ *
-+ * \inputs sink - identify edid/link for registry folder creation
-+ * module name - identify folders for registry
-+ * key name - identify keys within folders for registry
-+ * params - value to write in defined folder/key
-+ * size - size of the input params
-+ * flag - determine whether to save by link or edid
-+ *
-+ * \returns true - call is successful
-+ * false - call failed
-+ *
-+ * sink module key
-+ * -----------------------------------------------------------------------------
-+ * NULL NULL NULL - failure
-+ * NULL NULL - - create key with param value
-+ * under base folder
-+ * NULL - NULL - create module folder under base folder
-+ * - NULL NULL - failure
-+ * NULL - - - create key under module folder
-+ * with no edid/link identification
-+ * - NULL - - create key with param value
-+ * under base folder
-+ * - - NULL - create module folder under base folder
-+ * - - - - create key under module folder
-+ * with edid/link identification
-+ */
-+bool dm_write_persistent_data(struct dc_context *ctx,
-+ const struct dc_sink *sink,
-+ const char *module_name,
-+ const char *key_name,
-+ void *params,
-+ unsigned int size,
-+ struct persistent_data_flag *flag);
-+
-+
-+/* Call to read data in registry editor for persistent data storage.
-+ *
-+ * \inputs sink - identify edid/link for registry folder creation
-+ * module name - identify folders for registry
-+ * key name - identify keys within folders for registry
-+ * size - size of the output params
-+ * flag - determine whether it was save by link or edid
-+ *
-+ * \returns params - value read from defined folder/key
-+ * true - call is successful
-+ * false - call failed
-+ *
-+ * sink module key
-+ * -----------------------------------------------------------------------------
-+ * NULL NULL NULL - failure
-+ * NULL NULL - - read key under base folder
-+ * NULL - NULL - failure
-+ * - NULL NULL - failure
-+ * NULL - - - read key under module folder
-+ * with no edid/link identification
-+ * - NULL - - read key under base folder
-+ * - - NULL - failure
-+ * - - - - read key under module folder
-+ * with edid/link identification
-+ */
-+bool dm_read_persistent_data(struct dc_context *ctx,
-+ const struct dc_sink *sink,
-+ const char *module_name,
-+ const char *key_name,
-+ void *params,
-+ unsigned int size,
-+ struct persistent_data_flag *flag);
-+
-+void dm_delay_in_microseconds
-+ (struct dc_context *ctx, unsigned int microSeconds);
-+
-+bool dm_query_extended_brightness_caps
-+ (struct dc_context *ctx, enum dm_acpi_display_type display,
-+ struct dm_acpi_atif_backlight_caps *pCaps);
-+
-+bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id);
-+
-+/*
-+ *
-+ * 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);
-+
-+#endif /* __DM_SERVICES_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
-new file mode 100644
-index 0000000..44bad17
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
-@@ -0,0 +1,242 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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__
-+
-+#include "os_types.h"
-+#include "dc_types.h"
-+
-+struct dm_pp_clock_range {
-+ int min_khz;
-+ int max_khz;
-+};
-+
-+enum dm_pp_clocks_state {
-+ DM_PP_CLOCKS_STATE_INVALID,
-+ DM_PP_CLOCKS_STATE_ULTRA_LOW,
-+ DM_PP_CLOCKS_STATE_LOW,
-+ DM_PP_CLOCKS_STATE_NOMINAL,
-+ DM_PP_CLOCKS_STATE_PERFORMANCE,
-+
-+ /* Starting from DCE11, Max 8 levels of DPM state supported. */
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DM_PP_CLOCKS_STATE_INVALID,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_0 = DM_PP_CLOCKS_STATE_ULTRA_LOW,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_1 = DM_PP_CLOCKS_STATE_LOW,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_2 = DM_PP_CLOCKS_STATE_NOMINAL,
-+ /* to be backward compatible */
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_3 = DM_PP_CLOCKS_STATE_PERFORMANCE,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
-+ DM_PP_CLOCKS_DPM_STATE_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
-+};
-+
-+struct dm_pp_gpu_clock_range {
-+ enum dm_pp_clocks_state clock_state;
-+ struct dm_pp_clock_range sclk;
-+ struct dm_pp_clock_range mclk;
-+ struct dm_pp_clock_range eclk;
-+ struct dm_pp_clock_range dclk;
-+};
-+
-+enum dm_pp_clock_type {
-+ DM_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
-+ DM_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
-+ DM_PP_CLOCK_TYPE_MEMORY_CLK,
-+ DM_PP_CLOCK_TYPE_DCFCLK,
-+ DM_PP_CLOCK_TYPE_SOCCLK,
-+ DM_PP_CLOCK_TYPE_PIXELCLK,
-+ DM_PP_CLOCK_TYPE_DISPLAYPHYCLK
-+};
-+
-+#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
-+ (clk_type) == DM_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
-+ (clk_type) == DM_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
-+ (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
-+
-+#define DM_PP_MAX_CLOCK_LEVELS 8
-+
-+struct dm_pp_clock_levels {
-+ uint32_t num_levels;
-+ uint32_t clocks_in_khz[DM_PP_MAX_CLOCK_LEVELS];
-+};
-+
-+struct dm_pp_clock_with_latency {
-+ uint32_t clocks_in_khz;
-+ uint32_t latency_in_us;
-+};
-+
-+struct dm_pp_clock_levels_with_latency {
-+ uint32_t num_levels;
-+ struct dm_pp_clock_with_latency data[DM_PP_MAX_CLOCK_LEVELS];
-+};
-+
-+struct dm_pp_clock_with_voltage {
-+ uint32_t clocks_in_khz;
-+ uint32_t voltage_in_mv;
-+};
-+
-+struct dm_pp_clock_levels_with_voltage {
-+ uint32_t num_levels;
-+ struct dm_pp_clock_with_voltage data[DM_PP_MAX_CLOCK_LEVELS];
-+};
-+
-+struct dm_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 dc_link_settings link_settings; /* DP only */
-+};
-+
-+#define MAX_WM_SETS 4
-+
-+enum dm_pp_wm_set_id {
-+ WM_SET_A = 0,
-+ WM_SET_B,
-+ WM_SET_C,
-+ WM_SET_D,
-+ WM_SET_INVALID = 0xffff,
-+};
-+
-+struct dm_pp_clock_range_for_wm_set {
-+ enum dm_pp_wm_set_id wm_set_id;
-+ uint32_t wm_min_eng_clk_in_khz;
-+ uint32_t wm_max_eng_clk_in_khz;
-+ uint32_t wm_min_memg_clk_in_khz;
-+ uint32_t wm_max_mem_clk_in_khz;
-+};
-+
-+struct dm_pp_wm_sets_with_clock_ranges {
-+ uint32_t num_wm_sets;
-+ struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS];
-+};
-+
-+#define MAX_DISPLAY_CONFIGS 6
-+
-+struct dm_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 dm_pp_single_disp_config disp_configs[MAX_DISPLAY_CONFIGS];
-+
-+ /*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;
-+};
-+
-+struct dm_bl_data_point {
-+ /* Brightness level in percentage */
-+ uint8_t luminance;
-+ /* Brightness level as effective value in range 0-255,
-+ * corresponding to above percentage
-+ */
-+ uint8_t signalLevel;
-+};
-+
-+/* Total size of the structure should not exceed 256 bytes */
-+struct dm_acpi_atif_backlight_caps {
-+
-+
-+ uint16_t size; /* Bytes 0-1 (2 bytes) */
-+ uint16_t flags; /* Byted 2-3 (2 bytes) */
-+ uint8_t errorCode; /* Byte 4 */
-+ uint8_t acLevelPercentage; /* Byte 5 */
-+ uint8_t dcLevelPercentage; /* Byte 6 */
-+ uint8_t minInputSignal; /* Byte 7 */
-+ uint8_t maxInputSignal; /* Byte 8 */
-+ uint8_t numOfDataPoints; /* Byte 9 */
-+ struct dm_bl_data_point dataPoints[99]; /* Bytes 10-207 (198 bytes)*/
-+};
-+
-+enum dm_acpi_display_type {
-+ AcpiDisplayType_LCD1 = 0,
-+ AcpiDisplayType_CRT1 = 1,
-+ AcpiDisplayType_DFP1 = 3,
-+ AcpiDisplayType_CRT2 = 4,
-+ AcpiDisplayType_LCD2 = 5,
-+ AcpiDisplayType_DFP2 = 7,
-+ AcpiDisplayType_DFP3 = 9,
-+ AcpiDisplayType_DFP4 = 10,
-+ AcpiDisplayType_DFP5 = 11,
-+ AcpiDisplayType_DFP6 = 12
-+};
-+
-+enum dm_pp_power_level {
-+ DM_PP_POWER_LEVEL_INVALID,
-+ DM_PP_POWER_LEVEL_ULTRA_LOW,
-+ DM_PP_POWER_LEVEL_LOW,
-+ DM_PP_POWER_LEVEL_NOMINAL,
-+ DM_PP_POWER_LEVEL_PERFORMANCE,
-+
-+ DM_PP_POWER_LEVEL_0 = DM_PP_POWER_LEVEL_ULTRA_LOW,
-+ DM_PP_POWER_LEVEL_1 = DM_PP_POWER_LEVEL_LOW,
-+ DM_PP_POWER_LEVEL_2 = DM_PP_POWER_LEVEL_NOMINAL,
-+ DM_PP_POWER_LEVEL_3 = DM_PP_POWER_LEVEL_PERFORMANCE,
-+ DM_PP_POWER_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
-+ DM_PP_POWER_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
-+ DM_PP_POWER_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
-+ DM_PP_POWER_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
-+};
-+
-+struct dm_pp_power_level_change_request {
-+ enum dm_pp_power_level power_level;
-+};
-+
-+struct dm_pp_clock_for_voltage_req {
-+ enum dm_pp_clock_type clk_type;
-+ uint32_t clocks_in_khz;
-+};
-+
-+struct dm_pp_static_clock_info {
-+ uint32_t max_sclk_khz;
-+ uint32_t max_mclk_khz;
-+
-+ /* max possible display block clocks state */
-+ enum dm_pp_clocks_state max_clocks_state;
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
-new file mode 100644
-index 0000000..a15c257
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
-@@ -0,0 +1,38 @@
-+#
-+# Makefile for the 'gpio' sub-component of DAL.
-+# It provides the control and status of HW GPIO pins.
-+
-+GPIO = gpio_base.o gpio_service.o hw_factory.o \
-+ hw_gpio.o hw_hpd.o hw_ddc.o hw_translate.o
-+
-+AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO)
-+
-+###############################################################################
-+# DCE 8x
-+###############################################################################
-+# all DCE8.x are derived from DCE8.0
-+GPIO_DCE80 = hw_translate_dce80.o hw_factory_dce80.o
-+
-+AMD_DAL_GPIO_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpio/dce80/,$(GPIO_DCE80))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE80)
-+
-+###############################################################################
-+# DCE 11x
-+###############################################################################
-+GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o
-+
-+AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110)
-+
-+###############################################################################
-+# Diagnostics on FPGA
-+###############################################################################
-+GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o
-+
-+AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DIAG_FPGA)
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c
-new file mode 100644
-index 0000000..20d81bc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c
-@@ -0,0 +1,178 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "include/gpio_types.h"
-+#include "../hw_factory.h"
-+
-+#include "hw_factory_dce110.h"
-+
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+/* set field name */
-+#define SF_HPD(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+#define REG(reg_name)\
-+ mm ## reg_name
-+
-+#define REGI(reg_name, block, id)\
-+ mm ## block ## id ## _ ## reg_name
-+
-+#include "../hw_gpio.h"
-+#include "../hw_ddc.h"
-+#include "../hw_hpd.h"
-+
-+#include "reg_helper.h"
-+#include "../hpd_regs.h"
-+
-+#define hpd_regs(id) \
-+{\
-+ HPD_REG_LIST(id)\
-+}
-+
-+static const struct hpd_registers hpd_regs[] = {
-+ hpd_regs(0),
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5)
-+};
-+
-+static const struct hpd_sh_mask hpd_shift = {
-+ HPD_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct hpd_sh_mask hpd_mask = {
-+ HPD_MASK_SH_LIST(_MASK)
-+};
-+
-+#include "../ddc_regs.h"
-+
-+ /* set field name */
-+#define SF_DDC(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+static const struct ddc_registers ddc_data_regs[] = {
-+ ddc_data_regs(1),
-+ ddc_data_regs(2),
-+ ddc_data_regs(3),
-+ ddc_data_regs(4),
-+ ddc_data_regs(5),
-+ ddc_data_regs(6),
-+ ddc_vga_data_regs,
-+ ddc_i2c_data_regs
-+};
-+
-+static const struct ddc_registers ddc_clk_regs[] = {
-+ ddc_clk_regs(1),
-+ ddc_clk_regs(2),
-+ ddc_clk_regs(3),
-+ ddc_clk_regs(4),
-+ ddc_clk_regs(5),
-+ ddc_clk_regs(6),
-+ ddc_vga_clk_regs,
-+ ddc_i2c_clk_regs
-+};
-+
-+static const struct ddc_sh_mask ddc_shift = {
-+ DDC_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct ddc_sh_mask ddc_mask = {
-+ DDC_MASK_SH_LIST(_MASK)
-+};
-+
-+static void define_ddc_registers(
-+ struct hw_gpio_pin *pin,
-+ uint32_t en)
-+{
-+ struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin);
-+
-+ switch (pin->id) {
-+ case GPIO_ID_DDC_DATA:
-+ ddc->regs = &ddc_data_regs[en];
-+ ddc->base.regs = &ddc_data_regs[en].gpio;
-+ break;
-+ case GPIO_ID_DDC_CLOCK:
-+ ddc->regs = &ddc_clk_regs[en];
-+ ddc->base.regs = &ddc_clk_regs[en].gpio;
-+ break;
-+ default:
-+ ASSERT_CRITICAL(false);
-+ return;
-+ }
-+
-+ ddc->shifts = &ddc_shift;
-+ ddc->masks = &ddc_mask;
-+
-+}
-+
-+static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en)
-+{
-+ struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin);
-+
-+ hpd->regs = &hpd_regs[en];
-+ hpd->shifts = &hpd_shift;
-+ hpd->masks = &hpd_mask;
-+ hpd->base.regs = &hpd_regs[en].gpio;
-+}
-+
-+static const struct hw_factory_funcs funcs = {
-+ .create_ddc_data = dal_hw_ddc_create,
-+ .create_ddc_clock = dal_hw_ddc_create,
-+ .create_generic = NULL,
-+ .create_hpd = dal_hw_hpd_create,
-+ .create_sync = NULL,
-+ .create_gsl = NULL,
-+ .define_hpd_registers = define_hpd_registers,
-+ .define_ddc_registers = define_ddc_registers
-+};
-+
-+/*
-+ * 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/display/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h
-new file mode 100644
-index 0000000..ecf06ed
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c
-new file mode 100644
-index 0000000..ac4cddb
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c
-@@ -0,0 +1,387 @@
-+/*
-+ * 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"
-+
-+#include "hw_translate_dce110.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/display/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h
-new file mode 100644
-index 0000000..4d16e09
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpio/dce80/hw_factory_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c
-new file mode 100644
-index 0000000..48b6786
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c
-@@ -0,0 +1,173 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_factory.h"
-+
-+#include "hw_factory_dce80.h"
-+
-+#include "../hw_gpio.h"
-+#include "../hw_ddc.h"
-+#include "../hw_hpd.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#define REG(reg_name)\
-+ mm ## reg_name
-+
-+#include "reg_helper.h"
-+#include "../hpd_regs.h"
-+
-+#define HPD_REG_LIST_DCE8(id) \
-+ HPD_GPIO_REG_LIST(id), \
-+ .int_status = mmDC_HPD ## id ## _INT_STATUS,\
-+ .toggle_filt_cntl = mmDC_HPD ## id ## _TOGGLE_FILT_CNTL
-+
-+#define HPD_MASK_SH_LIST_DCE8(mask_sh) \
-+ .DC_HPD_SENSE_DELAYED = DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED ## mask_sh,\
-+ .DC_HPD_SENSE = DC_HPD1_INT_STATUS__DC_HPD1_SENSE ## mask_sh,\
-+ .DC_HPD_CONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY ## mask_sh,\
-+ .DC_HPD_DISCONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY ## mask_sh
-+
-+#define hpd_regs(id) \
-+{\
-+ HPD_REG_LIST_DCE8(id)\
-+}
-+
-+static const struct hpd_registers hpd_regs[] = {
-+ hpd_regs(1),
-+ hpd_regs(2),
-+ hpd_regs(3),
-+ hpd_regs(4),
-+ hpd_regs(5),
-+ hpd_regs(6)
-+};
-+
-+static const struct hpd_sh_mask hpd_shift = {
-+ HPD_MASK_SH_LIST_DCE8(__SHIFT)
-+};
-+
-+static const struct hpd_sh_mask hpd_mask = {
-+ HPD_MASK_SH_LIST_DCE8(_MASK)
-+};
-+
-+#include "../ddc_regs.h"
-+
-+ /* set field name */
-+#define SF_DDC(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+static const struct ddc_registers ddc_data_regs[] = {
-+ ddc_data_regs(1),
-+ ddc_data_regs(2),
-+ ddc_data_regs(3),
-+ ddc_data_regs(4),
-+ ddc_data_regs(5),
-+ ddc_data_regs(6),
-+ ddc_vga_data_regs,
-+ ddc_i2c_data_regs
-+};
-+
-+static const struct ddc_registers ddc_clk_regs[] = {
-+ ddc_clk_regs(1),
-+ ddc_clk_regs(2),
-+ ddc_clk_regs(3),
-+ ddc_clk_regs(4),
-+ ddc_clk_regs(5),
-+ ddc_clk_regs(6),
-+ ddc_vga_clk_regs,
-+ ddc_i2c_clk_regs
-+};
-+
-+static const struct ddc_sh_mask ddc_shift = {
-+ DDC_MASK_SH_LIST(__SHIFT)
-+};
-+
-+static const struct ddc_sh_mask ddc_mask = {
-+ DDC_MASK_SH_LIST(_MASK)
-+};
-+
-+static void define_ddc_registers(
-+ struct hw_gpio_pin *pin,
-+ uint32_t en)
-+{
-+ struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin);
-+
-+ switch (pin->id) {
-+ case GPIO_ID_DDC_DATA:
-+ ddc->regs = &ddc_data_regs[en];
-+ ddc->base.regs = &ddc_data_regs[en].gpio;
-+ break;
-+ case GPIO_ID_DDC_CLOCK:
-+ ddc->regs = &ddc_clk_regs[en];
-+ ddc->base.regs = &ddc_clk_regs[en].gpio;
-+ break;
-+ default:
-+ ASSERT_CRITICAL(false);
-+ return;
-+ }
-+
-+ ddc->shifts = &ddc_shift;
-+ ddc->masks = &ddc_mask;
-+
-+}
-+
-+static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en)
-+{
-+ struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin);
-+
-+ hpd->regs = &hpd_regs[en];
-+ hpd->shifts = &hpd_shift;
-+ hpd->masks = &hpd_mask;
-+ hpd->base.regs = &hpd_regs[en].gpio;
-+}
-+
-+static const struct hw_factory_funcs funcs = {
-+ .create_ddc_data = dal_hw_ddc_create,
-+ .create_ddc_clock = dal_hw_ddc_create,
-+ .create_generic = NULL,
-+ .create_hpd = dal_hw_hpd_create,
-+ .create_sync = NULL,
-+ .create_gsl = NULL,
-+ .define_hpd_registers = define_hpd_registers,
-+ .define_ddc_registers = define_ddc_registers
-+};
-+
-+void dal_hw_factory_dce80_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/display/dc/gpio/dce80/hw_factory_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h
-new file mode 100644
-index 0000000..e78a8b3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE80_H__
-+#define __DAL_HW_FACTORY_DCE80_H__
-+
-+void dal_hw_factory_dce80_init(
-+ struct hw_factory *factory);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c
-new file mode 100644
-index 0000000..fabb9da
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c
-@@ -0,0 +1,411 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_translate.h"
-+
-+#include "hw_translate_dce80.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+#include "smu/smu_7_0_1_d.h"
-+
-+/*
-+ * @brief
-+ * Returns index of first bit (starting with LSB) which is set
-+ */
-+static uint32_t index_from_vector(
-+ uint32_t vector)
-+{
-+ uint32_t result = 0;
-+ uint32_t mask = 1;
-+
-+ do {
-+ if (vector == mask)
-+ return result;
-+
-+ ++result;
-+ mask <<= 1;
-+ } while (mask);
-+
-+ BREAK_TO_DEBUGGER();
-+
-+ return GPIO_ENUM_UNKNOWN;
-+}
-+
-+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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+ break;
-+ /* GPIOPAD */
-+ case mmGPIOPAD_A:
-+ *id = GPIO_ID_GPIO_PAD;
-+ *en = index_from_vector(mask);
-+ return (*en <= GPIO_GPIO_PAD_MAX);
-+ /* 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ 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:
-+ BREAK_TO_DEBUGGER();
-+ result = false;
-+ }
-+ break;
-+ case GPIO_ID_GPIO_PAD:
-+ info->offset = mmGPIOPAD_A;
-+ info->mask = (1 << en);
-+ result = (info->mask <= GPIO_GPIO_PAD_MAX);
-+ break;
-+ case GPIO_ID_VIP_PAD:
-+ default:
-+ BREAK_TO_DEBUGGER();
-+ 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;
-+}
-+
-+static const struct hw_translate_funcs funcs = {
-+ .offset_to_id = offset_to_id,
-+ .id_to_offset = id_to_offset,
-+};
-+
-+void dal_hw_translate_dce80_init(
-+ struct hw_translate *translate)
-+{
-+ translate->funcs = &funcs;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h
-new file mode 100644
-index 0000000..374f2f3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE80_H__
-+#define __DAL_HW_TRANSLATE_DCE80_H__
-+
-+void dal_hw_translate_dce80_init(
-+ struct hw_translate *tr);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
-new file mode 100644
-index 0000000..9c4a56c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
-@@ -0,0 +1,150 @@
-+/*
-+ * 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 DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_
-+
-+#include "gpio_regs.h"
-+
-+/****************************** new register headers */
-+/*** following in header */
-+
-+#define DDC_GPIO_REG_LIST_ENTRY(type,cd,id) \
-+ .type ## _reg = REG(DC_GPIO_DDC ## id ## _ ## type),\
-+ .type ## _mask = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## _MASK,\
-+ .type ## _shift = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## __SHIFT
-+
-+#define DDC_GPIO_REG_LIST(cd,id) \
-+ {\
-+ DDC_GPIO_REG_LIST_ENTRY(MASK,cd,id),\
-+ DDC_GPIO_REG_LIST_ENTRY(A,cd,id),\
-+ DDC_GPIO_REG_LIST_ENTRY(EN,cd,id),\
-+ DDC_GPIO_REG_LIST_ENTRY(Y,cd,id)\
-+ }
-+
-+#define DDC_REG_LIST(cd,id) \
-+ DDC_GPIO_REG_LIST(cd,id),\
-+ .ddc_setup = REG(DC_I2C_DDC ## id ## _SETUP)
-+
-+#define DDC_GPIO_VGA_REG_LIST_ENTRY(type,cd)\
-+ .type ## _reg = REG(DC_GPIO_DDCVGA_ ## type),\
-+ .type ## _mask = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## _MASK,\
-+ .type ## _shift = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## __SHIFT
-+
-+#define DDC_GPIO_VGA_REG_LIST(cd) \
-+ {\
-+ DDC_GPIO_VGA_REG_LIST_ENTRY(MASK,cd),\
-+ DDC_GPIO_VGA_REG_LIST_ENTRY(A,cd),\
-+ DDC_GPIO_VGA_REG_LIST_ENTRY(EN,cd),\
-+ DDC_GPIO_VGA_REG_LIST_ENTRY(Y,cd)\
-+ }
-+
-+#define DDC_VGA_REG_LIST(cd) \
-+ DDC_GPIO_VGA_REG_LIST(cd),\
-+ .ddc_setup = mmDC_I2C_DDCVGA_SETUP
-+
-+#define DDC_GPIO_I2C_REG_LIST_ENTRY(type,cd) \
-+ .type ## _reg = REG(DC_GPIO_I2CPAD_ ## type),\
-+ .type ## _mask = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## _MASK,\
-+ .type ## _shift = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## __SHIFT
-+
-+#define DDC_GPIO_I2C_REG_LIST(cd) \
-+ {\
-+ DDC_GPIO_I2C_REG_LIST_ENTRY(MASK,cd),\
-+ DDC_GPIO_I2C_REG_LIST_ENTRY(A,cd),\
-+ DDC_GPIO_I2C_REG_LIST_ENTRY(EN,cd),\
-+ DDC_GPIO_I2C_REG_LIST_ENTRY(Y,cd)\
-+ }
-+
-+#define DDC_I2C_REG_LIST(cd) \
-+ DDC_GPIO_I2C_REG_LIST(cd),\
-+ .ddc_setup = 0
-+
-+#define DDC_MASK_SH_LIST(mask_sh) \
-+ SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\
-+ SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_ENABLE, mask_sh),\
-+ SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_MODE, mask_sh),\
-+ SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1DATA_PD_EN, mask_sh),\
-+ SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1CLK_PD_EN, mask_sh),\
-+ SF_DDC(DC_GPIO_DDC1_MASK, AUX_PAD1_MODE, mask_sh),\
-+ SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SDA_PD_DIS, mask_sh),\
-+ SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SCL_PD_DIS, mask_sh)
-+
-+
-+struct ddc_registers {
-+ struct gpio_registers gpio;
-+ uint32_t ddc_setup;
-+};
-+
-+struct ddc_sh_mask {
-+ /* i2c_dd_setup */
-+ uint32_t DC_I2C_DDC1_ENABLE;
-+ uint32_t DC_I2C_DDC1_EDID_DETECT_ENABLE;
-+ uint32_t DC_I2C_DDC1_EDID_DETECT_MODE;
-+ /* ddc1_mask */
-+ uint32_t DC_GPIO_DDC1DATA_PD_EN;
-+ uint32_t DC_GPIO_DDC1CLK_PD_EN;
-+ uint32_t AUX_PAD1_MODE;
-+ /* i2cpad_mask */
-+ uint32_t DC_GPIO_SDA_PD_DIS;
-+ uint32_t DC_GPIO_SCL_PD_DIS;
-+};
-+
-+
-+
-+/*** following in dc_resource */
-+
-+#define ddc_data_regs(id) \
-+{\
-+ DDC_REG_LIST(DATA,id)\
-+}
-+
-+#define ddc_clk_regs(id) \
-+{\
-+ DDC_REG_LIST(CLK,id)\
-+}
-+
-+#define ddc_vga_data_regs \
-+{\
-+ DDC_VGA_REG_LIST(DATA)\
-+}
-+
-+#define ddc_vga_clk_regs \
-+{\
-+ DDC_VGA_REG_LIST(CLK)\
-+}
-+
-+#define ddc_i2c_data_regs \
-+{\
-+ DDC_I2C_REG_LIST(SDA)\
-+}
-+
-+#define ddc_i2c_clk_regs \
-+{\
-+ DDC_I2C_REG_LIST(SCL)\
-+}
-+
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c
-new file mode 100644
-index 0000000..26695b9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c
-@@ -0,0 +1,63 @@
-+/*
-+ * 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.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_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/display/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h
-new file mode 100644
-index 0000000..8a74f6a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c
-new file mode 100644
-index 0000000..bf90688
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c
-@@ -0,0 +1,40 @@
-+/*
-+ * 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/display/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h
-new file mode 100644
-index 0000000..4f05324
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
-new file mode 100644
-index 0000000..d42eb3d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.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
-+ *
-+ */
-+
-+/*
-+ * 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.h"
-+#include "hw_translate.h"
-+#include "hw_factory.h"
-+#include "gpio_service.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);
-+}
-+
-+enum gpio_result dal_gpio_open_ex(
-+ struct gpio *gpio,
-+ enum gpio_mode mode)
-+{
-+ 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, &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(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);
-+
-+ *gpio = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h
-new file mode 100644
-index 0000000..5c59252
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h
-@@ -0,0 +1,45 @@
-+/*
-+ * 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 DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_
-+
-+struct gpio_registers {
-+ uint32_t MASK_reg;
-+ uint32_t MASK_mask;
-+ uint32_t MASK_shift;
-+ uint32_t A_reg;
-+ uint32_t A_mask;
-+ uint32_t A_shift;
-+ uint32_t EN_reg;
-+ uint32_t EN_mask;
-+ uint32_t EN_shift;
-+ uint32_t Y_reg;
-+ uint32_t Y_mask;
-+ uint32_t Y_shift;
-+};
-+
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
-new file mode 100644
-index 0000000..eeb1cd0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
-@@ -0,0 +1,592 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_translate.h"
-+#include "hw_factory.h"
-+
-+/*
-+ * Header of this unit
-+ */
-+
-+#include "gpio_service.h"
-+
-+/*
-+ * Post-requisites: headers required by this unit
-+ */
-+
-+#include "hw_gpio.h"
-+
-+/*
-+ * @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(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(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(slot);
-+ };
-+
-+failure_1:
-+ dm_free(service);
-+
-+ return NULL;
-+}
-+
-+struct gpio *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);
-+}
-+
-+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(slot);
-+
-+ ++index_of_id;
-+ } while (index_of_id < GPIO_ID_COUNT);
-+ }
-+
-+ dm_free(*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,
-+ 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);
-+ service->factory.funcs->define_ddc_registers(pin, en);
-+ break;
-+ case GPIO_ID_DDC_CLOCK:
-+ pin = service->factory.funcs->create_ddc_clock(
-+ service->ctx, id, en);
-+ service->factory.funcs->define_ddc_registers(pin, 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);
-+ service->factory.funcs->define_hpd_registers(pin, 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)) {
-+ 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);
-+ }
-+}
-+
-+
-+enum dc_irq_source dal_irq_get_source(
-+ const struct gpio *irq)
-+{
-+ enum gpio_id id = dal_gpio_get_id(irq);
-+
-+ switch (id) {
-+ case GPIO_ID_HPD:
-+ return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
-+ dal_gpio_get_enum(irq));
-+ case GPIO_ID_GPIO_PAD:
-+ return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
-+ dal_gpio_get_enum(irq));
-+ default:
-+ return DC_IRQ_SOURCE_INVALID;
-+ }
-+}
-+
-+enum dc_irq_source dal_irq_get_rx_source(
-+ const struct gpio *irq)
-+{
-+ enum gpio_id id = dal_gpio_get_id(irq);
-+
-+ switch (id) {
-+ case GPIO_ID_HPD:
-+ return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
-+ dal_gpio_get_enum(irq));
-+ default:
-+ return DC_IRQ_SOURCE_INVALID;
-+ }
-+}
-+
-+enum gpio_result dal_irq_setup_hpd_filter(
-+ struct gpio *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, &config_data);
-+}
-+
-+/*
-+ * @brief
-+ * Creation and destruction
-+ */
-+
-+struct gpio *dal_gpio_create_irq(
-+ struct gpio_service *service,
-+ enum gpio_id id,
-+ uint32_t en)
-+{
-+ struct gpio *irq;
-+
-+ switch (id) {
-+ case GPIO_ID_HPD:
-+ case GPIO_ID_GPIO_PAD:
-+ break;
-+ default:
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ irq = dal_gpio_create(
-+ service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
-+
-+ if (irq)
-+ return irq;
-+
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+}
-+
-+void dal_gpio_destroy_irq(
-+ struct gpio **irq)
-+{
-+ if (!irq || !*irq) {
-+ ASSERT_CRITICAL(false);
-+ return;
-+ }
-+
-+ dal_gpio_close(*irq);
-+ dal_gpio_destroy(irq);
-+ dm_free(*irq);
-+
-+ *irq = NULL;
-+}
-+
-+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(sizeof(struct ddc));
-+
-+ if (!ddc) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ ddc->pin_data = dal_gpio_create(
-+ 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_create(
-+ 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_destroy(&ddc->pin_data);
-+
-+failure_1:
-+ dm_free(ddc);
-+
-+ return NULL;
-+}
-+
-+void dal_gpio_destroy_ddc(
-+ struct ddc **ddc)
-+{
-+ if (!ddc || !*ddc) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ dal_ddc_close(*ddc);
-+ dal_gpio_destroy(&(*ddc)->pin_data);
-+ dal_gpio_destroy(&(*ddc)->pin_clock);
-+ dm_free(*ddc);
-+
-+ *ddc = NULL;
-+}
-+
-+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_config_data config_data;
-+ struct hw_gpio *hw_data;
-+ struct hw_gpio *hw_clock;
-+
-+ result = dal_gpio_open_ex(ddc->pin_data, mode);
-+
-+ if (result != GPIO_RESULT_OK) {
-+ BREAK_TO_DEBUGGER();
-+ return result;
-+ }
-+
-+ result = dal_gpio_open_ex(ddc->pin_clock, mode);
-+
-+ 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;
-+
-+ hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
-+ hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
-+
-+ config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
-+ config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
-+
-+ 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_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;
-+}
-+
-+enum gpio_ddc_line dal_ddc_get_line(
-+ const struct ddc *ddc)
-+{
-+ return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
-+}
-+
-+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);
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h
-new file mode 100644
-index 0000000..c7f3081
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.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_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,
-+ 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/display/dc/gpio/hpd_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h
-new file mode 100644
-index 0000000..dcfdd71
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h
-@@ -0,0 +1,79 @@
-+/*
-+ * 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 DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_
-+
-+#include "gpio_regs.h"
-+
-+#define ONE_MORE_0 1
-+#define ONE_MORE_1 2
-+#define ONE_MORE_2 3
-+#define ONE_MORE_3 4
-+#define ONE_MORE_4 5
-+#define ONE_MORE_5 6
-+
-+
-+#define HPD_GPIO_REG_LIST_ENTRY(type,cd,id) \
-+ .type ## _reg = REG(DC_GPIO_HPD_## type),\
-+ .type ## _mask = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## _MASK,\
-+ .type ## _shift = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## __SHIFT
-+
-+#define HPD_GPIO_REG_LIST(id) \
-+ {\
-+ HPD_GPIO_REG_LIST_ENTRY(MASK,cd,id),\
-+ HPD_GPIO_REG_LIST_ENTRY(A,cd,id),\
-+ HPD_GPIO_REG_LIST_ENTRY(EN,cd,id),\
-+ HPD_GPIO_REG_LIST_ENTRY(Y,cd,id)\
-+ }
-+
-+#define HPD_REG_LIST(id) \
-+ HPD_GPIO_REG_LIST(ONE_MORE_ ## id), \
-+ .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\
-+ .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id)
-+
-+ #define HPD_MASK_SH_LIST(mask_sh) \
-+ SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE_DELAYED, mask_sh),\
-+ SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\
-+ SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\
-+ SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh)
-+
-+struct hpd_registers {
-+ struct gpio_registers gpio;
-+ uint32_t int_status;
-+ uint32_t toggle_filt_cntl;
-+};
-+
-+struct hpd_sh_mask {
-+ /* int_status */
-+ uint32_t DC_HPD_SENSE_DELAYED;
-+ uint32_t DC_HPD_SENSE;
-+ /* toggle_filt_cntl */
-+ uint32_t DC_HPD_CONNECT_INT_DELAY;
-+ uint32_t DC_HPD_DISCONNECT_INT_DELAY;
-+};
-+
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
-new file mode 100644
-index 0000000..47e0f8f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
-@@ -0,0 +1,243 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_gpio.h"
-+#include "hw_ddc.h"
-+
-+#include "reg_helper.h"
-+#include "gpio_regs.h"
-+
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ ddc->shifts->field_name, ddc->masks->field_name
-+
-+#define CTX \
-+ ddc->base.base.ctx
-+#define REG(reg)\
-+ (ddc->regs->reg)
-+
-+static void destruct(
-+ struct hw_ddc *pin)
-+{
-+ dal_hw_gpio_destruct(&pin->base);
-+}
-+
-+static void destroy(
-+ struct hw_gpio_pin **ptr)
-+{
-+ struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
-+
-+ destruct(pin);
-+
-+ dm_free(pin);
-+
-+ *ptr = NULL;
-+}
-+
-+static enum gpio_result set_config(
-+ struct hw_gpio_pin *ptr,
-+ const struct gpio_config_data *config_data)
-+{
-+ struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
-+ struct hw_gpio *hw_gpio = NULL;
-+ 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 = &ddc->base;
-+
-+ if (hw_gpio == NULL) {
-+ ASSERT_CRITICAL(false);
-+ return GPIO_RESULT_NULL_HANDLE;
-+ }
-+
-+ regval = REG_GET_3(gpio.MASK_reg,
-+ DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en,
-+ DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en,
-+ AUX_PAD1_MODE, &aux_pad_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) {
-+
-+ REG_SET_2(gpio.MASK_reg, regval,
-+ DC_GPIO_DDC1DATA_PD_EN, 1,
-+ DC_GPIO_DDC1CLK_PD_EN, 1);
-+
-+ if (config_data->type ==
-+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
-+ msleep(3);
-+ }
-+ } else {
-+ uint32_t reg2;
-+ uint32_t sda_pd_dis = 0;
-+ uint32_t scl_pd_dis = 0;
-+
-+ reg2 = REG_GET_2(gpio.MASK_reg,
-+ DC_GPIO_SDA_PD_DIS, &sda_pd_dis,
-+ DC_GPIO_SCL_PD_DIS, &scl_pd_dis);
-+
-+ if (sda_pd_dis) {
-+ REG_SET(gpio.MASK_reg, regval,
-+ DC_GPIO_SDA_PD_DIS, 0);
-+
-+ if (config_data->type ==
-+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
-+ msleep(3);
-+ }
-+
-+ if (!scl_pd_dis) {
-+ REG_SET(gpio.MASK_reg, regval,
-+ DC_GPIO_SCL_PD_DIS, 1);
-+
-+ if (config_data->type ==
-+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
-+ msleep(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); */
-+ msleep(2);
-+
-+ /* set the I2C pad mode */
-+ /* read the register again,
-+ * some bits may have been changed */
-+ REG_UPDATE(gpio.MASK_reg,
-+ AUX_PAD1_MODE, 0);
-+ }
-+
-+ return GPIO_RESULT_OK;
-+ case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
-+ /* set the AUX pad mode */
-+ if (!aux_pad_mode) {
-+ REG_SET(gpio.MASK_reg, regval,
-+ AUX_PAD1_MODE, 1);
-+ }
-+
-+ 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)) {
-+ REG_UPDATE_3(ddc_setup,
-+ DC_I2C_DDC1_ENABLE, 1,
-+ DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
-+ DC_I2C_DDC1_EDID_DETECT_MODE, 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)) {
-+ REG_UPDATE_3(ddc_setup,
-+ DC_I2C_DDC1_ENABLE, 1,
-+ DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
-+ DC_I2C_DDC1_EDID_DETECT_MODE, 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)) {
-+ REG_UPDATE_2(ddc_setup,
-+ DC_I2C_DDC1_ENABLE, 0,
-+ DC_I2C_DDC1_EDID_DETECT_ENABLE, 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_gpio_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 *ddc,
-+ enum gpio_id id,
-+ uint32_t en,
-+ struct dc_context *ctx)
-+{
-+ if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+
-+ if (!dal_hw_gpio_construct(&ddc->base, id, en, ctx)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+
-+ ddc->base.base.funcs = &funcs;
-+
-+ return true;
-+}
-+
-+struct hw_gpio_pin *dal_hw_ddc_create(
-+ struct dc_context *ctx,
-+ enum gpio_id id,
-+ uint32_t en)
-+{
-+ struct hw_ddc *pin = dm_alloc(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(pin);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
-new file mode 100644
-index 0000000..9690e2a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.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_H__
-+#define __DAL_HW_DDC_H__
-+
-+#include "ddc_regs.h"
-+
-+struct hw_ddc {
-+ struct hw_gpio base;
-+ const struct ddc_registers *regs;
-+ const struct ddc_sh_mask *shifts;
-+ const struct ddc_sh_mask *masks;
-+};
-+
-+#define HW_DDC_FROM_BASE(hw_gpio) \
-+ container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base)
-+
-+struct hw_gpio_pin *dal_hw_ddc_create(
-+ struct dc_context *ctx,
-+ enum gpio_id id,
-+ uint32_t en);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
-new file mode 100644
-index 0000000..f1a6fa7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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
-+ */
-+
-+#include "dce80/hw_factory_dce80.h"
-+
-+#include "dce110/hw_factory_dce110.h"
-+
-+#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) {
-+ case DCE_VERSION_8_0:
-+ dal_hw_factory_dce80_init(factory);
-+ return true;
-+
-+ case DCE_VERSION_10_0:
-+ dal_hw_factory_dce110_init(factory);
-+ return true;
-+ case DCE_VERSION_11_0:
-+ case DCE_VERSION_11_2:
-+ dal_hw_factory_dce110_init(factory);
-+ return true;
-+ 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(*factory);
-+
-+ *factory = NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h
-new file mode 100644
-index 0000000..6e4dd35
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.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_HW_FACTORY_H__
-+#define __DAL_HW_FACTORY_H__
-+
-+struct hw_gpio_pin;
-+struct hw_hpd;
-+
-+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_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);
-+ void (*define_hpd_registers)(
-+ struct hw_gpio_pin *pin,
-+ uint32_t en);
-+ void (*define_ddc_registers)(
-+ struct hw_gpio_pin *pin,
-+ 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/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
-new file mode 100644
-index 0000000..4cdcdfb
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.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 "include/gpio_types.h"
-+#include "hw_gpio.h"
-+
-+#include "reg_helper.h"
-+#include "gpio_regs.h"
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ gpio->regs->field_name ## _shift, gpio->regs->field_name ## _mask
-+
-+#define CTX \
-+ gpio->base.ctx
-+#define REG(reg)\
-+ (gpio->regs->reg)
-+
-+static void store_registers(
-+ struct hw_gpio *gpio)
-+{
-+ REG_GET(MASK_reg, MASK, &gpio->store.mask);
-+ REG_GET(A_reg, A, &gpio->store.a);
-+ REG_GET(EN_reg, EN, &gpio->store.en);
-+ /* TODO store GPIO_MUX_CONTROL if we ever use it */
-+}
-+
-+static void restore_registers(
-+ struct hw_gpio *gpio)
-+{
-+ REG_UPDATE(MASK_reg, MASK, gpio->store.mask);
-+ REG_UPDATE(A_reg, A, gpio->store.a);
-+ REG_UPDATE(EN_reg, EN, gpio->store.en);
-+ /* TODO restore GPIO_MUX_CONTROL if we ever use it */
-+}
-+
-+bool dal_hw_gpio_open(
-+ struct hw_gpio_pin *ptr,
-+ enum gpio_mode mode)
-+{
-+ struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
-+
-+ store_registers(pin);
-+
-+ ptr->opened = (dal_hw_gpio_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 *gpio = FROM_HW_GPIO_PIN(ptr);
-+
-+ enum gpio_result result = GPIO_RESULT_OK;
-+
-+ switch (ptr->mode) {
-+ case GPIO_MODE_INPUT:
-+ case GPIO_MODE_OUTPUT:
-+ case GPIO_MODE_HARDWARE:
-+ case GPIO_MODE_FAST_OUTPUT:
-+ REG_GET(Y_reg, Y, value);
-+ 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 *gpio = 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:
-+ REG_UPDATE(A_reg, A, value);
-+ return GPIO_RESULT_OK;
-+ 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 */
-+ REG_UPDATE(EN_reg, EN, ~value);
-+ return GPIO_RESULT_OK;
-+ 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 dal_hw_gpio_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;
-+}
-+
-+enum gpio_result dal_hw_gpio_config_mode(
-+ struct hw_gpio *gpio,
-+ enum gpio_mode mode)
-+{
-+ gpio->base.mode = mode;
-+
-+ switch (mode) {
-+ case GPIO_MODE_INPUT:
-+ /* turn off output enable, act as input pin;
-+ * program the pin as GPIO, mask out signal driven by HW */
-+ REG_UPDATE(EN_reg, EN, 0);
-+ REG_UPDATE(MASK_reg, MASK, 1);
-+ return GPIO_RESULT_OK;
-+ case GPIO_MODE_OUTPUT:
-+ /* turn on output enable, act as output pin;
-+ * program the pin as GPIO, mask out signal driven by HW */
-+ REG_UPDATE(A_reg, A, 0);
-+ REG_UPDATE(MASK_reg, MASK, 1);
-+ return GPIO_RESULT_OK;
-+ case GPIO_MODE_FAST_OUTPUT:
-+ /* grounding the A register then use the EN register bit
-+ * will have faster effect on the rise time */
-+ REG_UPDATE(A_reg, A, 0);
-+ REG_UPDATE(MASK_reg, MASK, 1);
-+ return GPIO_RESULT_OK;
-+ case GPIO_MODE_HARDWARE:
-+ /* program the pin as tri-state, pin is driven by HW */
-+ REG_UPDATE(MASK_reg, MASK, 0);
-+ return GPIO_RESULT_OK;
-+ case GPIO_MODE_INTERRUPT:
-+ /* Interrupt mode supported only by HPD (IrqGpio) pins. */
-+ REG_UPDATE(MASK_reg, MASK, 0);
-+ return GPIO_RESULT_OK;
-+ default:
-+ return GPIO_RESULT_NON_SPECIFIC_ERROR;
-+ }
-+}
-+
-+bool dal_hw_gpio_construct(
-+ struct hw_gpio *pin,
-+ enum gpio_id id,
-+ uint32_t en,
-+ struct dc_context *ctx)
-+{
-+ pin->base.ctx = ctx;
-+ pin->base.id = id;
-+ pin->base.en = en;
-+ pin->base.mode = GPIO_MODE_UNKNOWN;
-+ pin->base.opened = false;
-+
-+ 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)
-+{
-+ ASSERT(!pin->base.opened);
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h
-new file mode 100644
-index 0000000..fb41ee2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h
-@@ -0,0 +1,144 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__
-+
-+#include "gpio_regs.h"
-+
-+#define FROM_HW_GPIO_PIN(ptr) \
-+ container_of((ptr), struct hw_gpio, base)
-+
-+struct addr_mask {
-+ uint32_t addr;
-+ uint32_t mask;
-+};
-+
-+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;
-+};
-+
-+struct hw_gpio_pin_funcs {
-+ void (*destroy)(
-+ struct hw_gpio_pin **ptr);
-+ bool (*open)(
-+ struct hw_gpio_pin *pin,
-+ enum gpio_mode mode);
-+ 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;
-+
-+/* 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;
-+
-+ /* 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;
-+ const struct gpio_registers *regs;
-+};
-+
-+#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);
-+
-+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/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
-new file mode 100644
-index 0000000..9634e88
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
-@@ -0,0 +1,175 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_gpio.h"
-+#include "hw_hpd.h"
-+
-+#include "reg_helper.h"
-+#include "hpd_regs.h"
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ hpd->shifts->field_name, hpd->masks->field_name
-+
-+#define CTX \
-+ hpd->base.base.ctx
-+#define REG(reg)\
-+ (hpd->regs->reg)
-+
-+static 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;
-+ return true;
-+}
-+
-+static void dal_hw_hpd_destruct(
-+ struct hw_hpd *pin)
-+{
-+ dal_hw_gpio_destruct(&pin->base);
-+}
-+
-+
-+static void destruct(
-+ struct hw_hpd *hpd)
-+{
-+ dal_hw_hpd_destruct(hpd);
-+}
-+
-+static void destroy(
-+ struct hw_gpio_pin **ptr)
-+{
-+ struct hw_hpd *hpd = HW_HPD_FROM_BASE(*ptr);
-+
-+ destruct(hpd);
-+
-+ dm_free(hpd);
-+
-+ *ptr = NULL;
-+}
-+
-+static enum gpio_result get_value(
-+ const struct hw_gpio_pin *ptr,
-+ uint32_t *value)
-+{
-+ struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr);
-+ uint32_t hpd_delayed = 0;
-+
-+ /* in Interrupt mode we ask for SENSE bit */
-+
-+ if (ptr->mode == GPIO_MODE_INTERRUPT) {
-+
-+ REG_GET(int_status,
-+ DC_HPD_SENSE_DELAYED, &hpd_delayed);
-+
-+ *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 *hpd = HW_HPD_FROM_BASE(ptr);
-+
-+ if (!config_data)
-+ return GPIO_RESULT_INVALID_DATA;
-+
-+ REG_UPDATE_2(toggle_filt_cntl,
-+ DC_HPD_CONNECT_INT_DELAY, config_data->config.hpd.delay_on_connect / 10,
-+ DC_HPD_DISCONNECT_INT_DELAY, config_data->config.hpd.delay_on_disconnect / 10);
-+
-+ 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 *hpd,
-+ enum gpio_id id,
-+ uint32_t en,
-+ struct dc_context *ctx)
-+{
-+ 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(hpd, id, en, ctx)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+
-+ hpd->base.base.funcs = &funcs;
-+
-+ return true;
-+}
-+
-+struct hw_gpio_pin *dal_hw_hpd_create(
-+ struct dc_context *ctx,
-+ enum gpio_id id,
-+ uint32_t en)
-+{
-+ struct hw_hpd *hpd = dm_alloc(sizeof(struct hw_hpd));
-+
-+ if (!hpd) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (construct(hpd, id, en, ctx))
-+ return &hpd->base.base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(hpd);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h
-new file mode 100644
-index 0000000..4ab7a20
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.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_HPD_H__
-+#define __DAL_HW_HPD_H__
-+
-+#include "hpd_regs.h"
-+
-+struct hw_hpd {
-+ struct hw_gpio base;
-+ const struct hpd_registers *regs;
-+ const struct hpd_sh_mask *shifts;
-+ const struct hpd_sh_mask *masks;
-+};
-+
-+#define HW_HPD_FROM_BASE(hw_gpio) \
-+ container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base)
-+
-+struct hw_gpio_pin *dal_hw_hpd_create(
-+ struct dc_context *ctx,
-+ enum gpio_id id,
-+ uint32_t en);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
-new file mode 100644
-index 0000000..23e097f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
-@@ -0,0 +1,75 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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
-+ */
-+
-+#include "dce80/hw_translate_dce80.h"
-+#include "dce110/hw_translate_dce110.h"
-+
-+#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) {
-+ case DCE_VERSION_8_0:
-+ dal_hw_translate_dce80_init(translate);
-+ return true;
-+ case DCE_VERSION_10_0:
-+ case DCE_VERSION_11_0:
-+ case DCE_VERSION_11_2:
-+ dal_hw_translate_dce110_init(translate);
-+ return true;
-+ default:
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h
-new file mode 100644
-index 0000000..3a7d89c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile
-new file mode 100644
-index 0000000..fd17af1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile
-@@ -0,0 +1,36 @@
-+#
-+# 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 = display_clock.o divider_range.o
-+
-+AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPU)
-+
-+###############################################################################
-+# DCE 80 family
-+###############################################################################
-+GPU_DCE80 = display_clock_dce80.o
-+
-+AMD_DAL_GPU_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpu/dce80/,$(GPU_DCE80))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE80)
-+
-+
-+###############################################################################
-+# DCE 110 family
-+###############################################################################
-+GPU_DCE110 = display_clock_dce110.o
-+
-+AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110)
-+
-+GPU_DCE112 = display_clock_dce112.o
-+
-+AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112)
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c
-new file mode 100644
-index 0000000..1bc39f1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c
-@@ -0,0 +1,1035 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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/bios_parser_interface.h"
-+#include "include/fixed32_32.h"
-+#include "include/logger_interface.h"
-+
-+#include "../divider_range.h"
-+
-+#include "display_clock_dce110.h"
-+#include "dc.h"
-+
-+#define FROM_DISPLAY_CLOCK(base) \
-+ container_of(base, struct display_clock_dce110, disp_clk_base)
-+
-+#define PSR_SET_WAITLOOP 0x31
-+
-+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 */
-+};
-+
-+union dce110_dmcu_psr_config_data_wait_loop_reg1 {
-+ struct {
-+ unsigned int waitLoop:16; /* [15:0] */
-+ unsigned int reserved:16; /* [31:16] */
-+ } bits;
-+ unsigned int u32All;
-+};
-+
-+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);
-+ struct dm_pp_power_level_change_request level_change_req = {
-+ DM_PP_POWER_LEVEL_INVALID};
-+
-+ if (clocks_state > dc->max_clks_state) {
-+ /*Requested state exceeds max supported state.*/
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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;
-+ }
-+
-+ switch (clocks_state) {
-+ case CLOCKS_STATE_ULTRA_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW;
-+ break;
-+ case CLOCKS_STATE_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_LOW;
-+ break;
-+ case CLOCKS_STATE_NOMINAL:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL;
-+ break;
-+ case CLOCKS_STATE_PERFORMANCE:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE;
-+ break;
-+ case CLOCKS_STATE_INVALID:
-+ default:
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "Requested state invalid state");
-+ return false;
-+ }
-+
-+ /* get max clock state from PPLIB */
-+ if (dm_pp_apply_power_level_change_request(
-+ base->ctx, &level_change_req))
-+ 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(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*/
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "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) {
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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 {
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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 dc_debug *debug = &disp_clk->disp_clk_base.ctx->dc->debug;
-+ struct dc_bios *bp = disp_clk->disp_clk_base.ctx->dc_bios;
-+ struct integrated_info info;
-+ struct firmware_info fw_info;
-+ uint32_t i;
-+ struct display_clock *base = &disp_clk->disp_clk_base;
-+
-+ memset(&info, 0, sizeof(struct integrated_info));
-+ memset(&fw_info, 0, sizeof(struct firmware_info));
-+
-+ if (bp->integrated_info)
-+ info = *bp->integrated_info;
-+
-+ disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq;
-+ if (disp_clk->dentist_vco_freq_khz == 0) {
-+ bp->funcs->get_firmware_info(bp, &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 (bp->integrated_info == NULL)
-+ 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 = false;
-+ if (!debug->disable_dfs_bypass)
-+ if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
-+ disp_clk->dfs_bypass_enabled = true;
-+
-+ disp_clk->use_max_disp_clk = debug->max_disp_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*/
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "%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 psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz)
-+{
-+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-+ unsigned int dmcu_wait_reg_ready_interval = 100;
-+ unsigned int regValue;
-+ uint32_t masterCmd;
-+ uint32_t masterComCntl;
-+ union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1;
-+
-+ /* waitDMCUReadyForCmd */
-+ do {
-+ dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-+ regValue = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG);
-+ dmcu_max_retry_on_wait_reg_ready--;
-+ } while
-+ /* expected value is 0, loop while not 0*/
-+ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
-+ dmcu_max_retry_on_wait_reg_ready > 0);
-+
-+ masterCmdData1.u32All = 0;
-+ masterCmdData1.bits.waitLoop = display_clk_khz / 1000 / 7;
-+ dm_write_reg(ctx, mmMASTER_COMM_DATA_REG1, masterCmdData1.u32All);
-+
-+ /* setDMCUParam_Cmd */
-+ masterCmd = dm_read_reg(ctx, mmMASTER_COMM_CMD_REG);
-+ set_reg_field_value(
-+ masterCmd,
-+ PSR_SET_WAITLOOP,
-+ MASTER_COMM_CMD_REG,
-+ MASTER_COMM_CMD_REG_BYTE0);
-+
-+ dm_write_reg(ctx, mmMASTER_COMM_CMD_REG, masterCmd);
-+
-+ /* notifyDMCUMsg */
-+ masterComCntl = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG);
-+ set_reg_field_value(
-+ masterComCntl,
-+ 1,
-+ MASTER_COMM_CNTL_REG,
-+ MASTER_COMM_INTERRUPT);
-+ dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl);
-+}
-+
-+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 = base->ctx->dc_bios;
-+
-+ /* Prepare to program display clock*/
-+ memset(&pxl_clk_params, 0, sizeof(pxl_clk_params));
-+
-+ /* Make sure requested clock isn't lower than minimum threshold*/
-+ if (requested_clk_khz > 0)
-+ requested_clk_khz = dm_max(requested_clk_khz,
-+ base->min_display_clk_threshold_khz);
-+
-+ 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;
-+
-+ psr_wait_loop(base->ctx, requested_clk_khz);
-+}
-+
-+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 display_clock *dc_base = &dc110->disp_clk_base;
-+ struct dc_bios *bp = ctx->dc_bios;
-+
-+ if (!dal_display_clock_construct_base(dc_base, ctx))
-+ return false;
-+
-+ dc_base->funcs = &funcs;
-+
-+ dc110->dfs_bypass_disp_clk = 0;
-+
-+ if (!display_clock_integrated_info_construct(dc110))
-+ dm_logger_write(dc_base->ctx->logger, LOG_WARNING,
-+ "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 =
-+ bp->funcs->get_ss_entry_number(bp,
-+ AS_SIGNAL_TYPE_GPU_PLL);
-+
-+ if (ss_info_num) {
-+ struct spread_spectrum_info info;
-+ enum bp_result result;
-+
-+ memset(&info, 0, sizeof(info));
-+
-+ result = bp->funcs->get_spread_spectrum_info(bp,
-+ 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 == BP_RESULT_OK &&
-+ 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 display_clock_dce110 *dc110;
-+
-+ dc110 = dm_alloc(sizeof(struct display_clock_dce110));
-+
-+ if (dc110 == NULL)
-+ return NULL;
-+
-+ if (dal_display_clock_dce110_construct(dc110, ctx))
-+ return &dc110->disp_clk_base;
-+
-+ dm_free(dc110);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h
-new file mode 100644
-index 0000000..0cdc7b5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c
-new file mode 100644
-index 0000000..9b7c975
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c
-@@ -0,0 +1,964 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+#include "include/bios_parser_interface.h"
-+#include "include/fixed32_32.h"
-+#include "include/logger_interface.h"
-+
-+#include "../divider_range.h"
-+
-+#include "display_clock_dce112.h"
-+
-+#define FROM_DISPLAY_CLOCK(base) \
-+ container_of(base, struct display_clock_dce112, 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 = 389189, .pixel_clk_khz = 346672 },
-+/*ClocksStateLow*/
-+{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 },
-+/*ClocksStateNominal*/
-+{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 },
-+/*ClocksStatePerformance*/
-+{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } };
-+
-+/* 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 dce112_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
-+ */
-+void dispclk_dce112_store_max_clocks_state(
-+ struct display_clock *base,
-+ enum clocks_state max_clocks_state)
-+{
-+ struct display_clock_dce112 *dc = DCLCK112_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;
-+ }
-+}
-+
-+enum clocks_state dispclk_dce112_get_min_clocks_state(
-+ struct display_clock *base)
-+{
-+ return base->cur_min_clks_state;
-+}
-+
-+bool dispclk_dce112_set_min_clocks_state(
-+ struct display_clock *base,
-+ enum clocks_state clocks_state)
-+{
-+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base);
-+ struct dm_pp_power_level_change_request level_change_req = {
-+ DM_PP_POWER_LEVEL_INVALID};
-+
-+ if (clocks_state > dc->max_clks_state) {
-+ /*Requested state exceeds max supported state.*/
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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;
-+ }
-+
-+ switch (clocks_state) {
-+ case CLOCKS_STATE_ULTRA_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW;
-+ break;
-+ case CLOCKS_STATE_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_LOW;
-+ break;
-+ case CLOCKS_STATE_NOMINAL:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL;
-+ break;
-+ case CLOCKS_STATE_PERFORMANCE:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE;
-+ break;
-+ case CLOCKS_STATE_INVALID:
-+ default:
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "Requested state invalid state");
-+ return false;
-+ }
-+
-+ /* get max clock state from PPLIB */
-+ if (dm_pp_apply_power_level_change_request(
-+ base->ctx, &level_change_req))
-+ 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_dce112 *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;
-+}
-+
-+void dispclk_dce112_destroy(struct display_clock **base)
-+{
-+ struct display_clock_dce112 *dc112;
-+
-+ dc112 = DCLCK112_FROM_BASE(*base);
-+
-+ dm_free(dc112);
-+
-+ *base = NULL;
-+}
-+
-+uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc)
-+{
-+ uint32_t clk = 0;
-+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc);
-+
-+ switch (disp_clk->max_clks_state) {
-+ case CLOCKS_STATE_ULTRA_LOW:
-+ clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_ULTRA_LOW)->
-+ display_clk_khz;
-+
-+ case CLOCKS_STATE_LOW:
-+ clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)->
-+ display_clk_khz;
-+ break;
-+
-+ case CLOCKS_STATE_NOMINAL:
-+ clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_NOMINAL)->
-+ display_clk_khz;
-+ break;
-+
-+ case CLOCKS_STATE_PERFORMANCE:
-+ clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_PERFORMANCE)->
-+ display_clk_khz;
-+ break;
-+
-+ case CLOCKS_STATE_INVALID:
-+ default:
-+ /*Invalid Clocks State*/
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "Invalid clock state");
-+ /* just return the display engine clock for
-+ * lowest supported state*/
-+ clk = (disp_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_dce112 *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_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base);
-+ uint32_t max_clk_khz = dispclk_dce112_get_validation_clock(base);
-+ bool panning_allowed = false; /* TODO: receive this value from AS */
-+
-+ if (params == NULL) {
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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 {
-+ dm_logger_write(base->ctx->logger, LOG_WARNING,
-+ "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;
-+}
-+
-+uint32_t dispclk_dce112_calculate_min_clock(
-+ struct display_clock *base,
-+ uint32_t path_num,
-+ struct min_clock_params *params)
-+{
-+ uint32_t i;
-+ uint32_t validation_clk_khz =
-+ dispclk_dce112_get_validation_clock(base);
-+ uint32_t min_clk_khz = validation_clk_khz;
-+ uint32_t max_clk_khz = 0;
-+ struct display_clock_dce112 *dc = DCLCK112_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 = dispclk_dce112_get_validation_clock(base);
-+
-+ return min_clk_khz;
-+}
-+
-+static bool display_clock_integrated_info_construct(
-+ struct display_clock_dce112 *disp_clk)
-+{
-+ struct integrated_info info;
-+ uint32_t i;
-+ struct display_clock *base = &disp_clk->disp_clk_base;
-+
-+ memset(&info, 0, sizeof(struct integrated_info));
-+
-+ disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq;
-+ if (disp_clk->dentist_vco_freq_khz == 0)
-+ disp_clk->dentist_vco_freq_khz = 3600000;
-+
-+ disp_clk->crystal_freq_khz = 100000;
-+
-+ base->min_display_clk_threshold_khz =
-+ disp_clk->dentist_vco_freq_khz / 64;
-+
-+ /*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) {
-+ (disp_clk->max_clks_by_state + clk_state)->
-+ display_clk_khz =
-+ info.disp_clk_voltage[i].max_supported_clk;
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+static uint32_t get_clock(struct display_clock *dc)
-+{
-+ uint32_t disp_clock = dispclk_dce112_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_dce112 *disp_clk = DCLCK112_FROM_BASE(dc);
-+
-+ /* 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;
-+}
-+
-+enum clocks_state dispclk_dce112_get_required_clocks_state(
-+ struct display_clock *dc,
-+ struct state_dependent_clocks *req_clocks)
-+{
-+ int32_t i;
-+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc);
-+ enum clocks_state low_req_clk = disp_clk->max_clks_state;
-+
-+ if (!req_clocks) {
-+ /* NULL pointer*/
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "%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 <=
-+ (disp_clk->max_clks_by_state + i)->
-+ display_clk_khz) &&
-+ (req_clocks->pixel_clk_khz <=
-+ (disp_clk->max_clks_by_state + i)->
-+ pixel_clk_khz))
-+ low_req_clk = i;
-+ }
-+ return low_req_clk;
-+}
-+
-+void dispclk_dce112_set_clock(
-+ struct display_clock *base,
-+ uint32_t requested_clk_khz)
-+{
-+ struct bp_set_dce_clock_parameters dce_clk_params;
-+ struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base);
-+ struct dc_bios *bp = base->ctx->dc_bios;
-+
-+ /* Prepare to program display clock*/
-+ memset(&dce_clk_params, 0, sizeof(dce_clk_params));
-+
-+ /* Make sure requested clock isn't lower than minimum threshold*/
-+ if (requested_clk_khz > 0)
-+ requested_clk_khz = dm_max(requested_clk_khz,
-+ base->min_display_clk_threshold_khz);
-+
-+ dce_clk_params.target_clock_frequency = requested_clk_khz;
-+ dce_clk_params.pll_id = dc->disp_clk_base.id;
-+ dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK;
-+
-+ bp->funcs->set_dce_clock(bp, &dce_clk_params);
-+
-+ /* 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;
-+
-+ /*Program DP ref Clock*/
-+ /*VBIOS will determine DPREFCLK frequency, so we don't set it*/
-+ dce_clk_params.target_clock_frequency = 0;
-+ dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK;
-+ dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK =
-+ (dce_clk_params.pll_id ==
-+ CLOCK_SOURCE_COMBO_DISPLAY_PLL0);
-+
-+ bp->funcs->set_dce_clock(bp, &dce_clk_params);
-+}
-+
-+void dispclk_dce112_set_clock_state(
-+ struct display_clock *dc,
-+ struct display_clock_state clk_state)
-+{
-+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc);
-+
-+ disp_clk->clock_state = clk_state;
-+}
-+
-+struct display_clock_state dispclk_dce112_get_clock_state(
-+ struct display_clock *dc)
-+{
-+ struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc);
-+
-+ return disp_clk->clock_state;
-+}
-+
-+uint32_t dispclk_dce112_get_dfs_bypass_threshold(
-+ struct display_clock *dc)
-+{
-+ return dce112_DFS_BYPASS_THRESHOLD_KHZ;
-+}
-+
-+static const struct display_clock_funcs funcs = {
-+ .destroy = dispclk_dce112_destroy,
-+ .calculate_min_clock = dispclk_dce112_calculate_min_clock,
-+ .get_clock = get_clock,
-+ .get_clock_state = dispclk_dce112_get_clock_state,
-+ .get_dfs_bypass_threshold = dispclk_dce112_get_dfs_bypass_threshold,
-+ .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency,
-+ .get_min_clocks_state = dispclk_dce112_get_min_clocks_state,
-+ .get_required_clocks_state = dispclk_dce112_get_required_clocks_state,
-+ .get_validation_clock = dispclk_dce112_get_validation_clock,
-+ .set_clock = dispclk_dce112_set_clock,
-+ .set_clock_state = dispclk_dce112_set_clock_state,
-+ .set_dp_ref_clock_source = NULL,
-+ .set_min_clocks_state = dispclk_dce112_set_min_clocks_state,
-+ .store_max_clocks_state = dispclk_dce112_store_max_clocks_state,
-+ .validate = NULL,
-+};
-+
-+bool dal_display_clock_dce112_construct(
-+ struct display_clock_dce112 *dc112,
-+ struct dc_context *ctx)
-+{
-+ struct display_clock *dc_base = &dc112->disp_clk_base;
-+
-+ /*if (NULL == as)
-+ return false;*/
-+
-+ if (!dal_display_clock_construct_base(dc_base, ctx))
-+ return false;
-+
-+ dc_base->funcs = &funcs;
-+
-+ dc112->dfs_bypass_disp_clk = 0;
-+
-+ if (!display_clock_integrated_info_construct(dc112))
-+ dm_logger_write(dc_base->ctx->logger, LOG_WARNING,
-+ "Cannot obtain VBIOS integrated info\n");
-+
-+ dc112->gpu_pll_ss_percentage = 0;
-+ dc112->gpu_pll_ss_divider = 1000;
-+ dc112->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_dce112::StoreMaxClocksState(). This call will come in
-+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/
-+ dc112->max_clks_state = CLOCKS_STATE_NOMINAL;
-+
-+ dc112->disp_clk_base.min_display_clk_threshold_khz =
-+ dc112->crystal_freq_khz;
-+
-+ if (dc112->disp_clk_base.min_display_clk_threshold_khz <
-+ (dc112->dentist_vco_freq_khz / 62))
-+ dc112->disp_clk_base.min_display_clk_threshold_khz =
-+ (dc112->dentist_vco_freq_khz / 62);
-+
-+ 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 =
-+ ctx->dc_bios->funcs->
-+ get_ss_entry_number(ctx->dc_bios, AS_SIGNAL_TYPE_GPU_PLL);
-+
-+ if (ss_info_num) {
-+ struct spread_spectrum_info info;
-+ bool result;
-+
-+ memset(&info, 0, sizeof(info));
-+
-+ result =
-+ (BP_RESULT_OK == ctx->dc_bios->funcs->
-+ get_spread_spectrum_info(ctx->dc_bios,
-+ AS_SIGNAL_TYPE_GPU_PLL, 0, &info)) ? true : false;
-+
-+
-+ /* 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) {
-+ dc112->ss_on_gpu_pll = true;
-+ dc112->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 */
-+ dc112->gpu_pll_ss_percentage =
-+ info.spread_spectrum_percentage;
-+ }
-+ }
-+
-+ }
-+ }
-+
-+ dc112->use_max_disp_clk = true;
-+ dc112->max_clks_by_state = max_clks_by_state;
-+
-+ return true;
-+}
-+
-+/*****************************************************************************
-+ * public functions
-+ *****************************************************************************/
-+
-+struct display_clock *dal_display_clock_dce112_create(
-+ struct dc_context *ctx)
-+{
-+ struct display_clock_dce112 *dc112;
-+
-+ dc112 = dm_alloc(sizeof(struct display_clock_dce112));
-+
-+ if (dc112 == NULL)
-+ return NULL;
-+
-+ if (dal_display_clock_dce112_construct(dc112, ctx))
-+ return &dc112->disp_clk_base;
-+
-+ dm_free(dc112);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h
-new file mode 100644
-index 0000000..937e179
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h
-@@ -0,0 +1,114 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE112_H__
-+#define __DAL_DISPLAY_CLOCK_DCE112_H__
-+
-+#include "gpu/display_clock.h"
-+
-+struct display_clock_dce112 {
-+ struct display_clock disp_clk_base;
-+ /* Max display block clocks state*/
-+ enum clocks_state max_clks_state;
-+ bool use_max_disp_clk;
-+ uint32_t crystal_freq_khz;
-+ 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;
-+ struct state_dependent_clocks *max_clks_by_state;
-+
-+};
-+
-+#define DCLCK112_FROM_BASE(dc_base) \
-+ container_of(dc_base, struct display_clock_dce112, disp_clk_base)
-+
-+/* 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*/
-+};
-+
-+/* 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.*/
-+};
-+
-+bool dal_display_clock_dce112_construct(
-+ struct display_clock_dce112 *dc112,
-+ struct dc_context *ctx);
-+
-+void dispclk_dce112_destroy(struct display_clock **base);
-+
-+uint32_t dispclk_dce112_calculate_min_clock(
-+ struct display_clock *base,
-+ uint32_t path_num,
-+ struct min_clock_params *params);
-+
-+struct display_clock_state dispclk_dce112_get_clock_state(
-+ struct display_clock *dc);
-+
-+uint32_t dispclk_dce112_get_dfs_bypass_threshold(
-+ struct display_clock *dc);
-+
-+enum clocks_state dispclk_dce112_get_min_clocks_state(
-+ struct display_clock *base);
-+
-+enum clocks_state dispclk_dce112_get_required_clocks_state(
-+ struct display_clock *dc,
-+ struct state_dependent_clocks *req_clocks);
-+
-+uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc);
-+
-+void dispclk_dce112_set_clock(
-+ struct display_clock *base,
-+ uint32_t requested_clk_khz);
-+
-+void dispclk_dce112_set_clock_state(
-+ struct display_clock *dc,
-+ struct display_clock_state clk_state);
-+
-+bool dispclk_dce112_set_min_clocks_state(
-+ struct display_clock *base,
-+ enum clocks_state clocks_state);
-+
-+void dispclk_dce112_store_max_clocks_state(
-+ struct display_clock *base,
-+ enum clocks_state max_clocks_state);
-+
-+#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c
-new file mode 100644
-index 0000000..eedcfd6
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c
-@@ -0,0 +1,934 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+#include "include/bios_parser_interface.h"
-+#include "include/fixed32_32.h"
-+#include "include/logger_interface.h"
-+
-+#include "../divider_range.h"
-+#include "display_clock_dce80.h"
-+#include "dc.h"
-+
-+#define DCE80_DFS_BYPASS_THRESHOLD_KHZ 100000
-+
-+/* Max clock values for each state indexed by "enum clocks_state": */
-+static struct state_dependent_clocks max_clks_by_state[] = {
-+/* ClocksStateInvalid - should not be used */
-+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-+/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */
-+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-+/* ClocksStateLow */
-+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000},
-+/* ClocksStateNominal */
-+{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
-+/* ClocksStatePerformance */
-+{ .display_clk_khz = 600000, .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.*/
-+};
-+
-+/* 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 */
-+};
-+
-+/* 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*/
-+};
-+
-+static struct divider_range divider_ranges[DIVIDER_RANGE_MAX];
-+
-+#define FROM_DISPLAY_CLOCK(base) \
-+ container_of(base, struct display_clock_dce80, disp_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 uint32_t get_scaler_efficiency(struct min_clock_params *params)
-+{
-+ uint32_t scaler_efficiency = 3;
-+
-+ switch (params->scaler_efficiency) {
-+ case V_SCALER_EFFICIENCY_LB18BPP:
-+ case V_SCALER_EFFICIENCY_LB24BPP:
-+ scaler_efficiency = 4;
-+ break;
-+
-+ case V_SCALER_EFFICIENCY_LB30BPP:
-+ case V_SCALER_EFFICIENCY_LB36BPP:
-+ scaler_efficiency = 3;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ return scaler_efficiency;
-+}
-+
-+static uint32_t get_actual_required_display_clk(
-+ struct display_clock_dce80 *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(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 get_validation_clock(struct display_clock *dc)
-+{
-+ uint32_t clk = 0;
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(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*/
-+ BREAK_TO_DEBUGGER();
-+ /* 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 uint32_t calc_single_display_min_clks(
-+ struct display_clock *base,
-+ struct min_clock_params *params,
-+ bool set_clk)
-+{
-+ struct fixed32_32 h_scale = dal_fixed32_32_from_int(1);
-+ struct fixed32_32 v_scale = dal_fixed32_32_from_int(1);
-+ uint32_t pix_clk_khz = params->requested_pixel_clock;
-+ uint32_t line_total = params->timing_info.h_total;
-+ uint32_t max_clk_khz = get_validation_clock(base);
-+ struct fixed32_32 deep_color_factor = get_deep_color_factor(params);
-+ uint32_t scaler_efficiency = get_scaler_efficiency(params);
-+ struct fixed32_32 v_filter_init;
-+ uint32_t v_filter_init_trunc;
-+ struct fixed32_32 v_filter_init_ceil;
-+ struct fixed32_32 src_lines_per_dst_line;
-+ uint32_t src_wdth_rnd_to_chunks;
-+ struct fixed32_32 scaling_coeff;
-+ struct fixed32_32 fx_disp_clk_khz;
-+ struct fixed32_32 fx_alt_disp_clk_khz;
-+ uint32_t disp_clk_khz;
-+ uint32_t alt_disp_clk_khz;
-+ struct display_clock_dce80 *dc = FROM_DISPLAY_CLOCK(base);
-+
-+ if (0 != params->dest_view.height && 0 != params->dest_view.width) {
-+
-+ h_scale = dal_fixed32_32_from_fraction(
-+ params->source_view.width,
-+ params->dest_view.width);
-+ v_scale = dal_fixed32_32_from_fraction(
-+ params->source_view.height,
-+ params->dest_view.height);
-+ }
-+
-+ v_filter_init = dal_fixed32_32_from_fraction(
-+ params->scaling_info.v_taps, 2u);
-+ v_filter_init = dal_fixed32_32_add(v_filter_init,
-+ dal_fixed32_32_div_int(v_scale, 2));
-+ v_filter_init = dal_fixed32_32_add(v_filter_init,
-+ dal_fixed32_32_from_fraction(15, 10));
-+
-+ 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);
-+ v_filter_init_ceil = dal_fixed32_32_div_int(v_filter_init_ceil, 3);
-+ v_filter_init_ceil = dal_fixed32_32_from_int(
-+ dal_fixed32_32_ceil(v_filter_init_ceil));
-+
-+ src_lines_per_dst_line = dal_fixed32_32_max(
-+ dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_scale)),
-+ v_filter_init_ceil);
-+
-+ src_wdth_rnd_to_chunks =
-+ ((params->source_view.width - 1) / 128) * 128 + 256;
-+
-+ scaling_coeff = dal_fixed32_32_max(
-+ dal_fixed32_32_from_fraction(params->scaling_info.h_taps, 4),
-+ dal_fixed32_32_mul(
-+ dal_fixed32_32_from_fraction(
-+ params->scaling_info.v_taps,
-+ scaler_efficiency),
-+ h_scale));
-+
-+ scaling_coeff = dal_fixed32_32_max(scaling_coeff, h_scale);
-+
-+ fx_disp_clk_khz = dal_fixed32_32_mul(
-+ scaling_coeff, dal_fixed32_32_from_fraction(11, 10));
-+ if (0 != line_total) {
-+ struct fixed32_32 d_clk = dal_fixed32_32_mul_int(
-+ src_lines_per_dst_line, src_wdth_rnd_to_chunks);
-+ d_clk = dal_fixed32_32_div_int(d_clk, line_total);
-+ d_clk = dal_fixed32_32_mul(d_clk,
-+ dal_fixed32_32_from_fraction(11, 10));
-+ fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, d_clk);
-+ }
-+
-+ fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz,
-+ dal_fixed32_32_mul(deep_color_factor,
-+ dal_fixed32_32_from_fraction(11, 10)));
-+
-+ fx_disp_clk_khz = dal_fixed32_32_mul_int(fx_disp_clk_khz, pix_clk_khz);
-+ fx_disp_clk_khz = dal_fixed32_32_mul(fx_disp_clk_khz,
-+ dal_fixed32_32_from_fraction(1005, 1000));
-+
-+ fx_alt_disp_clk_khz = scaling_coeff;
-+
-+ if (0 != line_total) {
-+ struct fixed32_32 d_clk = dal_fixed32_32_mul_int(
-+ src_lines_per_dst_line, src_wdth_rnd_to_chunks);
-+ d_clk = dal_fixed32_32_div_int(d_clk, line_total);
-+ d_clk = dal_fixed32_32_mul(d_clk,
-+ dal_fixed32_32_from_fraction(105, 100));
-+ fx_alt_disp_clk_khz = dal_fixed32_32_max(
-+ fx_alt_disp_clk_khz, d_clk);
-+ }
-+ fx_alt_disp_clk_khz = dal_fixed32_32_max(
-+ fx_alt_disp_clk_khz, fx_alt_disp_clk_khz);
-+
-+ fx_alt_disp_clk_khz = dal_fixed32_32_mul_int(
-+ fx_alt_disp_clk_khz, pix_clk_khz);
-+
-+ /* convert to integer*/
-+ disp_clk_khz = dal_fixed32_32_floor(fx_disp_clk_khz);
-+ alt_disp_clk_khz = dal_fixed32_32_floor(fx_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(
-+ dc, disp_clk_khz);
-+ alt_disp_clk_khz = get_actual_required_display_clk(
-+ dc, alt_disp_clk_khz);
-+ }
-+
-+ if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz))
-+ disp_clk_khz = alt_disp_clk_khz;
-+
-+ return disp_clk_khz;
-+
-+}
-+
-+static uint32_t calc_cursor_bw_for_min_clks(struct min_clock_params *params)
-+{
-+
-+ struct fixed32_32 v_scale = dal_fixed32_32_from_int(1);
-+ struct fixed32_32 v_filter_ceiling;
-+ struct fixed32_32 src_lines_per_dst_line;
-+ struct fixed32_32 cursor_bw;
-+
-+ /* DCE8 Mode Support and Mode Set Architecture Specification Rev 1.3
-+ 6.3.3 Cursor data Throughput requirement on DISPCLK
-+ The MCIF to DCP cursor data return throughput is one pixel per DISPCLK
-+ shared among the display heads.
-+ If (Total Cursor Bandwidth in pixels for All heads> DISPCLK)
-+ The mode is not supported
-+ Cursor Bandwidth in Pixels = Cursor Width *
-+ (SourceLinesPerDestinationLine / Line Time)
-+ Assuming that Cursor Width = 128
-+ */
-+ /*In the hardware doc they mention an Interlace Factor
-+ It is not used here because we have already used it when
-+ calculating destination view*/
-+ if (0 != params->dest_view.height)
-+ v_scale = dal_fixed32_32_from_fraction(
-+ params->source_view.height,
-+ params->dest_view.height);
-+
-+ {
-+ /*Do: Vertical Filter Init = 0.5 + VTAPS/2 + VSR/2 * Interlace Factor*/
-+ /*Interlace Factor is included in verticalScaleRatio*/
-+ struct fixed32_32 v_filter = dal_fixed32_32_add(
-+ dal_fixed32_32_from_fraction(params->scaling_info.v_taps, 2),
-+ dal_fixed32_32_div_int(v_scale, 2));
-+ /*Do : Ceiling (Vertical Filter Init, 2)/3 )*/
-+ v_filter_ceiling = dal_fixed32_32_div_int(v_filter, 2);
-+ v_filter_ceiling = dal_fixed32_32_mul_int(
-+ dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_filter_ceiling)),
-+ 2);
-+ v_filter_ceiling = dal_fixed32_32_div_int(v_filter_ceiling, 3);
-+ }
-+ /*Do : MAX( CeilCeiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/
-+ /*Do : SourceLinesPerDestinationLine =
-+ * MAX( Ceiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/
-+ src_lines_per_dst_line = dal_fixed32_32_max(v_scale, v_filter_ceiling);
-+
-+ if ((params->requested_pixel_clock != 0) &&
-+ (params->timing_info.h_total != 0)) {
-+ /* pixelClock is in units of KHz. Calc lineTime in us*/
-+ struct fixed32_32 inv_line_time = dal_fixed32_32_from_fraction(
-+ params->requested_pixel_clock,
-+ params->timing_info.h_total);
-+ cursor_bw = dal_fixed32_32_mul(
-+ dal_fixed32_32_mul_int(inv_line_time, 128),
-+ src_lines_per_dst_line);
-+ }
-+
-+ /* convert to integer*/
-+ return dal_fixed32_32_floor(cursor_bw);
-+}
-+
-+static bool validate(
-+ struct display_clock *dc,
-+ struct min_clock_params *params)
-+{
-+ uint32_t max_clk_khz = get_validation_clock(dc);
-+ uint32_t req_clk_khz;
-+
-+ if (params == NULL)
-+ return false;
-+
-+ req_clk_khz = calc_single_display_min_clks(dc, params, false);
-+
-+ return (req_clk_khz <= max_clk_khz);
-+}
-+
-+static uint32_t calculate_min_clock(
-+ struct display_clock *dc,
-+ uint32_t path_num,
-+ struct min_clock_params *params)
-+{
-+ uint32_t i;
-+ uint32_t validation_clk_khz = get_validation_clock(dc);
-+ uint32_t min_clk_khz = validation_clk_khz;
-+ uint32_t max_clk_khz = 0;
-+ uint32_t total_cursor_bw = 0;
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ if (disp_clk->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(
-+ dc, params, true);
-+
-+ /* update the max required clock found*/
-+ if (disp_clk_khz > max_clk_khz)
-+ max_clk_khz = disp_clk_khz;
-+
-+ disp_clk_khz = calc_cursor_bw_for_min_clks(params);
-+
-+ total_cursor_bw += disp_clk_khz;
-+
-+ params++;
-+
-+ }
-+ }
-+
-+ max_clk_khz = (total_cursor_bw > max_clk_khz) ? total_cursor_bw :
-+ max_clk_khz;
-+
-+ min_clk_khz = max_clk_khz;
-+
-+ /*"Cursor data Throughput requirement on DISPCLK is now a factor,
-+ * need to change the code */
-+ ASSERT(total_cursor_bw < validation_clk_khz);
-+
-+ if (min_clk_khz > validation_clk_khz)
-+ min_clk_khz = validation_clk_khz;
-+ else if (min_clk_khz < dc->min_display_clk_threshold_khz)
-+ min_clk_khz = dc->min_display_clk_threshold_khz;
-+
-+ return min_clk_khz;
-+}
-+
-+static void set_clock(
-+ struct display_clock *dc,
-+ uint32_t requested_clk_khz)
-+{
-+ struct bp_pixel_clock_parameters pxl_clk_params;
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+ struct dc_bios *bp = dc->ctx->dc_bios;
-+
-+ /* Prepare to program display clock*/
-+ memset(&pxl_clk_params, 0, sizeof(pxl_clk_params));
-+
-+ pxl_clk_params.target_pixel_clock = requested_clk_khz;
-+ pxl_clk_params.pll_id = dc->id;
-+
-+ bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
-+
-+ if (disp_clk->dfs_bypass_enabled) {
-+
-+ /* Cache the fixed display clock*/
-+ disp_clk->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)
-+ disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL;
-+}
-+
-+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_dce80 *disp_clk = FROM_DISPLAY_CLOCK(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 void set_clock_state(
-+ struct display_clock *dc,
-+ struct display_clock_state clk_state)
-+{
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ disp_clk->clock_state = clk_state;
-+}
-+static struct display_clock_state get_clock_state(
-+ struct display_clock *dc)
-+{
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ return disp_clk->clock_state;
-+}
-+
-+static enum clocks_state get_min_clocks_state(struct display_clock *dc)
-+{
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ return disp_clk->cur_min_clks_state;
-+}
-+
-+static enum clocks_state get_required_clocks_state
-+ (struct display_clock *dc,
-+ struct state_dependent_clocks *req_clocks)
-+{
-+ int32_t i;
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+ enum clocks_state low_req_clk = disp_clk->max_clks_state;
-+
-+ if (!req_clocks) {
-+ /* NULL pointer*/
-+ BREAK_TO_DEBUGGER();
-+ 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 bool set_min_clocks_state(
-+ struct display_clock *dc,
-+ enum clocks_state clocks_state)
-+{
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ struct dm_pp_power_level_change_request level_change_req = {
-+ DM_PP_POWER_LEVEL_INVALID};
-+
-+ if (clocks_state > disp_clk->max_clks_state) {
-+ /*Requested state exceeds max supported state.*/
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "Requested state exceeds max supported state");
-+ return false;
-+ } else if (clocks_state == dc->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;
-+ }
-+
-+ switch (clocks_state) {
-+ case CLOCKS_STATE_ULTRA_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW;
-+ break;
-+ case CLOCKS_STATE_LOW:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_LOW;
-+ break;
-+ case CLOCKS_STATE_NOMINAL:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL;
-+ break;
-+ case CLOCKS_STATE_PERFORMANCE:
-+ level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE;
-+ break;
-+ case CLOCKS_STATE_INVALID:
-+ default:
-+ dm_logger_write(dc->ctx->logger, LOG_WARNING,
-+ "Requested state invalid state");
-+ return false;
-+ }
-+
-+ /* get max clock state from PPLIB */
-+ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req))
-+ dc->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_dce80 *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 store_max_clocks_state(
-+ struct display_clock *dc,
-+ enum clocks_state max_clocks_state)
-+{
-+ struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc);
-+
-+ switch (max_clocks_state) {
-+ case CLOCKS_STATE_LOW:
-+ case CLOCKS_STATE_NOMINAL:
-+ case CLOCKS_STATE_PERFORMANCE:
-+ case CLOCKS_STATE_ULTRA_LOW:
-+ disp_clk->max_clks_state = max_clocks_state;
-+ break;
-+
-+ case CLOCKS_STATE_INVALID:
-+ default:
-+ /*Invalid Clocks State!*/
-+ BREAK_TO_DEBUGGER();
-+ break;
-+ }
-+}
-+
-+static void display_clock_ss_construct(
-+ struct display_clock_dce80 *disp_clk)
-+{
-+ struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios;
-+ uint32_t ss_entry_num = bp->funcs->get_ss_entry_number(bp,
-+ AS_SIGNAL_TYPE_GPU_PLL);
-+
-+ /*Read SS Info from VBIOS SS Info table for DP Reference Clock spread.*/
-+ if (ss_entry_num > 0) {/* Should be only one entry */
-+ struct spread_spectrum_info ss_info;
-+ enum bp_result res;
-+
-+ memset(&ss_info, 0, sizeof(struct spread_spectrum_info));
-+
-+ res = bp->funcs->get_spread_spectrum_info(bp,
-+ AS_SIGNAL_TYPE_GPU_PLL, 0, &ss_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 (res == BP_RESULT_OK && ss_info.spread_spectrum_percentage != 0) {
-+ disp_clk->ss_on_gpu_pll = true;
-+ disp_clk->gpu_pll_ss_divider =
-+ ss_info.spread_percentage_divider;
-+ if (ss_info.type.CENTER_MODE == 0)
-+ /* Currently we need only SS
-+ * percentage for down-spread*/
-+ disp_clk->gpu_pll_ss_percentage =
-+ ss_info.spread_spectrum_percentage;
-+ }
-+ }
-+}
-+
-+static bool display_clock_integrated_info_construct(
-+ struct display_clock_dce80 *disp_clk)
-+{
-+ struct dc_debug *debug = &disp_clk->disp_clk.ctx->dc->debug;
-+ struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios;
-+ struct integrated_info info = { { { 0 } } };
-+ struct firmware_info fw_info = { { 0 } };
-+ uint32_t i;
-+
-+ if (bp->integrated_info)
-+ info = *bp->integrated_info;
-+
-+ disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq;
-+ if (disp_clk->dentist_vco_freq_khz == 0) {
-+ bp->funcs->get_firmware_info(bp, &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;
-+ }
-+ disp_clk->disp_clk.min_display_clk_threshold_khz =
-+ disp_clk->dentist_vco_freq_khz / 64;
-+
-+ /* TODO: initialise disp_clk->dfs_bypass_disp_clk */
-+
-+ /*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 = false;
-+ if (!debug->disable_dfs_bypass)
-+ if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
-+ disp_clk->dfs_bypass_enabled = true;
-+
-+ disp_clk->use_max_disp_clk = debug->max_disp_clk;
-+
-+ return true;
-+}
-+
-+static uint32_t get_dfs_bypass_threshold(struct display_clock *dc)
-+{
-+ return DCE80_DFS_BYPASS_THRESHOLD_KHZ;
-+}
-+
-+static void destroy(struct display_clock **dc)
-+{
-+ struct display_clock_dce80 *disp_clk;
-+
-+ disp_clk = FROM_DISPLAY_CLOCK(*dc);
-+ dm_free(disp_clk);
-+ *dc = NULL;
-+}
-+
-+static const struct display_clock_funcs funcs = {
-+ .calculate_min_clock = calculate_min_clock,
-+ .destroy = destroy,
-+ .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 =
-+ dal_display_clock_base_set_dp_ref_clock_source,
-+ .set_min_clocks_state = set_min_clocks_state,
-+ .store_max_clocks_state = store_max_clocks_state,
-+ .validate = validate,
-+};
-+
-+static bool display_clock_construct(
-+ struct dc_context *ctx,
-+ struct display_clock_dce80 *disp_clk)
-+{
-+ struct display_clock *dc_base = &disp_clk->disp_clk;
-+
-+ if (!dal_display_clock_construct_base(dc_base, ctx))
-+ return false;
-+
-+ dc_base->funcs = &funcs;
-+ /*
-+ * set_dp_ref_clock_source
-+ * set_clock_state
-+ * get_clock_state
-+ * get_dfs_bypass_threshold
-+ */
-+
-+ disp_clk->gpu_pll_ss_percentage = 0;
-+ disp_clk->gpu_pll_ss_divider = 1000;
-+ disp_clk->ss_on_gpu_pll = false;
-+ disp_clk->dfs_bypass_enabled = false;
-+ disp_clk->dfs_bypass_disp_clk = 0;
-+ disp_clk->use_max_disp_clk = true;/* false will hang the system! */
-+
-+ disp_clk->disp_clk.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_Dce50::StoreMaxClocksState(). This call will come in
-+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/
-+ disp_clk->max_clks_state = CLOCKS_STATE_NOMINAL;
-+/* 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.*/
-+ disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID;
-+
-+ display_clock_ss_construct(disp_clk);
-+
-+ if (!display_clock_integrated_info_construct(disp_clk)) {
-+ dm_logger_write(dc_base->ctx->logger, LOG_WARNING,
-+ "Cannot obtain VBIOS integrated info");
-+ }
-+
-+ 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);
-+ return true;
-+}
-+
-+struct display_clock *dal_display_clock_dce80_create(
-+ struct dc_context *ctx)
-+{
-+ struct display_clock_dce80 *disp_clk;
-+
-+ disp_clk = dm_alloc(sizeof(struct display_clock_dce80));
-+
-+ if (disp_clk == NULL)
-+ return NULL;
-+
-+ if (display_clock_construct(ctx, disp_clk))
-+ return &disp_clk->disp_clk;
-+
-+ dm_free(disp_clk);
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h
-new file mode 100644
-index 0000000..944dd03
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.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_DISPLAY_CLOCK_DCE80_H__
-+#define __DAL_DISPLAY_CLOCK_DCE80_H__
-+
-+#include "gpu/display_clock.h"
-+
-+struct display_clock_dce80 {
-+ struct display_clock disp_clk;
-+ /* DFS input - GPUPLL VCO frequency - from VBIOS Firmware info. */
-+ uint32_t dentist_vco_freq_khz;
-+ /* 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;
-+ /* Max display block clocks state*/
-+ enum clocks_state max_clks_state;
-+ /* Current minimum display block clocks state*/
-+ enum clocks_state cur_min_clks_state;
-+ /* DFS-bypass feature variable
-+ Cache the status of DFS-bypass feature*/
-+ bool dfs_bypass_enabled;
-+ /* 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;
-+ bool use_max_disp_clk;
-+ struct display_clock_state clock_state;
-+};
-+
-+struct display_clock *dal_display_clock_dce80_create(
-+ struct dc_context *ctx);
-+
-+#endif /* __DAL_DISPLAY_CLOCK_DCE80_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c
-new file mode 100644
-index 0000000..bcc0a51
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c
-@@ -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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "display_clock.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)
-+{
-+ base->ctx = ctx;
-+ base->id = CLOCK_SOURCE_ID_DCPLL;
-+ base->min_display_clk_threshold_khz = 0;
-+
-+/* 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);
-+}
-+
-+bool dal_display_clock_get_min_clocks_state(
-+ struct display_clock *disp_clk,
-+ enum clocks_state *clocks_state)
-+{
-+ if (!disp_clk->funcs->get_min_clocks_state)
-+ return false;
-+
-+ *clocks_state = disp_clk->funcs->get_min_clocks_state(disp_clk);
-+ return true;
-+}
-+
-+bool dal_display_clock_get_required_clocks_state(
-+ struct display_clock *disp_clk,
-+ struct state_dependent_clocks *req_clocks,
-+ enum clocks_state *clocks_state)
-+{
-+ if (!disp_clk->funcs->get_required_clocks_state)
-+ return false;
-+
-+ *clocks_state = disp_clk->funcs->get_required_clocks_state(
-+ disp_clk, req_clocks);
-+ return true;
-+}
-+
-+bool dal_display_clock_set_min_clocks_state(
-+ struct display_clock *disp_clk,
-+ enum clocks_state clocks_state)
-+{
-+ if (!disp_clk->funcs->set_min_clocks_state)
-+ return false;
-+
-+ disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state);
-+ return true;
-+}
-+
-+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/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h
-new file mode 100644
-index 0000000..663580d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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;
-+
-+ 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);
-+
-+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk);
-+
-+void dal_display_clock_store_max_clocks_state(
-+ struct display_clock *disp_clk,
-+ enum clocks_state max_clocks_state);
-+
-+
-+#endif /* __DAL_DISPLAY_CLOCK_H__*/
-diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c
-new file mode 100644
-index 0000000..59d4400
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h
-new file mode 100644
-index 0000000..e53522f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.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_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__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile
-new file mode 100644
-index 0000000..83dfc43
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile
-@@ -0,0 +1,58 @@
-+#
-+# 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_DISPLAY_FILES += $(AMD_DAL_I2CAUX)
-+
-+###############################################################################
-+# DCE 8x family
-+###############################################################################
-+I2CAUX_DCE80 = i2caux_dce80.o i2c_hw_engine_dce80.o \
-+ i2c_sw_engine_dce80.o
-+
-+AMD_DAL_I2CAUX_DCE80 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce80/,$(I2CAUX_DCE80))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE80)
-+
-+###############################################################################
-+# DCE 100 family
-+###############################################################################
-+I2CAUX_DCE100 = i2caux_dce100.o
-+
-+AMD_DAL_I2CAUX_DCE100 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce100/,$(I2CAUX_DCE100))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE100)
-+
-+###############################################################################
-+# DCE 110 family
-+###############################################################################
-+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_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE110)
-+
-+###############################################################################
-+# DCE 112 family
-+###############################################################################
-+I2CAUX_DCE112 = i2caux_dce112.o
-+
-+AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE112))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112)
-+
-+###############################################################################
-+# Diagnostics on FPGA
-+###############################################################################
-+I2CAUX_DIAG = i2caux_diag.o
-+
-+AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DIAG)
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
-new file mode 100644
-index 0000000..667660f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+ uint32_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
-+ udelay(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 {
-+ 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)
-+ msleep(engine->delay);
-+ } while (ctx.operation_succeeded && !ctx.transaction_complete);
-+
-+ return ctx.operation_succeeded;
-+}
-+
-+struct write_command_context {
-+ bool mot;
-+
-+ uint8_t *buffer;
-+ uint32_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
-+ udelay(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
-+ udelay(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)
-+ msleep(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/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h
-new file mode 100644
-index 0000000..b5d6c79
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.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_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;
-+ uint32_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;
-+ uint32_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);
-+ 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 acquire_reset;
-+};
-+
-+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/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c
-new file mode 100644
-index 0000000..0712caf
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c
-@@ -0,0 +1,112 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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/i2caux_interface.h"
-+#include "../i2caux.h"
-+#include "../engine.h"
-+#include "../i2c_engine.h"
-+#include "../i2c_sw_engine.h"
-+#include "../i2c_hw_engine.h"
-+
-+#include "../dce110/aux_engine_dce110.h"
-+#include "../dce110/i2c_hw_engine_dce110.h"
-+#include "../dce110/i2caux_dce110.h"
-+
-+#include "dce/dce_10_0_d.h"
-+#include "dce/dce_10_0_sh_mask.h"
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_COMMON_REG_LIST(id), \
-+ .AUX_RESET_MASK = 0 \
-+}
-+
-+#define hw_engine_regs(id)\
-+{\
-+ I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-+}
-+
-+static const struct dce110_aux_registers dce100_aux_regs[] = {
-+ aux_regs(0),
-+ aux_regs(1),
-+ aux_regs(2),
-+ aux_regs(3),
-+ aux_regs(4),
-+ aux_regs(5),
-+};
-+
-+static const struct dce110_i2c_hw_engine_registers dce100_hw_engine_regs[] = {
-+ hw_engine_regs(1),
-+ hw_engine_regs(2),
-+ hw_engine_regs(3),
-+ hw_engine_regs(4),
-+ hw_engine_regs(5),
-+ hw_engine_regs(6)
-+};
-+
-+static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-+ I2C_COMMON_MASK_SH_LIST_DCE100(__SHIFT)
-+};
-+
-+static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-+ I2C_COMMON_MASK_SH_LIST_DCE100(_MASK)
-+};
-+
-+struct i2caux *dal_i2caux_dce100_create(
-+ struct dc_context *ctx)
-+{
-+ struct i2caux_dce110 *i2caux_dce110 =
-+ dm_alloc(sizeof(struct i2caux_dce110));
-+
-+ if (!i2caux_dce110) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (dal_i2caux_dce110_construct(
-+ i2caux_dce110,
-+ ctx,
-+ dce100_aux_regs,
-+ dce100_hw_engine_regs,
-+ &i2c_shift,
-+ &i2c_mask))
-+ return &i2caux_dce110->base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(i2caux_dce110);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h
-new file mode 100644
-index 0000000..2b508d3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE100_H__
-+#define __DAL_I2C_AUX_DCE100_H__
-+
-+struct i2caux *dal_i2caux_dce100_create(
-+ struct dc_context *ctx);
-+
-+#endif /* __DAL_I2C_AUX_DCE100_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
-new file mode 100644
-index 0000000..f49fd1a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
-@@ -0,0 +1,456 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_sh_mask.h"
-+
-+#define CTX \
-+ aux110->base.base.ctx
-+#define REG(reg_name)\
-+ (aux110->regs->reg_name)
-+#include "reg_helper.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 *aux110 = FROM_ENGINE(engine);
-+
-+ REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
-+}
-+
-+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(engine);
-+
-+ *aux_engine = NULL;
-+}
-+
-+#define SW_CAN_ACCESS_AUX 1
-+
-+static bool acquire_engine(
-+ struct aux_engine *engine)
-+{
-+ struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-+
-+ /* enable AUX before request SW to access AUX */
-+ uint32_t value = REG_READ(AUX_CONTROL);
-+ uint32_t field = get_reg_field_value(value,
-+ AUX_CONTROL,
-+ AUX_EN);
-+
-+ if (field == 0) {
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ AUX_CONTROL,
-+ AUX_EN);
-+
-+ if (REG(AUX_RESET_MASK)) {
-+ /*DP_AUX block as part of the enable sequence*/
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ AUX_CONTROL,
-+ AUX_RESET);
-+ }
-+
-+ REG_WRITE(AUX_CONTROL, value);
-+
-+ if (REG(AUX_RESET_MASK)) {
-+ /*poll HW to make sure reset it done*/
-+
-+ REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
-+ 1, 11);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ AUX_CONTROL,
-+ AUX_RESET);
-+
-+ REG_WRITE(AUX_CONTROL, value);
-+
-+ REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
-+ 1, 11);
-+ }
-+ } /*if (field)*/
-+
-+ /* request SW to access AUX */
-+ REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
-+
-+ value = REG_READ(AUX_ARB_CONTROL);
-+ field = get_reg_field_value(
-+ value,
-+ AUX_ARB_CONTROL,
-+ AUX_REG_RW_CNTL_STATUS);
-+
-+ return (field == SW_CAN_ACCESS_AUX);
-+}
-+
-+#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 *aux110 = 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 */
-+ REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK,
-+ 1,
-+ 0);
-+
-+ REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK,
-+ 1,
-+ 0);
-+
-+ /* force_default_calibrate */
-+ REG_UPDATE_1BY1_2(AUXN_IMPCAL,
-+ AUXN_IMPCAL_ENABLE, 1,
-+ AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
-+
-+ /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
-+
-+ REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
-+ 1,
-+ 0);
-+
-+ /* set the delay and the number of bytes to write */
-+
-+ /* 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;
-+
-+ REG_UPDATE_2(AUX_SW_CONTROL,
-+ AUX_SW_START_DELAY, request->delay,
-+ AUX_SW_WR_BYTES, length);
-+
-+ /* program action and address and payload data (if 'is_write') */
-+ value = REG_UPDATE_4(AUX_SW_DATA,
-+ AUX_SW_INDEX, 0,
-+ AUX_SW_DATA_RW, 0,
-+ AUX_SW_AUTOINCREMENT_DISABLE, 1,
-+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
-+
-+ value = REG_SET_2(AUX_SW_DATA, value,
-+ AUX_SW_AUTOINCREMENT_DISABLE, 0,
-+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
-+
-+ value = REG_SET(AUX_SW_DATA, value,
-+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
-+
-+ if (request->length) {
-+ value = REG_SET(AUX_SW_DATA, value,
-+ AUX_SW_DATA, request->length - 1);
-+ }
-+
-+ 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) {
-+ value = REG_SET(AUX_SW_DATA, value,
-+ AUX_SW_DATA, request->data[i]);
-+
-+ ++i;
-+ }
-+ }
-+
-+ REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
-+ REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
-+ 10, aux110->timeout_period/10);
-+ REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
-+}
-+
-+static void process_channel_reply(
-+ struct aux_engine *engine,
-+ struct aux_reply_transaction_data *reply)
-+{
-+ struct aux_engine_dce110 *aux110 = 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;
-+
-+ value = REG_GET(AUX_SW_STATUS,
-+ AUX_SW_REPLY_BYTE_COUNT, &bytes_replied);
-+
-+ if (bytes_replied) {
-+ uint32_t reply_result;
-+
-+ REG_UPDATE_1BY1_3(AUX_SW_DATA,
-+ AUX_SW_INDEX, 0,
-+ AUX_SW_AUTOINCREMENT_DISABLE, 1,
-+ AUX_SW_DATA_RW, 1);
-+
-+ REG_GET(AUX_SW_DATA,
-+ AUX_SW_DATA, &reply_result);
-+
-+ 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) {
-+ uint32_t aux_sw_data_val;
-+
-+ REG_GET(AUX_SW_DATA,
-+ AUX_SW_DATA, &aux_sw_data_val);
-+
-+ reply->data[i] = aux_sw_data_val;
-+ ++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 *aux110 = FROM_AUX_ENGINE(engine);
-+
-+ uint32_t value;
-+
-+ 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 */
-+ value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
-+ 10, aux110->timeout_period/10);
-+
-+ /* 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 (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
-+ if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
-+ (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
-+ return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
-+
-+ else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
-+ (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
-+ (value &
-+ AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
-+ (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
-+ 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 struct aux_engine_funcs aux_engine_funcs = {
-+ .destroy = destroy,
-+ .acquire_engine = acquire_engine,
-+ .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,
-+ .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)
-+{
-+ 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;
-+
-+ engine->timeout_period = aux_init_data->timeout_period;
-+ engine->regs = aux_init_data->regs;
-+
-+ 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(sizeof(*engine));
-+
-+ if (!engine) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (construct(engine, aux_init_data))
-+ return &engine->base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(engine);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h
-new file mode 100644
-index 0000000..85ee821
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h
-@@ -0,0 +1,78 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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"
-+
-+#define AUX_COMMON_REG_LIST(id)\
-+ SRI(AUX_CONTROL, DP_AUX, id), \
-+ SRI(AUX_ARB_CONTROL, DP_AUX, id), \
-+ SRI(AUX_SW_DATA, DP_AUX, id), \
-+ SRI(AUX_SW_CONTROL, DP_AUX, id), \
-+ SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
-+ SRI(AUX_SW_STATUS, DP_AUX, id), \
-+ SR(AUXN_IMPCAL), \
-+ SR(AUXP_IMPCAL)
-+
-+struct dce110_aux_registers {
-+ 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 AUXN_IMPCAL;
-+ uint32_t AUXP_IMPCAL;
-+
-+ uint32_t AUX_RESET_MASK;
-+};
-+
-+struct aux_engine_dce110 {
-+ struct aux_engine base;
-+ const struct dce110_aux_registers *regs;
-+ 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;
-+ } addr;
-+ uint32_t timeout_period;
-+};
-+
-+struct aux_engine_dce110_init_data {
-+ uint32_t engine_id;
-+ uint32_t timeout_period;
-+ struct dc_context *ctx;
-+ const struct dce110_aux_registers *regs;
-+};
-+
-+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/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
-new file mode 100644
-index 0000000..80d06ad
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
-@@ -0,0 +1,577 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "reg_helper.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 = 538
-+};
-+
-+/*
-+ * @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))
-+
-+#define CTX \
-+ hw_engine->base.base.base.ctx
-+
-+#define REG(reg_name)\
-+ (hw_engine->regs->reg_name)
-+
-+#undef FN
-+#define FN(reg_name, field_name) \
-+ hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name
-+
-+#include "reg_helper.h"
-+
-+static void disable_i2c_hw_engine(
-+ struct i2c_hw_engine_dce110 *hw_engine)
-+{
-+ REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0);
-+}
-+
-+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;
-+
-+ base = &hw_engine->base.base;
-+
-+ /* Restore original HW engine speed */
-+
-+ base->funcs->set_speed(base, hw_engine->base.original_speed);
-+
-+ /* Release I2C */
-+ REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1);
-+
-+ /* Reset HW engine */
-+ {
-+ uint32_t i2c_sw_status = 0;
-+ REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-+ /* if used by SW, safe to reset */
-+ safe_to_reset = (i2c_sw_status == 1);
-+ }
-+
-+ if (safe_to_reset)
-+ REG_UPDATE_2(
-+ DC_I2C_CONTROL,
-+ DC_I2C_SOFT_RESET, 1,
-+ DC_I2C_SW_STATUS_RESET, 1);
-+ else
-+ REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
-+
-+ /* HW I2c engine - clock gating feature */
-+ if (!hw_engine->engine_keep_power_up_count)
-+ disable_i2c_hw_engine(hw_engine);
-+}
-+
-+static bool setup_engine(
-+ struct i2c_engine *i2c_engine)
-+{
-+ struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-+
-+ /* Program pin select */
-+ REG_UPDATE_6(
-+ DC_I2C_CONTROL,
-+ DC_I2C_GO, 0,
-+ DC_I2C_SOFT_RESET, 0,
-+ DC_I2C_SEND_RESET, 0,
-+ DC_I2C_SW_STATUS_RESET, 1,
-+ DC_I2C_TRANSACTION_COUNT, 0,
-+ DC_I2C_DDC_SELECT, hw_engine->engine_id);
-+
-+ /* Program time limit */
-+ REG_UPDATE_N(
-+ SETUP, 2,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), I2C_SETUP_TIME_LIMIT,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
-+
-+ /* 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 */
-+ REG_UPDATE_2(
-+ DC_I2C_ARBITRATION,
-+ DC_I2C_NO_QUEUED_SW_GO, 0,
-+ DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
-+
-+ return true;
-+}
-+
-+static uint32_t get_speed(
-+ const struct i2c_engine *i2c_engine)
-+{
-+ const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-+ uint32_t pre_scale = 0;
-+
-+ REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale);
-+
-+ /* [anaumov] it seems following is unnecessary */
-+ /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
-+ return pre_scale ?
-+ hw_engine->reference_frequency / pre_scale :
-+ hw_engine->base.default_speed;
-+}
-+
-+static void set_speed(
-+ struct i2c_engine *i2c_engine,
-+ uint32_t speed)
-+{
-+ struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-+
-+ if (speed) {
-+ if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
-+ REG_UPDATE_N(
-+ SPEED, 3,
-+ FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
-+ FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
-+ FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
-+ else
-+ REG_UPDATE_N(
-+ SPEED, 2,
-+ FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
-+ FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
-+ }
-+}
-+
-+static inline void reset_hw_engine(struct engine *engine)
-+{
-+ struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
-+
-+ REG_UPDATE_2(
-+ DC_I2C_CONTROL,
-+ DC_I2C_SW_STATUS_RESET, 1,
-+ DC_I2C_SW_STATUS_RESET, 1);
-+}
-+
-+static bool is_hw_busy(struct engine *engine)
-+{
-+ struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
-+ uint32_t i2c_sw_status = 0;
-+
-+ REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-+ if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
-+ return false;
-+
-+ reset_hw_engine(engine);
-+
-+ REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-+ return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
-+}
-+
-+
-+#define STOP_TRANS_PREDICAT \
-+ ((hw_engine->transaction_count == 3) || \
-+ (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || \
-+ (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ))
-+
-+#define SET_I2C_TRANSACTION(id) \
-+ do { \
-+ REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \
-+ FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1, \
-+ FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1, \
-+ FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0, \
-+ FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)), \
-+ FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length); \
-+ if (STOP_TRANS_PREDICAT) \
-+ last_transaction = true; \
-+ } while (false)
-+
-+
-+static bool process_transaction(
-+ struct i2c_hw_engine_dce110 *hw_engine,
-+ struct i2c_request_transaction_data *request)
-+{
-+ uint32_t length = request->length;
-+ uint8_t *buffer = request->data;
-+ uint32_t value = 0;
-+
-+ bool last_transaction = false;
-+
-+ struct dc_context *ctx = NULL;
-+
-+ ctx = hw_engine->base.base.base.ctx;
-+
-+
-+
-+ switch (hw_engine->transaction_count) {
-+ case 0:
-+ SET_I2C_TRANSACTION(0);
-+ break;
-+ case 1:
-+ SET_I2C_TRANSACTION(1);
-+ break;
-+ case 2:
-+ SET_I2C_TRANSACTION(2);
-+ break;
-+ case 3:
-+ SET_I2C_TRANSACTION(3);
-+ break;
-+ default:
-+ /* TODO Warning ? */
-+ break;
-+ }
-+
-+
-+ /* 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. */
-+ if (hw_engine->transaction_count == 0) {
-+ value = REG_SET_4(DC_I2C_DATA, 0,
-+ DC_I2C_DATA_RW, false,
-+ DC_I2C_DATA, request->address,
-+ DC_I2C_INDEX, 0,
-+ DC_I2C_INDEX_WRITE, 1);
-+ hw_engine->buffer_used_write = 0;
-+ } else
-+ value = REG_SET_2(DC_I2C_DATA, 0,
-+ DC_I2C_DATA_RW, false,
-+ DC_I2C_DATA, request->address);
-+
-+ hw_engine->buffer_used_write++;
-+
-+ if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
-+ while (length) {
-+ REG_SET_2(DC_I2C_DATA, value,
-+ DC_I2C_INDEX_WRITE, 0,
-+ DC_I2C_DATA, *buffer++);
-+ hw_engine->buffer_used_write++;
-+ --length;
-+ }
-+ }
-+
-+ ++hw_engine->transaction_count;
-+ hw_engine->buffer_used_bytes += length + 1;
-+
-+ return last_transaction;
-+}
-+
-+static void execute_transaction(
-+ struct i2c_hw_engine_dce110 *hw_engine)
-+{
-+ REG_UPDATE_N(SETUP, 5,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
-+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
-+
-+
-+ REG_UPDATE_5(DC_I2C_CONTROL,
-+ DC_I2C_SOFT_RESET, 0,
-+ DC_I2C_SW_STATUS_RESET, 0,
-+ DC_I2C_SEND_RESET, 0,
-+ DC_I2C_GO, 0,
-+ DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1);
-+
-+ /* start I2C transfer */
-+ REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
-+
-+ /* all transactions were executed and HW buffer became empty
-+ * (even though it actually happens when status becomes DONE) */
-+ hw_engine->transaction_count = 0;
-+ hw_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)
-+{
-+ uint32_t length = reply->length;
-+ uint8_t *buffer = reply->data;
-+
-+ struct i2c_hw_engine_dce110 *hw_engine =
-+ FROM_I2C_ENGINE(engine);
-+
-+
-+ REG_SET_3(DC_I2C_DATA, 0,
-+ DC_I2C_INDEX, hw_engine->buffer_used_write,
-+ DC_I2C_DATA_RW, 1,
-+ DC_I2C_INDEX_WRITE, 1);
-+
-+ 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 */
-+
-+ uint32_t i2c_data;
-+
-+ REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
-+ *buffer++ = i2c_data;
-+
-+ --length;
-+ }
-+}
-+
-+static enum i2c_channel_operation_result get_channel_status(
-+ struct i2c_engine *i2c_engine,
-+ uint8_t *returned_bytes)
-+{
-+ uint32_t i2c_sw_status = 0;
-+ struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-+ uint32_t value =
-+ REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &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 & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK)
-+ return I2C_CHANNEL_OPERATION_NO_RESPONSE;
-+ else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT)
-+ return I2C_CHANNEL_OPERATION_TIMEOUT;
-+ else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED)
-+ return I2C_CHANNEL_OPERATION_FAILED;
-+ else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE)
-+ return I2C_CHANNEL_OPERATION_SUCCEEDED;
-+
-+ /*
-+ * this is the case when HW used for communication, I2C_SW_STATUS
-+ * could be zero
-+ */
-+ return I2C_CHANNEL_OPERATION_SUCCEEDED;
-+}
-+
-+static uint32_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(engine_dce110);
-+
-+ *i2c_engine = NULL;
-+}
-+
-+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,
-+ .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,
-+};
-+
-+bool i2c_hw_engine_dce110_construct(
-+ struct i2c_hw_engine_dce110 *hw_engine,
-+ const struct i2c_hw_engine_dce110_create_arg *arg)
-+{
-+ uint32_t xtal_ref_div = 0;
-+
-+ if (!arg->reference_frequency)
-+ return false;
-+
-+ if (!dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx))
-+ return false;
-+
-+ hw_engine->base.base.base.funcs = &engine_funcs;
-+ hw_engine->base.base.funcs = &i2c_engine_funcs;
-+ hw_engine->base.funcs = &i2c_hw_engine_funcs;
-+ hw_engine->base.default_speed = arg->default_speed;
-+
-+ hw_engine->regs = arg->regs;
-+ hw_engine->i2c_shift = arg->i2c_shift;
-+ hw_engine->i2c_mask = arg->i2c_mask;
-+
-+ hw_engine->engine_id = arg->engine_id;
-+
-+ hw_engine->buffer_used_bytes = 0;
-+ hw_engine->transaction_count = 0;
-+ hw_engine->engine_keep_power_up_count = 1;
-+
-+
-+ REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div);
-+
-+ if (xtal_ref_div == 0) {
-+ dm_logger_write(
-+ hw_engine->base.base.base.ctx->logger, LOG_WARNING,
-+ "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
-+ */
-+ hw_engine->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(sizeof(struct i2c_hw_engine_dce110));
-+
-+ if (!engine_dce10) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (i2c_hw_engine_dce110_construct(engine_dce10, arg))
-+ return &engine_dce10->base.base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(engine_dce10);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h
-new file mode 100644
-index 0000000..c573c64
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h
-@@ -0,0 +1,214 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__
-+
-+#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\
-+ SRI(SETUP, DC_I2C_DDC, id),\
-+ SRI(SPEED, DC_I2C_DDC, id),\
-+ SR(DC_I2C_ARBITRATION),\
-+ SR(DC_I2C_CONTROL),\
-+ SR(DC_I2C_SW_STATUS),\
-+ SR(DC_I2C_TRANSACTION0),\
-+ SR(DC_I2C_TRANSACTION1),\
-+ SR(DC_I2C_TRANSACTION2),\
-+ SR(DC_I2C_TRANSACTION3),\
-+ SR(DC_I2C_DATA),\
-+ SR(MICROSECOND_TIME_BASE_DIV)
-+
-+#define I2C_SF(reg_name, field_name, post_fix)\
-+ .field_name = reg_name ## __ ## field_name ## post_fix
-+
-+#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\
-+ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\
-+ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\
-+ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\
-+ I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\
-+ I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\
-+ I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\
-+ I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\
-+ I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\
-+ I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\
-+ I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\
-+ I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\
-+ I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\
-+ I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\
-+ I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\
-+ I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\
-+ I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\
-+ I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\
-+ I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\
-+ I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh)
-+
-+#define I2C_COMMON_MASK_SH_LIST_DCE100(mask_sh)\
-+ I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
-+
-+#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
-+ I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
-+ I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh)
-+
-+struct dce110_i2c_hw_engine_shift {
-+ uint8_t DC_I2C_DDC1_ENABLE;
-+ uint8_t DC_I2C_DDC1_TIME_LIMIT;
-+ uint8_t DC_I2C_DDC1_DATA_DRIVE_EN;
-+ uint8_t DC_I2C_DDC1_CLK_DRIVE_EN;
-+ uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL;
-+ uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
-+ uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
-+ uint8_t DC_I2C_SW_DONE_USING_I2C_REG;
-+ uint8_t DC_I2C_NO_QUEUED_SW_GO;
-+ uint8_t DC_I2C_SW_PRIORITY;
-+ uint8_t DC_I2C_SOFT_RESET;
-+ uint8_t DC_I2C_SW_STATUS_RESET;
-+ uint8_t DC_I2C_GO;
-+ uint8_t DC_I2C_SEND_RESET;
-+ uint8_t DC_I2C_TRANSACTION_COUNT;
-+ uint8_t DC_I2C_DDC_SELECT;
-+ uint8_t DC_I2C_DDC1_PRESCALE;
-+ uint8_t DC_I2C_DDC1_THRESHOLD;
-+ uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
-+ uint8_t DC_I2C_SW_STOPPED_ON_NACK;
-+ uint8_t DC_I2C_SW_TIMEOUT;
-+ uint8_t DC_I2C_SW_ABORTED;
-+ uint8_t DC_I2C_SW_DONE;
-+ uint8_t DC_I2C_SW_STATUS;
-+ uint8_t DC_I2C_STOP_ON_NACK0;
-+ uint8_t DC_I2C_START0;
-+ uint8_t DC_I2C_RW0;
-+ uint8_t DC_I2C_STOP0;
-+ uint8_t DC_I2C_COUNT0;
-+ uint8_t DC_I2C_DATA_RW;
-+ uint8_t DC_I2C_DATA;
-+ uint8_t DC_I2C_INDEX;
-+ uint8_t DC_I2C_INDEX_WRITE;
-+ uint8_t XTAL_REF_DIV;
-+};
-+
-+struct dce110_i2c_hw_engine_mask {
-+ uint32_t DC_I2C_DDC1_ENABLE;
-+ uint32_t DC_I2C_DDC1_TIME_LIMIT;
-+ uint32_t DC_I2C_DDC1_DATA_DRIVE_EN;
-+ uint32_t DC_I2C_DDC1_CLK_DRIVE_EN;
-+ uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL;
-+ uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
-+ uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
-+ uint32_t DC_I2C_SW_DONE_USING_I2C_REG;
-+ uint32_t DC_I2C_NO_QUEUED_SW_GO;
-+ uint32_t DC_I2C_SW_PRIORITY;
-+ uint32_t DC_I2C_SOFT_RESET;
-+ uint32_t DC_I2C_SW_STATUS_RESET;
-+ uint32_t DC_I2C_GO;
-+ uint32_t DC_I2C_SEND_RESET;
-+ uint32_t DC_I2C_TRANSACTION_COUNT;
-+ uint32_t DC_I2C_DDC_SELECT;
-+ uint32_t DC_I2C_DDC1_PRESCALE;
-+ uint32_t DC_I2C_DDC1_THRESHOLD;
-+ uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
-+ uint32_t DC_I2C_SW_STOPPED_ON_NACK;
-+ uint32_t DC_I2C_SW_TIMEOUT;
-+ uint32_t DC_I2C_SW_ABORTED;
-+ uint32_t DC_I2C_SW_DONE;
-+ uint32_t DC_I2C_SW_STATUS;
-+ uint32_t DC_I2C_STOP_ON_NACK0;
-+ uint32_t DC_I2C_START0;
-+ uint32_t DC_I2C_RW0;
-+ uint32_t DC_I2C_STOP0;
-+ uint32_t DC_I2C_COUNT0;
-+ uint32_t DC_I2C_DATA_RW;
-+ uint32_t DC_I2C_DATA;
-+ uint32_t DC_I2C_INDEX;
-+ uint32_t DC_I2C_INDEX_WRITE;
-+ uint32_t XTAL_REF_DIV;
-+};
-+
-+struct dce110_i2c_hw_engine_registers {
-+ uint32_t SETUP;
-+ uint32_t SPEED;
-+ uint32_t DC_I2C_ARBITRATION;
-+ uint32_t DC_I2C_CONTROL;
-+ uint32_t DC_I2C_SW_STATUS;
-+ uint32_t DC_I2C_TRANSACTION0;
-+ uint32_t DC_I2C_TRANSACTION1;
-+ uint32_t DC_I2C_TRANSACTION2;
-+ uint32_t DC_I2C_TRANSACTION3;
-+ uint32_t DC_I2C_DATA;
-+ uint32_t MICROSECOND_TIME_BASE_DIV;
-+};
-+
-+struct i2c_hw_engine_dce110 {
-+ struct i2c_hw_engine base;
-+ const struct dce110_i2c_hw_engine_registers *regs;
-+ const struct dce110_i2c_hw_engine_shift *i2c_shift;
-+ const struct dce110_i2c_hw_engine_mask *i2c_mask;
-+ 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;
-+ const struct dce110_i2c_hw_engine_registers *regs;
-+ const struct dce110_i2c_hw_engine_shift *i2c_shift;
-+ const struct dce110_i2c_hw_engine_mask *i2c_mask;
-+};
-+
-+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
-+ const struct i2c_hw_engine_dce110_create_arg *arg);
-+
-+bool i2c_hw_engine_dce110_construct(
-+ struct i2c_hw_engine_dce110 *engine_dce110,
-+ const struct i2c_hw_engine_dce110_create_arg *arg);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c
-new file mode 100644
-index 0000000..996813d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c
-@@ -0,0 +1,171 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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(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,
-+};
-+
-+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(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(engine_dce110);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h
-new file mode 100644
-index 0000000..c48c61f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c
-new file mode 100644
-index 0000000..1c00ed0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c
-@@ -0,0 +1,323 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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(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 (ddc->hw_info.hw_supported) {
-+ 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,
-+};
-+
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_COMMON_REG_LIST(id), \
-+ .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \
-+}
-+
-+#define hw_engine_regs(id)\
-+{\
-+ I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-+}
-+
-+static const struct dce110_aux_registers dce110_aux_regs[] = {
-+ aux_regs(0),
-+ aux_regs(1),
-+ aux_regs(2),
-+ aux_regs(3),
-+ aux_regs(4),
-+ aux_regs(5)
-+};
-+
-+static const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[] = {
-+ hw_engine_regs(1),
-+ hw_engine_regs(2),
-+ hw_engine_regs(3),
-+ hw_engine_regs(4),
-+ hw_engine_regs(5),
-+ hw_engine_regs(6)
-+};
-+
-+static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-+ I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-+ I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+bool dal_i2caux_dce110_construct(
-+ struct i2caux_dce110 *i2caux_dce110,
-+ struct dc_context *ctx,
-+ const struct dce110_aux_registers aux_regs[],
-+ const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[],
-+ const struct dce110_i2c_hw_engine_shift *i2c_shift,
-+ const struct dce110_i2c_hw_engine_mask *i2c_mask)
-+{
-+ 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(ctx->dc_bios) >> 1;
-+
-+ base = &i2caux_dce110->base;
-+
-+ if (!dal_i2caux_construct(base, 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;
-+ hw_arg_dce110.regs = &i2c_hw_engine_regs[i];
-+ hw_arg_dce110.i2c_shift = i2c_shift;
-+ hw_arg_dce110.i2c_mask = i2c_mask;
-+
-+ 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;
-+ aux_init_data.regs = &aux_regs[i];
-+
-+ 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 dc_context *ctx)
-+{
-+ struct i2caux_dce110 *i2caux_dce110 =
-+ dm_alloc(sizeof(struct i2caux_dce110));
-+
-+ if (!i2caux_dce110) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (dal_i2caux_dce110_construct(
-+ i2caux_dce110,
-+ ctx,
-+ dce110_aux_regs,
-+ i2c_hw_engine_regs,
-+ &i2c_shift,
-+ &i2c_mask))
-+ return &i2caux_dce110->base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(i2caux_dce110);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h
-new file mode 100644
-index 0000000..fd1cc23
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_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_I2C_AUX_DCE110_H__
-+#define __DAL_I2C_AUX_DCE110_H__
-+
-+#include "../i2caux.h"
-+
-+struct i2caux_dce110 {
-+ struct i2caux base;
-+ /* indicate the I2C HW circular buffer is in use */
-+ bool i2c_hw_buffer_in_use;
-+};
-+
-+struct dce110_aux_registers;
-+struct dce110_i2c_hw_engine_registers;
-+struct dce110_i2c_hw_engine_shift;
-+struct dce110_i2c_hw_engine_mask;
-+
-+struct i2caux *dal_i2caux_dce110_create(
-+ struct dc_context *ctx);
-+
-+bool dal_i2caux_dce110_construct(
-+ struct i2caux_dce110 *i2caux_dce110,
-+ struct dc_context *ctx,
-+ const struct dce110_aux_registers *aux_regs,
-+ const struct dce110_i2c_hw_engine_registers *i2c_hw_engine_regs,
-+ const struct dce110_i2c_hw_engine_shift *i2c_shift,
-+ const struct dce110_i2c_hw_engine_mask *i2c_mask);
-+
-+#endif /* __DAL_I2C_AUX_DCE110_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c
-new file mode 100644
-index 0000000..d74f3f1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c
-@@ -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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+
-+#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"
-+
-+#include "../dce110/i2caux_dce110.h"
-+#include "i2caux_dce112.h"
-+
-+#include "../dce110/aux_engine_dce110.h"
-+
-+#include "../dce110/i2c_hw_engine_dce110.h"
-+
-+#include "dce/dce_11_2_d.h"
-+#include "dce/dce_11_2_sh_mask.h"
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_COMMON_REG_LIST(id), \
-+ .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \
-+}
-+
-+#define hw_engine_regs(id)\
-+{\
-+ I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-+}
-+
-+static const struct dce110_aux_registers dce112_aux_regs[] = {
-+ aux_regs(0),
-+ aux_regs(1),
-+ aux_regs(2),
-+ aux_regs(3),
-+ aux_regs(4),
-+ aux_regs(5),
-+};
-+
-+static const struct dce110_i2c_hw_engine_registers dce112_hw_engine_regs[] = {
-+ hw_engine_regs(1),
-+ hw_engine_regs(2),
-+ hw_engine_regs(3),
-+ hw_engine_regs(4),
-+ hw_engine_regs(5),
-+ hw_engine_regs(6)
-+};
-+
-+static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-+ I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-+};
-+
-+static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-+ I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-+};
-+
-+static bool construct(
-+ struct i2caux_dce110 *i2caux_dce110,
-+ struct dc_context *ctx)
-+{
-+ if (!dal_i2caux_dce110_construct(
-+ i2caux_dce110,
-+ ctx,
-+ dce112_aux_regs,
-+ dce112_hw_engine_regs,
-+ &i2c_shift,
-+ &i2c_mask)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+
-+ 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_dce112_create(
-+ struct dc_context *ctx)
-+{
-+ struct i2caux_dce110 *i2caux_dce110 =
-+ dm_alloc(sizeof(struct i2caux_dce110));
-+
-+ if (!i2caux_dce110) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (construct(i2caux_dce110, ctx))
-+ return &i2caux_dce110->base;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(i2caux_dce110);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h
-new file mode 100644
-index 0000000..8d35453
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE112_H__
-+#define __DAL_I2C_AUX_DCE112_H__
-+
-+struct i2caux *dal_i2caux_dce112_create(
-+ struct dc_context *ctx);
-+
-+#endif /* __DAL_I2C_AUX_DCE112_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c
-new file mode 100644
-index 0000000..423c38a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c
-@@ -0,0 +1,885 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+#include "../i2c_generic_hw_engine.h"
-+/*
-+ * Header of this unit
-+ */
-+
-+#include "i2c_hw_engine_dce80.h"
-+
-+/*
-+ * Post-requisites: headers required by this unit
-+ */
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_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 'struct i2c_hw_engine *'
-+ * to 'struct i2c_hw_engine_dce80 *'
-+ */
-+#define FROM_I2C_HW_ENGINE(ptr) \
-+ container_of((ptr), struct i2c_hw_engine_dce80, base)
-+
-+/*
-+ * @brief
-+ * Cast pointer to 'struct i2c_engine *'
-+ * to pointer to 'struct i2c_hw_engine_dce80 *'
-+ */
-+#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_dce80 *'
-+ */
-+#define FROM_ENGINE(ptr) \
-+ FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-+
-+static void disable_i2c_hw_engine(
-+ struct i2c_hw_engine_dce80 *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_dce80 *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 destruct(
-+ struct i2c_hw_engine_dce80 *engine)
-+{
-+ dal_i2c_hw_engine_destruct(&engine->base);
-+}
-+
-+static void destroy(
-+ struct i2c_engine **i2c_engine)
-+{
-+ struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine);
-+
-+ destruct(engine);
-+
-+ dm_free(engine);
-+
-+ *i2c_engine = NULL;
-+}
-+
-+static bool setup_engine(
-+ struct i2c_engine *i2c_engine)
-+{
-+ uint32_t value = 0;
-+ struct i2c_hw_engine_dce80 *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_dce80 *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_dce80 *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);
-+
-+ 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_dce80 *engine,
-+ struct i2c_request_transaction_data *request)
-+{
-+ uint32_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);
-+ }
-+
-+ dm_write_reg(ctx, mmDC_I2C_DATA, value);
-+
-+ 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);
-+ --length;
-+ }
-+ }
-+ }
-+
-+ ++engine->transaction_count;
-+ engine->buffer_used_bytes += length + 1;
-+
-+ return last_transaction;
-+}
-+
-+static void execute_transaction(
-+ struct i2c_hw_engine_dce80 *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)
-+{
-+ uint32_t length = reply->length;
-+ uint8_t *buffer = reply->data;
-+
-+ uint32_t value = 0;
-+
-+ /*set index*/
-+ set_reg_field_value(
-+ value,
-+ length - 1,
-+ 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;
-+
-+ /*
-+ * this is the case when HW used for communication, I2C_SW_STATUS
-+ * could be zero
-+ */
-+ return I2C_CHANNEL_OPERATION_SUCCEEDED;
-+}
-+
-+static uint32_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;
-+}
-+
-+/*
-+ * @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,
-+ .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_dce80 *engine,
-+ const struct i2c_hw_engine_dce80_create_arg *arg)
-+{
-+ 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->base, arg->ctx))
-+ return false;
-+
-+ engine->base.base.base.funcs = &engine_funcs;
-+ engine->base.base.funcs = &i2c_engine_funcs;
-+ engine->base.funcs = &i2c_hw_engine_funcs;
-+ engine->base.default_speed = arg->default_speed;
-+ engine->addr.DC_I2C_DDCX_SETUP =
-+ mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
-+ engine->addr.DC_I2C_DDCX_SPEED =
-+ mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
-+
-+ engine->engine_id = arg->engine_id;
-+ engine->reference_frequency = arg->reference_frequency;
-+ engine->buffer_used_bytes = 0;
-+ engine->transaction_count = 0;
-+ engine->engine_keep_power_up_count = 1;
-+
-+ return true;
-+}
-+
-+struct i2c_engine *dal_i2c_hw_engine_dce80_create(
-+ const struct i2c_hw_engine_dce80_create_arg *arg)
-+{
-+ struct i2c_hw_engine_dce80 *engine;
-+
-+ if (!arg) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ engine = dm_alloc(sizeof(struct i2c_hw_engine_dce80));
-+
-+ if (!engine) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ if (construct(engine, arg))
-+ return &engine->base.base;
-+
-+ BREAK_TO_DEBUGGER();
-+
-+ dm_free(engine);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h
-new file mode 100644
-index 0000000..5c6116fb
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h
-@@ -0,0 +1,54 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DCE80_H__
-+#define __DAL_I2C_HW_ENGINE_DCE80_H__
-+
-+struct i2c_hw_engine_dce80 {
-+ 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 pending transactions (before GO) */
-+ uint32_t transaction_count;
-+ uint32_t engine_keep_power_up_count;
-+};
-+
-+struct i2c_hw_engine_dce80_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_dce80_create(
-+ const struct i2c_hw_engine_dce80_create_arg *arg);
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c
-new file mode 100644
-index 0000000..804a326
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c
-@@ -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
-+ *
-+ */
-+
-+#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_dce80.h"
-+
-+/*
-+ * Post-requisites: headers required by this unit
-+ */
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+/*
-+ * This unit
-+ */
-+
-+static const uint32_t ddc_hw_status_addr[] = {
-+ mmDC_I2C_DDC1_HW_STATUS,
-+ mmDC_I2C_DDC2_HW_STATUS,
-+ mmDC_I2C_DDC3_HW_STATUS,
-+ mmDC_I2C_DDC4_HW_STATUS,
-+ mmDC_I2C_DDC5_HW_STATUS,
-+ mmDC_I2C_DDC6_HW_STATUS,
-+ mmDC_I2C_DDCVGA_HW_STATUS
-+};
-+
-+/*
-+ * @brief
-+ * Cast 'struct i2c_sw_engine *'
-+ * to 'struct i2c_sw_engine_dce80 *'
-+ */
-+#define FROM_I2C_SW_ENGINE(ptr) \
-+ container_of((ptr), struct i2c_sw_engine_dce80, 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_dce80 *engine)
-+{
-+ dal_i2c_sw_engine_destruct(&engine->base);
-+}
-+
-+static void destroy(
-+ struct i2c_engine **engine)
-+{
-+ struct i2c_sw_engine_dce80 *sw_engine = FROM_I2C_ENGINE(*engine);
-+
-+ destruct(sw_engine);
-+
-+ dm_free(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,
-+};
-+
-+static bool construct(
-+ struct i2c_sw_engine_dce80 *engine,
-+ const struct i2c_sw_engine_dce80_create_arg *arg)
-+{
-+ struct i2c_sw_engine_create_arg arg_base;
-+
-+ arg_base.ctx = arg->ctx;
-+ arg_base.default_speed = arg->default_speed;
-+
-+ if (!dal_i2c_sw_engine_construct(&engine->base, &arg_base)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ engine->base.base.base.funcs = &engine_funcs;
-+ engine->base.base.funcs = &i2c_engine_funcs;
-+ engine->base.default_speed = arg->default_speed;
-+ engine->engine_id = arg->engine_id;
-+
-+ return true;
-+}
-+
-+struct i2c_engine *dal_i2c_sw_engine_dce80_create(
-+ const struct i2c_sw_engine_dce80_create_arg *arg)
-+{
-+ struct i2c_sw_engine_dce80 *engine;
-+
-+ if (!arg) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ engine = dm_alloc(sizeof(struct i2c_sw_engine_dce80));
-+
-+ if (!engine) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ if (construct(engine, arg))
-+ return &engine->base.base;
-+
-+ BREAK_TO_DEBUGGER();
-+
-+ dm_free(engine);
-+
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h
-new file mode 100644
-index 0000000..26355c0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.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_DCE80_H__
-+#define __DAL_I2C_SW_ENGINE_DCE80_H__
-+
-+struct i2c_sw_engine_dce80 {
-+ struct i2c_sw_engine base;
-+ uint32_t engine_id;
-+};
-+
-+struct i2c_sw_engine_dce80_create_arg {
-+ uint32_t engine_id;
-+ uint32_t default_speed;
-+ struct dc_context *ctx;
-+};
-+
-+struct i2c_engine *dal_i2c_sw_engine_dce80_create(
-+ const struct i2c_sw_engine_dce80_create_arg *arg);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c
-new file mode 100644
-index 0000000..5e71450
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c
-@@ -0,0 +1,295 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+
-+/*
-+ * Header of this unit
-+ */
-+
-+#include "i2caux_dce80.h"
-+
-+/*
-+ * Post-requisites: headers required by this unit
-+ */
-+
-+#include "../engine.h"
-+#include "../i2c_engine.h"
-+#include "../i2c_sw_engine.h"
-+#include "i2c_sw_engine_dce80.h"
-+#include "../i2c_hw_engine.h"
-+#include "i2c_hw_engine_dce80.h"
-+#include "../i2c_generic_hw_engine.h"
-+#include "../aux_engine.h"
-+
-+
-+#include "../dce110/aux_engine_dce110.h"
-+#include "../dce110/i2caux_dce110.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_0_sh_mask.h"
-+
-+
-+/* set register offset */
-+#define SR(reg_name)\
-+ .reg_name = mm ## reg_name
-+
-+/* set register offset with instance */
-+#define SRI(reg_name, block, id)\
-+ .reg_name = mm ## block ## id ## _ ## reg_name
-+
-+#define aux_regs(id)\
-+[id] = {\
-+ AUX_COMMON_REG_LIST(id), \
-+ .AUX_RESET_MASK = 0 \
-+}
-+
-+static const struct dce110_aux_registers dce80_aux_regs[] = {
-+ aux_regs(0),
-+ aux_regs(1),
-+ aux_regs(2),
-+ aux_regs(3),
-+ aux_regs(4),
-+ aux_regs(5)
-+};
-+
-+/*
-+ * This unit
-+ */
-+
-+#define FROM_I2C_AUX(ptr) \
-+ container_of((ptr), struct i2caux_dce80, base)
-+
-+static void destruct(
-+ struct i2caux_dce80 *i2caux_dce80)
-+{
-+ dal_i2caux_destruct(&i2caux_dce80->base);
-+}
-+
-+static void destroy(
-+ struct i2caux **i2c_engine)
-+{
-+ struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(*i2c_engine);
-+
-+ destruct(i2caux_dce80);
-+
-+ dm_free(i2caux_dce80);
-+
-+ *i2c_engine = NULL;
-+}
-+
-+static struct i2c_engine *acquire_i2c_hw_engine(
-+ struct i2caux *i2caux,
-+ struct ddc *ddc)
-+{
-+ struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(i2caux);
-+
-+ struct i2c_engine *engine = NULL;
-+ bool non_generic;
-+
-+ if (!ddc)
-+ return NULL;
-+
-+ if (ddc->hw_info.hw_supported) {
-+ enum gpio_ddc_line line = dal_ddc_get_line(ddc);
-+
-+ if (line < GPIO_DDC_LINE_COUNT) {
-+ non_generic = true;
-+ engine = i2caux->i2c_hw_engines[line];
-+ }
-+ }
-+
-+ if (!engine) {
-+ non_generic = false;
-+ engine = i2caux->i2c_generic_hw_engine;
-+ }
-+
-+ if (!engine)
-+ return NULL;
-+
-+ if (non_generic) {
-+ if (!i2caux_dce80->i2c_hw_buffer_in_use &&
-+ engine->base.funcs->acquire(&engine->base, ddc)) {
-+ i2caux_dce80->i2c_hw_buffer_in_use = true;
-+ return engine;
-+ }
-+ } else {
-+ if (engine->base.funcs->acquire(&engine->base, ddc))
-+ return engine;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void release_engine(
-+ struct i2caux *i2caux,
-+ struct engine *engine)
-+{
-+ if (engine->funcs->get_engine_type(engine) ==
-+ I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
-+ FROM_I2C_AUX(i2caux)->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,
-+ GPIO_DDC_LINE_DDC_VGA
-+};
-+
-+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
-+};
-+
-+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_dce80 *i2caux_dce80,
-+ struct dc_context *ctx)
-+{
-+ /* Entire family have I2C engine reference clock frequency
-+ * changed from XTALIN (27) to XTALIN/2 (13.5) */
-+
-+ struct i2caux *base = &i2caux_dce80->base;
-+
-+ uint32_t reference_frequency =
-+ dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1;
-+
-+ /*bool use_i2c_sw_engine = dal_adapter_service_is_feature_supported(as,
-+ FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);*/
-+
-+ /* Use SWI2C for dce8 currently, sicne we have bug with hwi2c */
-+ bool use_i2c_sw_engine = true;
-+
-+ uint32_t i;
-+
-+ if (!dal_i2caux_construct(base, ctx)) {
-+ BREAK_TO_DEBUGGER();
-+ return false;
-+ }
-+
-+ i2caux_dce80->base.funcs = &i2caux_funcs;
-+ i2caux_dce80->i2c_hw_buffer_in_use = false;
-+
-+ /* Create I2C HW engines (HW + SW pairs)
-+ * for all lines which has assisted HW DDC
-+ * 'i' (loop counter) used as DDC/AUX engine_id */
-+
-+ i = 0;
-+
-+ do {
-+ enum gpio_ddc_line line_id = hw_ddc_lines[i];
-+
-+ struct i2c_hw_engine_dce80_create_arg hw_arg;
-+
-+ if (use_i2c_sw_engine) {
-+ struct i2c_sw_engine_dce80_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_dce80_create(&sw_arg);
-+ }
-+
-+ hw_arg.engine_id = i;
-+ hw_arg.reference_frequency = reference_frequency;
-+ hw_arg.default_speed = base->default_i2c_hw_speed;
-+ hw_arg.ctx = ctx;
-+
-+ base->i2c_hw_engines[line_id] =
-+ dal_i2c_hw_engine_dce80_create(&hw_arg);
-+
-+ ++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 arg;
-+
-+ arg.engine_id = i;
-+ arg.timeout_period = base->aux_timeout_period;
-+ arg.ctx = ctx;
-+ arg.regs = &dce80_aux_regs[i];
-+
-+ base->aux_engines[line_id] =
-+ dal_aux_engine_dce110_create(&arg);
-+
-+ ++i;
-+ } while (i < ARRAY_SIZE(hw_aux_lines));
-+
-+ /* TODO Generic I2C SW and HW */
-+
-+ return true;
-+}
-+
-+struct i2caux *dal_i2caux_dce80_create(
-+ struct dc_context *ctx)
-+{
-+ struct i2caux_dce80 *i2caux_dce80 =
-+ dm_alloc(sizeof(struct i2caux_dce80));
-+
-+ if (!i2caux_dce80) {
-+ BREAK_TO_DEBUGGER();
-+ return NULL;
-+ }
-+
-+ if (construct(i2caux_dce80, ctx))
-+ return &i2caux_dce80->base;
-+
-+ BREAK_TO_DEBUGGER();
-+
-+ dm_free(i2caux_dce80);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h
-new file mode 100644
-index 0000000..2190862
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.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_I2C_AUX_DCE80_H__
-+#define __DAL_I2C_AUX_DCE80_H__
-+
-+struct i2caux_dce80 {
-+ struct i2caux base;
-+ /* indicate the I2C HW circular buffer is in use */
-+ bool i2c_hw_buffer_in_use;
-+};
-+
-+struct i2caux *dal_i2caux_dce80_create(
-+ struct dc_context *ctx);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c
-new file mode 100644
-index 0000000..029bf73
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c
-@@ -0,0 +1,108 @@
-+/*
-+ * 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);
-+
-+ *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 dc_context *ctx)
-+{
-+ if (!dal_i2caux_construct(i2caux, ctx)) {
-+ ASSERT_CRITICAL(false);
-+ return false;
-+ }
-+
-+ i2caux->funcs = &i2caux_funcs;
-+
-+ return true;
-+}
-+
-+struct i2caux *dal_i2caux_diag_fpga_create(
-+ struct dc_context *ctx)
-+{
-+ struct i2caux *i2caux = dm_alloc(sizeof(struct i2caux));
-+
-+ if (!i2caux) {
-+ ASSERT_CRITICAL(false);
-+ return NULL;
-+ }
-+
-+ if (construct(i2caux, ctx))
-+ return i2caux;
-+
-+ ASSERT_CRITICAL(false);
-+
-+ dm_free(i2caux);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h
-new file mode 100644
-index 0000000..a83eeb7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h
-@@ -0,0 +1,32 @@
-+/*
-+ * 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 dc_context *ctx);
-+
-+#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h
-new file mode 100644
-index 0000000..76fe2df
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h
-@@ -0,0 +1,120 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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;
-+ uint32_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);
-+ 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);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c
-new file mode 100644
-index 0000000..09da813
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c
-@@ -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
-+ *
-+ */
-+
-+#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"
-+
-+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/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c
-new file mode 100644
-index 0000000..144f51d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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 */
-+
-+ udelay(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/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h
-new file mode 100644
-index 0000000..ce2c51d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+ uint32_t length;
-+ uint8_t *data;
-+};
-+
-+struct i2c_reply_transaction_data {
-+ uint32_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/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c
-new file mode 100644
-index 0000000..521c4ec
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+
-+ uint32_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;
-+ uint32_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) {
-+ uint32_t current_transaction_size;
-+ uint32_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/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h
-new file mode 100644
-index 0000000..083bb0d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+ uint32_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,
-+ uint32_t length);
-+ void (*read_data)(
-+ struct i2c_generic_hw_engine *engine,
-+ uint8_t *buffer,
-+ uint32_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/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c
-new file mode 100644
-index 0000000..00a8f07
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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;
-+
-+ udelay(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/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h
-new file mode 100644
-index 0000000..f2df174
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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 {
-+ uint32_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/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c
-new file mode 100644
-index 0000000..95bc445
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.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"
-+
-+/*
-+ * 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_gpio_get_value(ddc->pin_data, &value);
-+ else
-+ dal_gpio_get_value(ddc->pin_clock, &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_gpio_set_value(ddc->pin_data, value);
-+ else
-+ dal_gpio_set_value(ddc->pin_clock, 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;
-+
-+ udelay(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;
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4);
-+
-+ do {
-+ write_bit_to_ddc(ddc_handle, SDA, true);
-+
-+ if (!read_bit_from_ddc(ddc_handle, SDA)) {
-+ ++retry;
-+ continue;
-+ }
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4);
-+
-+ write_bit_to_ddc(ddc_handle, SCL, false);
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4);
-+
-+ write_bit_to_ddc(ddc_handle, SDA, false);
-+
-+ udelay(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 {
-+ udelay(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 {
-+ udelay(clock_delay_div_4);
-+
-+ write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
-+
-+ udelay(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 */
-+
-+ udelay(clock_delay_div_4);
-+
-+ write_bit_to_ddc(ddc_handle, SDA, true);
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4 << 1);
-+
-+ write_bit_to_ddc(ddc_handle, SCL, false);
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4 << 1);
-+
-+ --shift;
-+ } while (shift >= 0);
-+
-+ /* read only whole byte */
-+
-+ *byte = data;
-+
-+ udelay(clock_delay_div_4);
-+
-+ /* send the acknowledge bit:
-+ * SDA low means ACK, SDA high means NACK */
-+
-+ write_bit_to_ddc(ddc_handle, SDA, !more);
-+
-+ udelay(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);
-+
-+ udelay(clock_delay_div_4);
-+
-+ write_bit_to_ddc(ddc_handle, SDA, true);
-+
-+ udelay(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,
-+ uint32_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,
-+ uint32_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)
-+{
-+ /* No arbitration with VBIOS is performed since DCE 6.0 */
-+ return 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);
-+ *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,
-+};
-+
-+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(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(engine);
-+
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h
-new file mode 100644
-index 0000000..e0cb4c3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
-new file mode 100644
-index 0000000..5391655
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
-@@ -0,0 +1,459 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 "dc_bios_types.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
-+ */
-+
-+#include "dce80/i2caux_dce80.h"
-+
-+#include "dce100/i2caux_dce100.h"
-+
-+#include "dce110/i2caux_dce110.h"
-+
-+#include "dce112/i2caux_dce112.h"
-+
-+#include "diagnostics/i2caux_diag.h"
-+
-+/*
-+ * @brief
-+ * Plain API, available publicly
-+ */
-+
-+struct i2caux *dal_i2caux_create(
-+ struct dc_context *ctx)
-+{
-+ if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
-+ return dal_i2caux_diag_fpga_create(ctx);
-+ }
-+
-+ switch (ctx->dce_version) {
-+ case DCE_VERSION_8_0:
-+ return dal_i2caux_dce80_create(ctx);
-+ case DCE_VERSION_11_2:
-+ return dal_i2caux_dce112_create(ctx);
-+ case DCE_VERSION_11_0:
-+ return dal_i2caux_dce110_create(ctx);
-+ case DCE_VERSION_10_0:
-+ return dal_i2caux_dce100_create(ctx);
-+ 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;
-+ }
-+
-+ /*
-+ * default will be SW, however there is a feature flag in adapter
-+ * service that determines whether SW i2c_engine will be available or
-+ * not, if sw i2c is not available we will fallback to hw. This feature
-+ * flag is set to not creating sw i2c engine for every dce except dce80
-+ * currently
-+ */
-+ switch (cmd->engine) {
-+ case I2C_COMMAND_ENGINE_DEFAULT:
-+ 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:
-+ 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 (!ddc->hw_info.hw_supported)
-+ 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_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 dc_bios *bios)
-+{
-+ struct firmware_info info = { { 0 } };
-+
-+ if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK)
-+ 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 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/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h
-new file mode 100644
-index 0000000..bc20de3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.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 __DAL_I2C_AUX_H__
-+#define __DAL_I2C_AUX_H__
-+
-+uint32_t dal_i2caux_get_reference_clock(
-+ struct dc_bios *bios);
-+
-+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 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
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h
-new file mode 100644
-index 0000000..f9b871b
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h
-@@ -0,0 +1,503 @@
-+/*
-+ * 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 "DCEx_mode_support.xlsm" from Perforce.)
-+ */
-+#ifndef __BANDWIDTH_CALCS_H__
-+#define __BANDWIDTH_CALCS_H__
-+
-+#include "bw_fixed.h"
-+
-+struct pipe_ctx;
-+
-+enum bw_calcs_version {
-+ BW_CALCS_VERSION_INVALID,
-+ BW_CALCS_VERSION_CARRIZO,
-+ BW_CALCS_VERSION_POLARIS10,
-+ BW_CALCS_VERSION_POLARIS11,
-+ BW_CALCS_VERSION_STONEY,
-+};
-+
-+/*******************************************************************************
-+ * 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_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_array_linear_general,
-+ bw_def_array_linear_aligned,
-+ bw_def_rotated_micro_tiling,
-+ bw_def_display_micro_tiling,
-+
-+ //Memory type
-+ bw_def_gddr5,
-+ bw_def_hbm,
-+
-+ //Voltage
-+ bw_def_high_no_nbp_state_change,
-+ bw_def_0_72,
-+ bw_def_0_8,
-+ bw_def_0_9,
-+
-+ bw_def_notok = -1,
-+ bw_def_na = -1
-+};
-+
-+struct bw_calcs_dceip {
-+ enum bw_calcs_version version;
-+ bool large_cursor;
-+ uint32_t cursor_max_outstanding_group_num;
-+ bool dmif_pipe_en_fbc_chunk_tracker;
-+ struct bw_fixed dmif_request_buffer_size;
-+ uint32_t lines_interleaved_into_lb;
-+ uint32_t low_power_tiling_mode;
-+ 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 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;
-+};
-+
-+struct bw_calcs_vbios {
-+ enum bw_defines memory_type;
-+ uint32_t dram_channel_width_in_bits;
-+ uint32_t number_of_dram_channels;
-+ uint32_t number_of_dram_banks;
-+ struct bw_fixed low_yclk; /*m_hz*/
-+ struct bw_fixed mid_yclk; /*m_hz*/
-+ struct bw_fixed high_yclk; /*m_hz*/
-+ struct bw_fixed low_sclk; /*m_hz*/
-+ struct bw_fixed mid1_sclk; /*m_hz*/
-+ struct bw_fixed mid2_sclk; /*m_hz*/
-+ struct bw_fixed mid3_sclk; /*m_hz*/
-+ struct bw_fixed mid4_sclk; /*m_hz*/
-+ struct bw_fixed mid5_sclk; /*m_hz*/
-+ struct bw_fixed mid6_sclk; /*m_hz*/
-+ struct bw_fixed high_sclk; /*m_hz*/
-+ struct bw_fixed low_voltage_max_dispclk; /*m_hz*/
-+ struct bw_fixed mid_voltage_max_dispclk; /*m_hz*/
-+ struct bw_fixed high_voltage_max_dispclk; /*m_hz*/
-+ struct bw_fixed low_voltage_max_phyclk;
-+ struct bw_fixed mid_voltage_max_phyclk;
-+ struct bw_fixed high_voltage_max_phyclk;
-+ 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 stutter_self_refresh_entry_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;
-+};
-+
-+/*******************************************************************************
-+ * Temporary data structure(s).
-+ ******************************************************************************/
-+#define maximum_number_of_surfaces 12
-+/*Units : MHz, us */
-+
-+struct bw_calcs_data {
-+ /* data for all displays */
-+ uint32_t number_of_displays;
-+ enum bw_defines underlay_surface_type;
-+ enum bw_defines panning_and_bezel_adjustment;
-+ enum bw_defines graphics_tiling_mode;
-+ uint32_t graphics_lb_bpc;
-+ uint32_t underlay_lb_bpc;
-+ enum bw_defines underlay_tiling_mode;
-+ enum bw_defines d0_underlay_mode;
-+ bool d1_display_write_back_dwb_enable;
-+ enum bw_defines d1_underlay_mode;
-+
-+ 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;
-+ uint32_t number_of_dram_wrchannels;
-+ uint32_t chunk_request_delay;
-+ uint32_t number_of_dram_channels;
-+ enum bw_defines underlay_micro_tile_mode;
-+ enum bw_defines graphics_micro_tile_mode;
-+ struct bw_fixed max_phyclk;
-+ struct bw_fixed dram_efficiency;
-+ 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 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;
-+ struct bw_fixed dram_speed_change_margin;
-+ struct bw_fixed min_vblank_dram_speed_change_margin;
-+ struct bw_fixed min_stutter_refresh_duration;
-+ uint32_t total_stutter_dmif_buffer_size;
-+ uint32_t total_bytes_requested;
-+ uint32_t min_stutter_dmif_buffer_size;
-+ uint32_t num_stutter_bursts;
-+ struct bw_fixed v_blank_nbp_state_dram_speed_change_latency_supported;
-+ struct bw_fixed nbp_state_dram_speed_change_latency_supported;
-+ bool fbc_en[maximum_number_of_surfaces];
-+ bool lpt_en[maximum_number_of_surfaces];
-+ 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];
-+ bool line_buffer_prefetch[maximum_number_of_surfaces];
-+ uint32_t bytes_per_pixel[maximum_number_of_surfaces];
-+ uint32_t max_chunks_non_fbc_mode[maximum_number_of_surfaces];
-+ uint32_t lb_bpc[maximum_number_of_surfaces];
-+ uint32_t output_bpphdmi[maximum_number_of_surfaces];
-+ uint32_t output_bppdp4_lane_hbr[maximum_number_of_surfaces];
-+ uint32_t output_bppdp4_lane_hbr2[maximum_number_of_surfaces];
-+ uint32_t output_bppdp4_lane_hbr3[maximum_number_of_surfaces];
-+ enum bw_defines stereo_mode[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];
-+ struct bw_fixed stutter_dmif_buffer_size[maximum_number_of_surfaces];
-+ struct bw_fixed stutter_refresh_duration[maximum_number_of_surfaces];
-+ struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces];
-+ struct bw_fixed stutter_entry_watermark[maximum_number_of_surfaces];
-+ struct bw_fixed h_total[maximum_number_of_surfaces];
-+ struct bw_fixed v_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 h_scale_ratio[maximum_number_of_surfaces];
-+ struct bw_fixed v_scale_ratio[maximum_number_of_surfaces];
-+ struct bw_fixed rotation_angle[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 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];
-+ 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 v_blank_dram_speed_change_margin[maximum_number_of_surfaces];
-+ uint32_t num_displays_with_margin[3][8];
-+ struct bw_fixed dmif_burst_time[3][8];
-+ struct bw_fixed mcifwr_burst_time[3][8];
-+ struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][8];
-+ struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8];
-+ struct bw_fixed min_dram_speed_change_margin[3][8];
-+ struct bw_fixed dispclk_required_for_dram_speed_change[3][8];
-+ struct bw_fixed blackout_duration_margin[3][8];
-+ struct bw_fixed dispclk_required_for_blackout_duration[3][8];
-+ struct bw_fixed dispclk_required_for_blackout_recovery[3][8];
-+ struct bw_fixed dmif_required_sclk_for_urgent_latency[6];
-+};
-+
-+/*******************************************************************************
-+ * Output data structures.
-+ ******************************************************************************/
-+struct bw_watermarks {
-+ uint32_t a_mark;
-+ uint32_t b_mark;
-+ uint32_t c_mark;
-+ uint32_t d_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[6];
-+ struct bw_watermarks stutter_exit_wm_ns[6];
-+ struct bw_watermarks nbp_state_change_wm_ns[6];
-+ uint32_t required_sclk;
-+ uint32_t required_sclk_deep_sleep;
-+ uint32_t required_yclk;
-+ uint32_t dispclk_khz;
-+ int blackout_recovery_time_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,
-+ enum bw_calcs_version version);
-+
-+/**
-+ * 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 pipe_ctx *pipe,
-+ int pipe_count,
-+ struct bw_calcs_output *calcs_output);
-+
-+#endif /* __BANDWIDTH_CALCS_H__ */
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
-new file mode 100644
-index 0000000..b31d07a
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
-@@ -0,0 +1,63 @@
-+/*
-+ * 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/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h
-new file mode 100644
-index 0000000..c91c781
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h
-@@ -0,0 +1,178 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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;
-+ uint32_t SUPPORT_YCBCR420: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 {
-+ const struct clock_source_funcs *funcs;
-+ struct dc_context *ctx;
-+ enum clock_source_id id;
-+ bool dp_clk_src;
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h
-new file mode 100644
-index 0000000..af29259
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.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_COMPRESSOR_H__
-+#define __DAL_COMPRESSOR_H__
-+
-+#include "include/grph_object_id.h"
-+#include "bios_parser_interface.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;
-+};
-+
-+enum fbc_hw_max_resolution_supported {
-+ FBC_MAX_X = 3840,
-+ FBC_MAX_Y = 2400
-+};
-+
-+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/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h
-new file mode 100644
-index 0000000..7d6dc8e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h
-@@ -0,0 +1,50 @@
-+/*
-+ * core_dc.h
-+ *
-+ * Created on: Nov 13, 2015
-+ * Author: yonsun
-+ */
-+
-+#ifndef __CORE_DC_H__
-+#define __CORE_DC_H__
-+
-+#include "core_types.h"
-+#include "hw_sequencer.h"
-+
-+#define DC_TO_CORE(dc)\
-+ container_of(dc, struct core_dc, public)
-+
-+struct core_dc {
-+ struct dc public;
-+ 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 validate_context *temp_flip_context;
-+ struct resource_pool *res_pool;
-+
-+ /*Power State*/
-+ enum dc_video_power_state previous_power_state;
-+ enum dc_video_power_state current_power_state;
-+
-+ /* Display Engine Clock levels */
-+ struct dm_pp_clock_levels sclk_lvls;
-+
-+ /* 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;
-+ struct dce_hwseq *hwseq;
-+
-+ /* temp store of dm_pp_display_configuration
-+ * to compare to see if display config changed
-+ */
-+ struct dm_pp_display_configuration prev_display_config;
-+};
-+
-+#endif /* __CORE_DC_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
-new file mode 100644
-index 0000000..32a2cc7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
-@@ -0,0 +1,47 @@
-+/*
-+ * 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_CLOCK_SOURCE_RESOURCE,
-+ DC_FAIL_CONTROLLER_VALIDATE,
-+ DC_FAIL_ENC_VALIDATE,
-+ DC_FAIL_ATTACH_SURFACES,
-+ DC_FAIL_SURFACE_VALIDATE,
-+ DC_NO_DP_LINK_BANDWIDTH,
-+ DC_EXCEED_DONGLE_MAX_CLK,
-+ DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED,
-+ DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */
-+
-+ DC_ERROR_UNEXPECTED = -1
-+};
-+
-+#endif /* _CORE_STATUS_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
-new file mode 100644
-index 0000000..f2eb894
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
-@@ -0,0 +1,319 @@
-+/*
-+ * 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"
-+#include "dc_bios_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_CLOCK_SOURCES 7
-+
-+struct core_target {
-+ struct dc_target public;
-+
-+ struct dc_context *ctx;
-+};
-+
-+/********* core_surface **********/
-+#define DC_SURFACE_TO_CORE(dc_surface) \
-+ container_of(dc_surface, struct core_surface, public)
-+
-+#define DC_GAMMA_TO_CORE(dc_gamma) \
-+ container_of(dc_gamma, struct core_gamma, public)
-+
-+struct core_surface {
-+ struct dc_surface public;
-+ struct dc_surface_status status;
-+ struct dc_context *ctx;
-+};
-+
-+struct core_gamma {
-+ struct dc_gamma public;
-+ 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.h"
-+#include "hw_sequencer_types.h"
-+#include "opp.h"
-+
-+#define DC_STREAM_TO_CORE(dc_stream) container_of( \
-+ dc_stream, struct core_stream, public)
-+
-+struct core_stream {
-+ struct dc_stream public;
-+
-+ /* field internal to DC */
-+ struct dc_context *ctx;
-+ const struct core_sink *sink;
-+
-+ /* used by DCP and FMT */
-+ struct bit_depth_reduction_params bit_depth_params;
-+ struct clamping_and_pixel_encoding_params clamping;
-+
-+ int phy_pix_clk;
-+ enum signal_type signal;
-+
-+ struct dc_stream_status status;
-+};
-+
-+/************ 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 core_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. */
-+};
-+
-+/* 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 core_dc *dc;
-+
-+ struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/
-+
-+ 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;
-+ 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;
-+
-+ struct dc_link_status link_status;
-+};
-+
-+#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_stream *stream,
-+ struct core_link *link,
-+ const struct dc_crtc_timing *timing);
-+
-+void core_link_resume(struct core_link *link);
-+
-+void core_link_enable_stream(struct pipe_ctx *pipe_ctx);
-+
-+void core_link_disable_stream(struct pipe_ctx *pipe_ctx);
-+
-+/********** DAL Core*********************/
-+#include "display_clock_interface.h"
-+#include "transform.h"
-+
-+struct resource_pool;
-+struct validate_context;
-+struct resource_context;
-+
-+struct resource_funcs {
-+ void (*destroy)(struct resource_pool **pool);
-+ struct link_encoder *(*link_enc_create)(
-+ const struct encoder_init_data *init);
-+ enum dc_status (*validate_with_context)(
-+ const struct core_dc *dc,
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ struct validate_context *context);
-+
-+ enum dc_status (*validate_guaranteed)(
-+ const struct core_dc *dc,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context);
-+
-+ enum dc_status (*validate_bandwidth)(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+ struct validate_context *(*apply_clk_constraints)(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+ struct pipe_ctx *(*acquire_idle_pipe_for_layer)(
-+ struct resource_context *res_ctx,
-+ struct core_stream *stream);
-+
-+ void (*build_bit_depth_reduction_params)(
-+ const struct core_stream *stream,
-+ struct bit_depth_reduction_params *fmt_bit_depth);
-+};
-+
-+struct audio_support{
-+ bool dp_audio;
-+ bool hdmi_audio_on_dongle;
-+ bool hdmi_audio_native;
-+};
-+
-+struct resource_pool {
-+ 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_PIPES];
-+ struct stream_encoder *stream_enc[MAX_PIPES * 2];
-+
-+ unsigned int pipe_count;
-+ unsigned int underlay_pipe_index;
-+ unsigned int stream_enc_count;
-+
-+ /*
-+ * reserved clock source for DP
-+ */
-+ struct clock_source *dp_clock_source;
-+
-+ struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
-+ unsigned int clk_src_count;
-+
-+ struct audio *audios[MAX_PIPES];
-+ unsigned int audio_count;
-+ struct audio_support audio_support;
-+
-+ struct display_clock *display_clock;
-+ struct irq_service *irqs;
-+
-+ const struct resource_funcs *funcs;
-+ const struct resource_caps *res_cap;
-+};
-+
-+struct pipe_ctx {
-+ struct core_surface *surface;
-+ struct core_stream *stream;
-+
-+ struct mem_input *mi;
-+ struct input_pixel_processor *ipp;
-+ struct transform *xfm;
-+ struct output_pixel_processor *opp;
-+ struct timing_generator *tg;
-+
-+ struct scaler_data scl_data;
-+
-+ struct stream_encoder *stream_enc;
-+ struct display_clock *dis_clk;
-+ struct clock_source *clock_source;
-+
-+ struct audio *audio;
-+
-+ struct pixel_clk_params pix_clk_params;
-+ struct pll_settings pll_settings;
-+
-+ /*fmt*/
-+ struct encoder_info_frame encoder_info_frame;
-+
-+ uint8_t pipe_idx;
-+
-+ struct pipe_ctx *top_pipe;
-+ struct pipe_ctx *bottom_pipe;
-+};
-+
-+struct resource_context {
-+ const struct resource_pool *pool;
-+ struct pipe_ctx pipe_ctx[MAX_PIPES];
-+ bool is_stream_enc_acquired[MAX_PIPES * 2];
-+ bool is_audio_acquired[MAX_PIPES];
-+ uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
-+ uint8_t dp_clock_source_ref_count;
-+ };
-+
-+struct validate_context {
-+ struct core_target *targets[MAX_PIPES];
-+ struct dc_target_status target_status[MAX_PIPES];
-+ uint8_t target_count;
-+
-+ struct resource_context res_ctx;
-+
-+ /* The output from BW and WM calculations. */
-+ struct bw_calcs_output bw_results;
-+ /* Note: this is a big structure, do *not* put on stack! */
-+ struct dm_pp_display_configuration pp_display_cfg;
-+};
-+
-+#endif /* _CORE_TYPES_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
-new file mode 100644
-index 0000000..830fc3d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
-@@ -0,0 +1,145 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 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 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);
-+
-+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);
-+
-+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/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
-new file mode 100644
-index 0000000..b0cf8e0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
-@@ -0,0 +1,60 @@
-+/*
-+ * 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__
-+
-+#define LINK_TRAINING_ATTEMPTS 4
-+#define LINK_TRAINING_RETRY_DELAY 50 /* ms */
-+
-+struct core_link;
-+struct core_stream;
-+struct dc_link_settings;
-+
-+bool dp_hbr_verify_link_cap(
-+ struct core_link *link,
-+ struct dc_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 dc_link_settings *link_setting);
-+
-+bool perform_link_training_with_retries(
-+ struct core_link *link,
-+ const struct dc_link_settings *link_setting,
-+ bool skip_video_pattern,
-+ int attempts);
-+
-+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/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
-new file mode 100644
-index 0000000..e2c63fd
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
-@@ -0,0 +1,19 @@
-+/*
-+ * gamma_calcs.h
-+ *
-+ * Created on: Feb 9, 2016
-+ * Author: yonsun
-+ */
-+
-+#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
-+
-+#include "opp.h"
-+#include "core_types.h"
-+#include "dc.h"
-+
-+bool calculate_regamma_params(struct pwl_params *params,
-+ const struct core_gamma *ramp,
-+ const struct core_surface *surface);
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h
-new file mode 100644
-index 0000000..7948d2c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.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 GAMMA_TYPES_H_
-+
-+#define GAMMA_TYPES_H_
-+
-+#include "dc_types.h"
-+
-+/* TODO: Used in IPP and OPP */
-+
-+struct dev_c_lut16 {
-+ uint16_t red;
-+ uint16_t green;
-+ uint16_t blue;
-+};
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h
-new file mode 100644
-index 0000000..925204f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.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_AUDIO_H__
-+#define __DAL_AUDIO_H__
-+
-+#include "audio_types.h"
-+
-+struct audio;
-+
-+struct audio_funcs {
-+
-+ bool (*endpoint_valid)(struct audio *audio);
-+
-+ void (*hw_init)(struct audio *audio);
-+
-+ void (*az_enable)(struct audio *audio);
-+
-+ void (*az_disable)(struct audio *audio);
-+
-+ void (*az_configure)(struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_info *audio_info);
-+
-+ void (*wall_dto_setup)(struct audio *audio,
-+ enum signal_type signal,
-+ const struct audio_crtc_info *crtc_info,
-+ const struct audio_pll_info *pll_info);
-+
-+ void (*destroy)(struct audio **audio);
-+};
-+
-+struct audio {
-+ const struct audio_funcs *funcs;
-+ struct dc_context *ctx;
-+ unsigned int inst;
-+};
-+
-+#endif /* __DAL_AUDIO__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h
-new file mode 100644
-index 0000000..90d0148
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h
-@@ -0,0 +1,86 @@
-+/*
-+ * 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_GPIO_H__
-+#define __DAL_GPIO_H__
-+
-+#include "gpio_types.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;
-+};
-+
-+#if 0
-+struct gpio_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);
-+
-+ /* HW translation */
-+ 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);
-+};
-+#endif
-+
-+#endif /* __DAL_GPIO__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
-new file mode 100644
-index 0000000..3b0e616
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
-@@ -0,0 +1,74 @@
-+/*
-+ * 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_HW_SHARED_H__
-+#define __DAL_HW_SHARED_H__
-+
-+/******************************************************************************
-+ * Data types shared between different Virtual HW blocks
-+ ******************************************************************************/
-+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;
-+};
-+
-+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 pwl_params {
-+ uint32_t *data;
-+ struct gamma_curve arr_curve_points[16];
-+ struct curve_points arr_points[3];
-+ struct pwl_result_data rgb_resulted[256 + 3];
-+ uint32_t hw_points_num;
-+};
-+#endif /* __DAL_HW_SHARED_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
-new file mode 100644
-index 0000000..7e5f3e0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
-@@ -0,0 +1,121 @@
-+/*
-+ * 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 "hw_shared.h"
-+
-+#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;
-+ const struct ipp_funcs *funcs;
-+};
-+
-+enum ipp_prescale_mode {
-+ IPP_PRESCALE_MODE_BYPASS,
-+ IPP_PRESCALE_MODE_FIXED_SIGNED,
-+ IPP_PRESCALE_MODE_FLOAT_SIGNED,
-+ IPP_PRESCALE_MODE_FIXED_UNSIGNED,
-+ IPP_PRESCALE_MODE_FLOAT_UNSIGNED
-+};
-+
-+struct ipp_prescale_params {
-+ enum ipp_prescale_mode mode;
-+ uint16_t bias;
-+ uint16_t scale;
-+};
-+
-+enum ipp_degamma_mode {
-+ IPP_DEGAMMA_MODE_BYPASS,
-+ IPP_DEGAMMA_MODE_HW_sRGB,
-+ IPP_DEGAMMA_MODE_HW_xvYCC,
-+ IPP_DEGAMMA_MODE_USER_PWL
-+};
-+
-+enum ovl_color_space {
-+ OVL_COLOR_SPACE_UNKNOWN = 0,
-+ OVL_COLOR_SPACE_RGB,
-+ OVL_COLOR_SPACE_YUV601,
-+ OVL_COLOR_SPACE_YUV709
-+};
-+
-+enum expansion_mode {
-+ EXPANSION_MODE_DYNAMIC,
-+ EXPANSION_MODE_ZERO
-+};
-+
-+enum ipp_output_format {
-+ IPP_OUTPUT_FORMAT_12_BIT_FIX,
-+ IPP_OUTPUT_FORMAT_16_BIT_BYPASS,
-+ IPP_OUTPUT_FORMAT_FLOAT
-+};
-+
-+struct ipp_funcs {
-+
-+ /*** cursor ***/
-+ void (*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);
-+
-+ /*** setup input pixel processing ***/
-+
-+ /* put the entire pixel processor to bypass */
-+ void (*ipp_full_bypass)(
-+ struct input_pixel_processor *ipp);
-+
-+ /* setup ipp to expand/convert input to pixel processor internal format */
-+ void (*ipp_setup)(
-+ struct input_pixel_processor *ipp,
-+ enum surface_pixel_format input_format,
-+ enum expansion_mode mode,
-+ enum ipp_output_format output_format);
-+
-+ /* DCE function to setup IPP. TODO: see if we can consolidate to setup */
-+ void (*ipp_program_prescale)(
-+ struct input_pixel_processor *ipp,
-+ struct ipp_prescale_params *params);
-+
-+ /*** DEGAMMA RELATED ***/
-+ bool (*ipp_set_degamma)(
-+ struct input_pixel_processor *ipp,
-+ enum ipp_degamma_mode mode);
-+
-+ bool (*ipp_program_degamma_pwl)(
-+ struct input_pixel_processor *ipp,
-+ const struct pwl_params *params);
-+
-+};
-+
-+#endif /* __DAL_IPP_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
-new file mode 100644
-index 0000000..77f8aa4
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
-@@ -0,0 +1,263 @@
-+/*
-+ * link_encoder.h
-+ *
-+ * Created on: Oct 6, 2015
-+ * Author: yonsun
-+ */
-+
-+#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 encoder_set_dp_phy_pattern_param;
-+struct link_mst_stream_allocation_table;
-+struct dc_link_settings;
-+struct link_training_settings;
-+struct core_stream;
-+struct pipe_ctx;
-+
-+struct encoder_init_data {
-+ 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_HBR3_CAPABLE:1;
-+ uint32_t IS_HBR2_VALIDATED:1;
-+ uint32_t IS_TPS3_CAPABLE:1;
-+ uint32_t IS_TPS4_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;
-+ enum dc_color_depth max_hdmi_deep_color;
-+ /* maximum supported clock */
-+ unsigned int max_pixel_clock;
-+ unsigned int max_hdmi_pixel_clock;
-+ bool ycbcr420_supported;
-+};
-+
-+enum physical_phy_id {
-+ PHYLD_0,
-+ PHYLD_1,
-+ PHYLD_2,
-+ PHYLD_3,
-+ PHYLD_4,
-+ PHYLD_5,
-+ PHYLD_6,
-+ PHYLD_7,
-+ PHYLD_8,
-+ PHYLD_9,
-+ PHYLD_COUNT,
-+ PHYLD_UNKNOWN = (-1L)
-+};
-+
-+enum phy_type {
-+ PHY_TYPE_UNKNOWN = 1,
-+ PHY_TYPE_PCIE_PHY = 2,
-+ PHY_TYPE_UNIPHY = 3,
-+};
-+
-+union dmcu_psr_level {
-+ struct {
-+ unsigned int SKIP_CRC:1;
-+ unsigned int SKIP_DP_VID_STREAM_DISABLE:1;
-+ unsigned int SKIP_PHY_POWER_DOWN:1;
-+ unsigned int SKIP_AUX_ACK_CHECK:1;
-+ unsigned int SKIP_CRTC_DISABLE:1;
-+ unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1;
-+ unsigned int SKIP_SMU_NOTIFICATION:1;
-+ unsigned int SKIP_AUTO_STATE_ADVANCE:1;
-+ unsigned int DISABLE_PSR_ENTRY_ABORT:1;
-+ unsigned int RESERVED:23;
-+ } bits;
-+ unsigned int u32all;
-+};
-+
-+union dpcd_psr_configuration {
-+ struct {
-+ unsigned char ENABLE : 1;
-+ unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1;
-+ unsigned char CRC_VERIFICATION : 1;
-+ unsigned char FRAME_CAPTURE_INDICATION : 1;
-+ /* For eDP 1.4, PSR v2*/
-+ unsigned char LINE_CAPTURE_INDICATION : 1;
-+ /* For eDP 1.4, PSR v2*/
-+ unsigned char IRQ_HPD_WITH_CRC_ERROR : 1;
-+ unsigned char RESERVED : 2;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+union psr_error_status {
-+ struct {
-+ unsigned char LINK_CRC_ERROR :1;
-+ unsigned char RFB_STORAGE_ERROR :1;
-+ unsigned char RESERVED :6;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+union psr_sink_psr_status {
-+ struct {
-+ unsigned char SINK_SELF_REFRESH_STATUS :3;
-+ unsigned char RESERVED :5;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+struct psr_dmcu_context {
-+ /* ddc line */
-+ enum channel_id channel;
-+ /* Transmitter id */
-+ enum transmitter transmitterId;
-+ /* Engine Id is used for Dig Be source select */
-+ enum engine_id engineId;
-+ /* Controller Id used for Dig Fe source select */
-+ enum controller_id controllerId;
-+ /* Pcie or Uniphy */
-+ enum phy_type phyType;
-+ /* Physical PHY Id used by SMU interpretation */
-+ enum physical_phy_id smuPhyId;
-+ /* 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.
-+ */
-+ unsigned int crtcTimingVerticalTotal;
-+ /* PSR supported from panel capabilities and
-+ * current display configuration
-+ */
-+ bool psrSupportedDisplayConfig;
-+ /* Whether fast link training is supported by the panel */
-+ bool psrExitLinkTrainingRequired;
-+ /* 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 psrFrameCaptureIndicationReq;
-+ /* Set the last possible line SDP may be transmitted without violating
-+ * the RFB setup time or entering the active video frame.
-+ */
-+ unsigned int sdpTransmitLineNumDeadline;
-+ /* The VSync rate in Hz used to calculate the
-+ * step size for smooth brightness feature
-+ */
-+ unsigned int vsyncRateHz;
-+ unsigned int skipPsrWaitForPllLock;
-+ unsigned int numberOfControllers;
-+ /* Unused, for future use. To indicate that first changed frame from
-+ * state3 shouldn't result in psr_inactive, but rather to perform
-+ * an automatic single frame rfb_update.
-+ */
-+ bool rfb_update_auto_en;
-+ /* Number of frame before entering static screen */
-+ unsigned int timehyst_frames;
-+ /* Partial frames before entering static screen */
-+ unsigned int hyst_lines;
-+ /* # of repeated AUX transaction attempts to make before
-+ * indicating failure to the driver
-+ */
-+ unsigned int aux_repeats;
-+ /* Controls hw blocks to power down during PSR active state */
-+ union dmcu_psr_level psr_level;
-+ /* Controls additional delay after remote frame capture before
-+ * continuing powerd own
-+ */
-+ unsigned int frame_delay;
-+};
-+
-+
-+struct link_encoder {
-+ const struct link_encoder_funcs *funcs;
-+ 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 pipe_ctx *pipe_ctx);
-+ 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 dc_link_settings *link_settings,
-+ enum clock_source_id clock_source);
-+ void (*enable_dp_mst_output)(struct link_encoder *enc,
-+ const struct dc_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 (*set_dmcu_backlight_level)(struct link_encoder *enc,
-+ uint32_t level, uint32_t frame_ramp, uint32_t controller_id);
-+ void (*init_dmcu_backlight_settings)(struct link_encoder *enc);
-+ void (*set_dmcu_abm_level)(struct link_encoder *enc, uint32_t level);
-+ void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable);
-+ void (*setup_dmcu_psr)(struct link_encoder *enc,
-+ struct psr_dmcu_context *psr_context);
-+ 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);
-+ void (*enable_hpd)(struct link_encoder *enc);
-+ void (*disable_hpd)(struct link_encoder *enc);
-+ void (*destroy)(struct link_encoder **enc);
-+};
-+
-+#endif /* LINK_ENCODER_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
-new file mode 100644
-index 0000000..78dab74
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
-@@ -0,0 +1,106 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "dc.h"
-+#include "include/grph_object_id.h"
-+#include "inc/bandwidth_calcs.h"
-+
-+#include "dce/dce_mem_input.h" /* temporary */
-+
-+struct stutter_modes {
-+ bool enhanced;
-+ bool quad_dmif_buffer;
-+ bool watermark_nb_pstate;
-+};
-+
-+struct mem_input {
-+ struct mem_input_funcs *funcs;
-+ struct dc_context *ctx;
-+ struct dc_plane_address request_address;
-+ struct dc_plane_address current_address;
-+ uint32_t inst;
-+ struct stutter_modes stutter_mode;
-+
-+ const struct dce_mem_input_registers *regs;
-+ const struct dce_mem_input_shift *shifts;
-+ const struct dce_mem_input_mask *masks;
-+ struct dce_mem_input_wa wa;
-+};
-+
-+struct mem_input_funcs {
-+ 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 total_dest_line_time_ns);
-+
-+ void (*mem_input_program_chroma_display_marks)(
-+ struct mem_input *mem_input,
-+ struct bw_watermarks nbp,
-+ struct bw_watermarks stutter,
-+ struct bw_watermarks urgent,
-+ uint32_t total_dest_line_time_ns);
-+
-+ void (*allocate_mem_input)(
-+ struct mem_input *mem_input,
-+ uint32_t h_total,/* for current target */
-+ uint32_t v_total,/* for current target */
-+ uint32_t pix_clk_khz,/* for current target */
-+ uint32_t total_streams_num);
-+
-+ void (*free_mem_input)(
-+ 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_pte_vm)(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ enum dc_rotation_angle rotation);
-+
-+ bool (*mem_input_program_surface_config)(
-+ struct mem_input *mem_input,
-+ enum surface_pixel_format format,
-+ union dc_tiling_info *tiling_info,
-+ union plane_size *plane_size,
-+ enum dc_rotation_angle rotation,
-+ struct dc_plane_dcc_param *dcc,
-+ bool horizontal_mirror);
-+
-+ bool (*mem_input_is_flip_pending)(struct mem_input *mem_input);
-+
-+ void (*mem_input_update_dchub)(struct mem_input *mem_input,
-+ struct dchub_init_data *dh_data);
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
-new file mode 100644
-index 0000000..e615997
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
-@@ -0,0 +1,322 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "hw_shared.h"
-+#include "transform.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 gamma_pixel {
-+ struct fixed31_32 r;
-+ struct fixed31_32 g;
-+ struct fixed31_32 b;
-+};
-+
-+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 pwl_float_data {
-+ struct fixed31_32 r;
-+ struct fixed31_32 g;
-+ struct fixed31_32 b;
-+};
-+
-+enum opp_regamma {
-+ OPP_REGAMMA_BYPASS = 0,
-+ OPP_REGAMMA_SRGB,
-+ OPP_REGAMMA_3_6,
-+ OPP_REGAMMA_USER,
-+};
-+
-+struct output_pixel_processor {
-+ struct dc_context *ctx;
-+ uint32_t inst;
-+ const struct opp_funcs *funcs;
-+};
-+
-+enum fmt_stereo_action {
-+ FMT_STEREO_ACTION_ENABLE = 0,
-+ FMT_STEREO_ACTION_DISABLE,
-+ FMT_STEREO_ACTION_UPDATE_POLARITY
-+};
-+
-+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 */
-+};
-+
-+struct default_adjustment {
-+ enum lb_pixel_depth lb_color_depth;
-+ enum dc_color_space out_color_space;
-+ enum dc_color_space in_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;
-+};
-+
-+enum grph_color_adjust_option {
-+ GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
-+ GRPH_COLOR_MATRIX_SW
-+};
-+
-+struct opp_grph_csc_adjustment {
-+ enum grph_color_adjust_option color_adjust_option;
-+ enum dc_color_space c_space;
-+ enum dc_color_depth color_depth; /* clean up to uint32_t */
-+ enum graphics_csc_adjust_type csc_adjust_type;
-+ int32_t adjust_divider;
-+ int32_t grph_cont;
-+ int32_t grph_sat;
-+ int32_t grph_bright;
-+ int32_t grph_hue;
-+};
-+
-+struct out_csc_color_matrix {
-+ enum dc_color_space color_space;
-+ uint16_t regval[12];
-+};
-+
-+/* Underlay related types */
-+
-+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) */
-+};
-+
-+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 opp_funcs {
-+ void (*opp_power_on_regamma_lut)(
-+ struct output_pixel_processor *opp,
-+ bool power_on);
-+
-+ bool (*opp_program_regamma_pwl)(
-+ struct output_pixel_processor *opp,
-+ const struct pwl_params *params);
-+
-+ void (*opp_set_regamma_mode)(struct output_pixel_processor *opp,
-+ enum opp_regamma mode);
-+
-+ void (*opp_set_csc_adjustment)(
-+ struct output_pixel_processor *opp,
-+ const struct out_csc_color_matrix *tbl_entry);
-+
-+ void (*opp_set_csc_default)(
-+ struct output_pixel_processor *opp,
-+ const struct default_adjustment *default_adjust);
-+
-+ /* FORMATTER RELATED */
-+
-+ void (*opp_program_fmt)(
-+ struct output_pixel_processor *opp,
-+ struct bit_depth_reduction_params *fmt_bit_depth,
-+ struct clamping_and_pixel_encoding_params *clamping);
-+
-+ void (*opp_set_dyn_expansion)(
-+ struct output_pixel_processor *opp,
-+ enum dc_color_space color_sp,
-+ enum dc_color_depth color_dpth,
-+ enum signal_type signal);
-+
-+ void (*opp_program_bit_depth_reduction)(
-+ struct output_pixel_processor *opp,
-+ const struct bit_depth_reduction_params *params);
-+
-+ /* underlay related */
-+ void (*opp_get_underlay_adjustment_range)(
-+ struct output_pixel_processor *opp,
-+ enum ovl_csc_adjust_item overlay_adjust_item,
-+ struct hw_adjustment_range *range);
-+
-+ void (*opp_destroy)(struct output_pixel_processor **opp);
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
-new file mode 100644
-index 0000000..9caf2b3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
-@@ -0,0 +1,121 @@
-+/*
-+ * stream_encoder.h
-+ *
-+ */
-+
-+#ifndef STREAM_ENCODER_H_
-+#define STREAM_ENCODER_H_
-+
-+#include "include/hw_sequencer_types.h"
-+#include "audio_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 dc_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 {
-+ const 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,
-+ enum dc_color_space output_color_space);
-+
-+ void (*hdmi_set_stream_attribute)(
-+ struct stream_encoder *enc,
-+ struct dc_crtc_timing *crtc_timing,
-+ int actual_pix_clk_khz,
-+ 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);
-+
-+ void (*audio_mute_control)(
-+ struct stream_encoder *enc, bool mute);
-+
-+ void (*dp_audio_setup)(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info);
-+
-+ void (*dp_audio_enable) (
-+ struct stream_encoder *enc);
-+
-+ void (*dp_audio_disable) (
-+ struct stream_encoder *enc);
-+
-+ void (*hdmi_audio_setup)(
-+ struct stream_encoder *enc,
-+ unsigned int az_inst,
-+ struct audio_info *info,
-+ struct audio_crtc_info *audio_crtc_info);
-+
-+ void (*hdmi_audio_disable) (
-+ struct stream_encoder *enc);
-+};
-+
-+#endif /* STREAM_ENCODER_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
-new file mode 100644
-index 0000000..6ac609f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
-@@ -0,0 +1,162 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__
-+
-+struct dc_bios;
-+
-+/**
-+ * These parameters are required as input when doing blanking/Unblanking
-+*/
-+#define MAX_TG_COLOR_VALUE 0x3FF
-+
-+struct tg_color {
-+ /* Maximum 10 bits color value */
-+ uint16_t color_r_cr;
-+ uint16_t color_g_y;
-+ uint16_t color_b_cb;
-+};
-+
-+/* Contains CRTC vertical/horizontal pixel counters */
-+struct crtc_position {
-+ uint32_t vertical_count;
-+ uint32_t horizontal_count;
-+ uint32_t nominal_vcount;
-+};
-+
-+struct dcp_gsl_params {
-+ int gsl_group;
-+ int gsl_master;
-+};
-+
-+#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 {
-+ const struct timing_generator_funcs *funcs;
-+ struct dc_bios *bp;
-+ struct dc_context *ctx;
-+ int inst;
-+};
-+
-+struct dc_crtc_timing;
-+
-+struct drr_params;
-+
-+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);
-+ uint32_t (*get_scanoutpos)(
-+ struct timing_generator *tg,
-+ uint32_t *vbl,
-+ uint32_t *position);
-+ 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);
-+ bool (*is_blanked)(struct timing_generator *tg);
-+ void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color);
-+ void (*set_blank_color)(struct timing_generator *tg, const struct tg_color *color);
-+ void (*set_colors)(struct timing_generator *tg,
-+ const struct tg_color *blank_color,
-+ const struct tg_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 (*unlock)(struct timing_generator *tg);
-+ void (*lock)(struct timing_generator *tg);
-+ void (*enable_reset_trigger)(struct timing_generator *tg, int source_tg_inst);
-+ 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);
-+ void (*set_drr)(struct timing_generator *tg, const struct drr_params *params);
-+ void (*set_static_screen_control)(struct timing_generator *tg,
-+ uint32_t value);
-+ void (*set_test_pattern)(
-+ struct timing_generator *tg,
-+ enum controller_dp_test_pattern test_pattern,
-+ enum dc_color_depth color_depth);
-+
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
-new file mode 100644
-index 0000000..ef743b7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
-@@ -0,0 +1,179 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "dc_hw_types.h"
-+#include "fixed31_32.h"
-+
-+#define CSC_TEMPERATURE_MATRIX_SIZE 9
-+
-+struct bit_depth_reduction_params;
-+
-+struct transform {
-+ const struct transform_funcs *funcs;
-+ struct dc_context *ctx;
-+ int inst;
-+};
-+
-+/* Colorimetry */
-+enum colorimetry {
-+ COLORIMETRY_NO_DATA = 0,
-+ COLORIMETRY_ITU601 = 1,
-+ COLORIMETRY_ITU709 = 2,
-+ COLORIMETRY_EXTENDED = 3
-+};
-+
-+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
-+};
-+
-+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 xfm_grph_csc_adjustment {
-+ struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
-+ enum graphics_gamut_adjust_type gamut_adjust_type;
-+};
-+
-+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 overscan_info {
-+ int left;
-+ int right;
-+ int top;
-+ int bottom;
-+};
-+
-+struct scaling_ratios {
-+ struct fixed31_32 horz;
-+ struct fixed31_32 vert;
-+ struct fixed31_32 horz_c;
-+ struct fixed31_32 vert_c;
-+};
-+
-+struct sharpness_adj {
-+ int horz;
-+ int vert;
-+};
-+
-+struct line_buffer_params {
-+ bool alpha_en;
-+ bool pixel_expan_mode;
-+ bool interleave_en;
-+ int dynamic_pixel_depth;
-+ enum lb_pixel_depth depth;
-+};
-+
-+struct scaler_data {
-+ int h_active;
-+ int v_active;
-+ struct scaling_taps taps;
-+ struct rect viewport;
-+ struct rect recout;
-+ struct scaling_ratios ratios;
-+ struct sharpness_adj sharpness;
-+ enum pixel_format format;
-+ struct line_buffer_params lb_params;
-+};
-+
-+struct transform_funcs {
-+ void (*transform_reset)(struct transform *xfm);
-+
-+ void (*transform_set_scaler)(struct transform *xfm,
-+ const struct scaler_data *scl_data);
-+
-+ void (*transform_set_gamut_remap)(
-+ struct transform *xfm,
-+ const struct xfm_grph_csc_adjustment *adjust);
-+
-+ void (*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_optimal_number_of_taps)(
-+ struct transform *xfm,
-+ struct scaler_data *scl_data,
-+ const struct scaling_taps *in_taps);
-+};
-+
-+extern const uint16_t filter_2tap_16p[18];
-+extern const uint16_t filter_2tap_64p[66];
-+const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio);
-+const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio);
-+const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio);
-+const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
-new file mode 100644
-index 0000000..35a556d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
-@@ -0,0 +1,156 @@
-+/*
-+ * 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"
-+#include "timing_generator.h"
-+
-+struct gamma_parameters;
-+
-+enum pipe_gating_control {
-+ PIPE_GATING_CONTROL_DISABLE = 0,
-+ PIPE_GATING_CONTROL_ENABLE,
-+ PIPE_GATING_CONTROL_INIT
-+};
-+
-+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
-+};
-+
-+struct dce_hwseq;
-+
-+struct hw_sequencer_funcs {
-+
-+ void (*init_hw)(struct core_dc *dc);
-+
-+ enum dc_status (*apply_ctx_to_hw)(
-+ struct core_dc *dc, struct validate_context *context);
-+
-+ void (*reset_hw_ctx_wrap)(
-+ struct core_dc *dc, struct validate_context *context);
-+
-+ void (*prepare_pipe_for_context)(
-+ struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context);
-+
-+ void (*apply_ctx_for_surface)(
-+ struct core_dc *dc,
-+ struct core_surface *surface,
-+ struct validate_context *context);
-+
-+ void (*set_plane_config)(
-+ const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct resource_context *res_ctx);
-+
-+ void (*update_plane_addr)(
-+ const struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx);
-+
-+ void (*update_pending_status)(
-+ struct pipe_ctx *pipe_ctx);
-+
-+ bool (*set_gamma_correction)(
-+ struct input_pixel_processor *ipp,
-+ struct output_pixel_processor *opp,
-+ const struct core_gamma *ramp,
-+ const struct core_surface *surface);
-+
-+ void (*power_down)(struct core_dc *dc);
-+
-+ void (*enable_accelerated_mode)(struct core_dc *dc);
-+
-+ void (*enable_timing_synchronization)(
-+ struct core_dc *dc,
-+ int group_index,
-+ int group_size,
-+ struct pipe_ctx *grouped_pipes[]);
-+
-+ /* backlight control */
-+ void (*encoder_set_lcd_backlight_level)(
-+ struct link_encoder *enc, uint32_t level);
-+
-+ void (*enable_display_pipe_clock_gating)(
-+ struct dc_context *ctx,
-+ bool clock_gating);
-+
-+ bool (*enable_display_power_gating)(
-+ struct core_dc *dc,
-+ uint8_t controller_id,
-+ struct dc_bios *dcb,
-+ enum pipe_gating_control power_gating);
-+
-+ void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe);
-+ void (*update_info_frame)(struct pipe_ctx *pipe_ctx);
-+
-+ void (*enable_stream)(struct pipe_ctx *pipe_ctx);
-+
-+ void (*disable_stream)(struct pipe_ctx *pipe_ctx);
-+
-+ void (*unblank_stream)(struct pipe_ctx *pipe_ctx,
-+ struct dc_link_settings *link_settings);
-+
-+ void (*pipe_control_lock)(
-+ struct dce_hwseq *hwseq,
-+ unsigned int blnd_inst,
-+ enum pipe_lock_control control_mask,
-+ bool lock);
-+
-+ void (*set_displaymarks)(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+ void (*increase_watermarks_for_pipe)(struct core_dc *dc,
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context);
-+
-+ void (*set_display_clock)(struct validate_context *context);
-+
-+ void (*set_bandwidth)(struct core_dc *dc);
-+
-+ void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes,
-+ int vmin, int vmax);
-+
-+ void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
-+ int num_pipes, int value);
-+
-+ enum dc_status (*prog_pixclk_crtc_otg)(
-+ struct pipe_ctx *pipe_ctx,
-+ struct validate_context *context,
-+ struct core_dc *dc);
-+};
-+
-+void color_space_to_black_color(
-+ const struct core_dc *dc,
-+ enum dc_color_space colorspace,
-+ struct tg_color *black_color);
-+
-+#endif /* __DC_HW_SEQUENCER_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
-new file mode 100644
-index 0000000..662fa30
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
-@@ -0,0 +1,73 @@
-+/*
-+ * 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,
-+ enum clock_source_id clock_source,
-+ const struct dc_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, enum signal_type signal);
-+
-+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,
-+ uint8_t *custom_pattern,
-+ uint32_t custom_pattern_size);
-+
-+enum dp_panel_mode dp_get_panel_mode(struct core_link *link);
-+
-+void dp_retrain_link(struct core_link *link);
-+
-+#endif /* __DC_LINK_HWSS_H__ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
-new file mode 100644
-index 0000000..159b2c5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
-@@ -0,0 +1,290 @@
-+/*
-+ * 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 DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
-+
-+#include "dm_services.h"
-+
-+/* macro for register read/write
-+ * user of macro need to define
-+ *
-+ * CTX ==> macro to ptr to dc_context
-+ * eg. aud110->base.ctx
-+ *
-+ * REG ==> macro to location of register offset
-+ * eg. aud110->regs->reg
-+ */
-+#define REG_READ(reg_name) \
-+ dm_read_reg(CTX, REG(reg_name))
-+
-+#define REG_WRITE(reg_name, value) \
-+ dm_write_reg(CTX, REG(reg_name), value)
-+
-+#ifdef REG_SET
-+#undef REG_SET
-+#endif
-+
-+#ifdef REG_GET
-+#undef REG_GET
-+#endif
-+
-+/* macro to set register fields. */
-+#define REG_SET_N(reg_name, n, initial_val, ...) \
-+ generic_reg_update_ex(CTX, \
-+ REG(reg_name), \
-+ initial_val, \
-+ n, __VA_ARGS__)
-+
-+#define FN(reg_name, field) \
-+ FD(reg_name##__##field)
-+
-+#define REG_SET(reg_name, initial_val, field, val) \
-+ REG_SET_N(reg_name, 1, initial_val, \
-+ FN(reg_name, field), val)
-+
-+#define REG_SET_2(reg, init_value, f1, v1, f2, v2) \
-+ REG_SET_N(reg, 2, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2)
-+
-+#define REG_SET_3(reg, init_value, f1, v1, f2, v2, f3, v3) \
-+ REG_SET_N(reg, 3, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2,\
-+ FN(reg, f3), v3)
-+
-+#define REG_SET_4(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4) \
-+ REG_SET_N(reg, 4, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2,\
-+ FN(reg, f3), v3,\
-+ FN(reg, f4), v4)
-+
-+#define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \
-+ f5, v5) \
-+ REG_SET_N(reg, 6, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2,\
-+ FN(reg, f3), v3,\
-+ FN(reg, f4), v4,\
-+ FN(reg, f5), v5)
-+
-+#define REG_SET_6(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \
-+ f5, v5, f6, v6) \
-+ REG_SET_N(reg, 6, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2,\
-+ FN(reg, f3), v3,\
-+ FN(reg, f4), v4,\
-+ FN(reg, f5), v5,\
-+ FN(reg, f6), v6)
-+
-+#define REG_SET_7(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \
-+ f5, v5, f6, v6, f7, v7) \
-+ REG_SET_N(reg, 7, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2,\
-+ FN(reg, f3), v3,\
-+ FN(reg, f4), v4,\
-+ FN(reg, f5), v5,\
-+ FN(reg, f6), v6,\
-+ FN(reg, f7), v7)
-+
-+#define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \
-+ v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \
-+ REG_SET_N(reg, 10, init_value, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6, \
-+ FN(reg, f7), v7, \
-+ FN(reg, f8), v8, \
-+ FN(reg, f9), v9, \
-+ FN(reg, f10), v10)
-+
-+/* macro to get register fields
-+ * read given register and fill in field value in output parameter */
-+#define REG_GET(reg_name, field, val) \
-+ generic_reg_get(CTX, REG(reg_name), \
-+ FN(reg_name, field), val)
-+
-+#define REG_GET_2(reg_name, f1, v1, f2, v2) \
-+ generic_reg_get2(CTX, REG(reg_name), \
-+ FN(reg_name, f1), v1, \
-+ FN(reg_name, f2), v2)
-+
-+#define REG_GET_3(reg_name, f1, v1, f2, v2, f3, v3) \
-+ generic_reg_get3(CTX, REG(reg_name), \
-+ FN(reg_name, f1), v1, \
-+ FN(reg_name, f2), v2, \
-+ FN(reg_name, f3), v3)
-+
-+#define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \
-+ generic_reg_get5(CTX, REG(reg_name), \
-+ FN(reg_name, f1), v1, \
-+ FN(reg_name, f2), v2, \
-+ FN(reg_name, f3), v3, \
-+ FN(reg_name, f4), v4, \
-+ FN(reg_name, f5), v5)
-+
-+/* macro to poll and wait for a register field to read back given value */
-+
-+#define REG_WAIT(reg_name, field, val, delay, max_try) \
-+ generic_reg_wait(CTX, \
-+ REG(reg_name), FN(reg_name, field), val,\
-+ delay, max_try, __func__)
-+
-+/* macro to update (read, modify, write) register fields
-+ */
-+#define REG_UPDATE_N(reg_name, n, ...) \
-+ generic_reg_update_ex(CTX, \
-+ REG(reg_name), \
-+ REG_READ(reg_name), \
-+ n, __VA_ARGS__)
-+
-+#define REG_UPDATE(reg_name, field, val) \
-+ REG_UPDATE_N(reg_name, 1, \
-+ FN(reg_name, field), val)
-+
-+#define REG_UPDATE_2(reg, f1, v1, f2, v2) \
-+ REG_UPDATE_N(reg, 2,\
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2)
-+
-+#define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3) \
-+ REG_UPDATE_N(reg, 3, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3)
-+
-+#define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4) \
-+ REG_UPDATE_N(reg, 4, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4)
-+
-+#define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \
-+ REG_UPDATE_N(reg, 5, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5)
-+
-+#define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) \
-+ REG_UPDATE_N(reg, 6, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6)
-+
-+#define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) \
-+ REG_UPDATE_N(reg, 7, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6, \
-+ FN(reg, f7), v7)
-+
-+#define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) \
-+ REG_UPDATE_N(reg, 8, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6, \
-+ FN(reg, f7), v7, \
-+ FN(reg, f8), v8)
-+
-+#define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) \
-+ REG_UPDATE_N(reg, 9, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6, \
-+ FN(reg, f7), v7, \
-+ FN(reg, f8), v8, \
-+ FN(reg, f9), v9)
-+
-+#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \
-+ REG_UPDATE_N(reg, 10, \
-+ FN(reg, f1), v1,\
-+ FN(reg, f2), v2, \
-+ FN(reg, f3), v3, \
-+ FN(reg, f4), v4, \
-+ FN(reg, f5), v5, \
-+ FN(reg, f6), v6, \
-+ FN(reg, f7), v7, \
-+ FN(reg, f8), v8, \
-+ FN(reg, f9), v9, \
-+ FN(reg, f10), v10)
-+
-+/* macro to update a register field to specified values in given sequences.
-+ * useful when toggling bits
-+ */
-+#define REG_UPDATE_SEQ(reg, field, value1, value2) \
-+{ uint32_t val = REG_UPDATE(reg, field, value1); \
-+ REG_SET(reg, val, field, value2); }
-+
-+/* macro to update fields in register 1 field at a time in given order */
-+#define REG_UPDATE_1BY1_2(reg, f1, v1, f2, v2) \
-+{ uint32_t val = REG_UPDATE(reg, f1, v1); \
-+ REG_SET(reg, val, f2, v2); }
-+
-+#define REG_UPDATE_1BY1_3(reg, f1, v1, f2, v2, f3, v3) \
-+{ uint32_t val = REG_UPDATE(reg, f1, v1); \
-+ val = REG_SET(reg, val, f2, v2); \
-+ REG_SET(reg, val, f3, v3); }
-+
-+uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift, uint32_t mask, uint32_t *field_value);
-+
-+uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2);
-+
-+uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
-+ uint8_t shift3, uint32_t mask3, uint32_t *field_value3);
-+
-+uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
-+ uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
-+ uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
-+ uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
-+ uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
-+ uint8_t shift5, uint32_t mask5, uint32_t *field_value5);
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
-new file mode 100644
-index 0000000..8dd676d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
-@@ -0,0 +1,164 @@
-+/*
-+ * 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_DC_DEV_DC_INC_RESOURCE_H_
-+#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_
-+
-+#include "core_types.h"
-+#include "core_status.h"
-+#include "core_dc.h"
-+#include "dal_asic_id.h"
-+
-+/* TODO unhardcode, 4 for CZ*/
-+#define MEMORY_TYPE_MULTIPLIER 4
-+
-+enum dce_version resource_parse_asic_id(
-+ struct hw_asic_id asic_id);
-+
-+struct resource_caps {
-+ int num_timing_generator;
-+ int num_video_plane;
-+ int num_audio;
-+ int num_stream_encoder;
-+ int num_pll;
-+};
-+
-+struct resource_straps {
-+ uint32_t hdmi_disable;
-+ uint32_t dc_pinstraps_audio;
-+ uint32_t audio_stream_number;
-+};
-+
-+struct resource_create_funcs {
-+ void (*read_dce_straps)(
-+ struct dc_context *ctx, struct resource_straps *straps);
-+
-+ struct audio *(*create_audio)(
-+ struct dc_context *ctx, unsigned int inst);
-+
-+ struct stream_encoder *(*create_stream_encoder)(
-+ enum engine_id eng_id, struct dc_context *ctx);
-+
-+ struct dce_hwseq *(*create_hwseq)(
-+ struct dc_context *ctx);
-+};
-+
-+bool resource_construct(
-+ unsigned int num_virtual_links,
-+ struct core_dc *dc,
-+ struct resource_pool *pool,
-+ const struct resource_create_funcs *create_funcs);
-+
-+struct resource_pool *dc_create_resource_pool(
-+ struct core_dc *dc,
-+ int num_virtual_links,
-+ enum dce_version dc_version,
-+ struct hw_asic_id asic_id);
-+
-+void dc_destroy_resource_pool(struct core_dc *dc);
-+
-+enum dc_status resource_map_pool_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+bool resource_build_scaling_params(
-+ const struct dc_surface *surface,
-+ struct pipe_ctx *pipe_ctx);
-+
-+enum dc_status resource_build_scaling_params_for_context(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+void resource_build_info_frame(struct pipe_ctx *pipe_ctx);
-+
-+void resource_unreference_clock_source(
-+ struct resource_context *res_ctx,
-+ struct clock_source *clock_source);
-+
-+void resource_reference_clock_source(
-+ struct resource_context *res_ctx,
-+ struct clock_source *clock_source);
-+
-+bool resource_are_streams_timing_synchronizable(
-+ const struct core_stream *stream1,
-+ const struct core_stream *stream2);
-+
-+struct clock_source *resource_find_used_clk_src_for_sharing(
-+ struct resource_context *res_ctx,
-+ struct pipe_ctx *pipe_ctx);
-+
-+struct clock_source *dc_resource_find_first_free_pll(
-+ struct resource_context *res_ctx);
-+
-+struct pipe_ctx *resource_get_head_pipe_for_stream(
-+ struct resource_context *res_ctx,
-+ const struct core_stream *stream);
-+
-+bool resource_attach_surfaces_to_context(
-+ const struct dc_surface *const *surfaces,
-+ int surface_count,
-+ const struct dc_target *dc_target,
-+ struct validate_context *context);
-+
-+struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx);
-+
-+bool resource_is_stream_unchanged(
-+ const struct validate_context *old_context, struct core_stream *stream);
-+
-+bool is_target_unchanged(
-+ const struct core_target *old_target, const struct core_target *target);
-+bool resource_validate_attach_surfaces(
-+ const struct dc_validation_set set[],
-+ int set_count,
-+ const struct validate_context *old_context,
-+ struct validate_context *context);
-+
-+void validate_guaranteed_copy_target(
-+ struct validate_context *context,
-+ int max_targets);
-+
-+void resource_validate_ctx_update_pointer_after_copy(
-+ const struct validate_context *src_ctx,
-+ struct validate_context *dst_ctx);
-+
-+void resource_validate_ctx_copy_construct(
-+ const struct validate_context *src_ctx,
-+ struct validate_context *dst_ctx);
-+
-+void resource_validate_ctx_destruct(struct validate_context *context);
-+
-+enum dc_status resource_map_clock_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+enum dc_status resource_map_phy_clock_resources(
-+ const struct core_dc *dc,
-+ struct validate_context *context);
-+
-+bool pipe_need_reprogram(
-+ struct pipe_ctx *pipe_ctx_old,
-+ struct pipe_ctx *pipe_ctx);
-+
-+
-+#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile
-new file mode 100644
-index 0000000..0271033
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile
-@@ -0,0 +1,28 @@
-+#
-+# 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_DISPLAY_FILES += $(AMD_DAL_IRQ)
-+
-+###############################################################################
-+# DCE 8x
-+###############################################################################
-+IRQ_DCE80 = irq_service_dce80.o
-+
-+AMD_DAL_IRQ_DCE80 = $(addprefix $(AMDDALPATH)/dc/irq/dce80/,$(IRQ_DCE80))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE80)
-+
-+###############################################################################
-+# DCE 11x
-+###############################################################################
-+IRQ_DCE11 = irq_service_dce110.o
-+
-+AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11))
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11)
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
-new file mode 100644
-index 0000000..f3eda1b
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
-@@ -0,0 +1,367 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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 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 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()
-+
-+bool dal_irq_service_dummy_set(
-+ struct irq_service *irq_service,
-+ const struct irq_source_info *info,
-+ bool enable)
-+{
-+ dm_logger_write(
-+ irq_service->ctx->logger, LOG_ERROR,
-+ "%s: called for non-implemented irq source\n",
-+ __func__);
-+ return false;
-+}
-+
-+bool dal_irq_service_dummy_ack(
-+ struct irq_service *irq_service,
-+ const struct irq_source_info *info)
-+{
-+ dm_logger_write(
-+ irq_service->ctx->logger, LOG_ERROR,
-+ "%s: called for non-implemented irq source\n",
-+ __func__);
-+ return false;
-+}
-+
-+static const struct irq_source_info_funcs dummy_irq_info_funcs = {
-+ .set = dal_irq_service_dummy_set,
-+ .ack = dal_irq_service_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),
-+ 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),
-+ [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),
-+};
-+
-+enum dc_irq_source to_dal_irq_source_dce110(
-+ 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_dce110
-+};
-+
-+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(sizeof(*irq_service));
-+
-+ if (!irq_service)
-+ return NULL;
-+
-+ if (construct(irq_service, init_data))
-+ return irq_service;
-+
-+ dm_free(irq_service);
-+ return NULL;
-+}
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h
-new file mode 100644
-index 0000000..a84f360
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.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_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);
-+
-+enum dc_irq_source to_dal_irq_source_dce110(
-+ struct irq_service *irq_service,
-+ uint32_t src_id,
-+ uint32_t ext_id);
-+
-+bool dal_irq_service_dummy_set(
-+ struct irq_service *irq_service,
-+ const struct irq_source_info *info,
-+ bool enable);
-+
-+bool dal_irq_service_dummy_ack(
-+ struct irq_service *irq_service,
-+ const struct irq_source_info *info);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
-new file mode 100644
-index 0000000..8b4f453
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
-@@ -0,0 +1,283 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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_dce80.h"
-+#include "../dce110/irq_service_dce110.h"
-+
-+#include "dce/dce_8_0_d.h"
-+#include "dce/dce_8_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_HPD1_INT_STATUS,
-+ DC_HPD1_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_HPD1_INT_CONTROL,
-+ DC_HPD1_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_INVALID + reg_num] = {\
-+ .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
-+ .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
-+ .enable_value = {\
-+ DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
-+ ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\
-+ },\
-+ .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
-+ .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\
-+ .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\
-+ .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\
-+ .funcs = &hpd_irq_info_funcs\
-+ }
-+
-+#define hpd_rx_int_entry(reg_num)\
-+ [DC_IRQ_SOURCE_HPD6 + reg_num] = {\
-+ .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
-+ .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
-+ .enable_value = {\
-+ DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
-+ ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\
-+ .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
-+ .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
-+ .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
-+ .status_reg = mmDC_HPD ## reg_num ## _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 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 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 const struct irq_source_info_funcs dummy_irq_info_funcs = {
-+ .set = dal_irq_service_dummy_set,
-+ .ack = dal_irq_service_dummy_ack
-+};
-+
-+static const struct irq_source_info
-+irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER] = {
-+ [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
-+ hpd_int_entry(1),
-+ hpd_int_entry(2),
-+ hpd_int_entry(3),
-+ hpd_int_entry(4),
-+ hpd_int_entry(5),
-+ hpd_int_entry(6),
-+ 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),
-+ hpd_rx_int_entry(6),
-+ i2c_int_entry(1),
-+ i2c_int_entry(2),
-+ i2c_int_entry(3),
-+ i2c_int_entry(4),
-+ i2c_int_entry(5),
-+ i2c_int_entry(6),
-+ 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),
-+ [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 const struct irq_service_funcs irq_service_funcs_dce80 = {
-+ .to_dal_irq_source = to_dal_irq_source_dce110
-+};
-+
-+static 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_dce80;
-+ irq_service->funcs = &irq_service_funcs_dce80;
-+
-+ return true;
-+}
-+
-+struct irq_service *dal_irq_service_dce80_create(
-+ struct irq_service_init_data *init_data)
-+{
-+ struct irq_service *irq_service = dm_alloc(sizeof(*irq_service));
-+
-+ if (!irq_service)
-+ return NULL;
-+
-+ if (construct(irq_service, init_data))
-+ return irq_service;
-+
-+ dm_free(irq_service);
-+ return NULL;
-+}
-+
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h
-new file mode 100644
-index 0000000..3dd1013
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.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 __DAL_IRQ_SERVICE_DCE80_H__
-+#define __DAL_IRQ_SERVICE_DCE80_H__
-+
-+#include "../irq_service.h"
-+
-+struct irq_service *dal_irq_service_dce80_create(
-+ struct irq_service_init_data *init_data);
-+
-+#endif
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
-new file mode 100644
-index 0000000..fbaa2fc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
-@@ -0,0 +1,163 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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"
-+
-+#include "dce110/irq_service_dce110.h"
-+
-+
-+#include "dce80/irq_service_dce80.h"
-+
-+
-+#include "reg_helper.h"
-+#include "irq_service.h"
-+
-+
-+
-+#define CTX \
-+ irq_service->ctx
-+
-+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;
-+}
-+
-+void dal_irq_service_destroy(struct irq_service **irq_service)
-+{
-+ if (!irq_service || !*irq_service) {
-+ BREAK_TO_DEBUGGER();
-+ return;
-+ }
-+
-+ dm_free(*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) {
-+ dm_logger_write(
-+ irq_service->ctx->logger, LOG_ERROR,
-+ "%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) {
-+ dm_logger_write(
-+ irq_service->ctx->logger, LOG_ERROR,
-+ "%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/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h
-new file mode 100644
-index 0000000..a2a2d69
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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
-diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h
-new file mode 100644
-index 0000000..e4b4b99
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/irq_types.h
-@@ -0,0 +1,185 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DPSINK1,
-+ DC_IRQ_SOURCE_DPSINK2,
-+ DC_IRQ_SOURCE_DPSINK3,
-+ DC_IRQ_SOURCE_DPSINK4,
-+ DC_IRQ_SOURCE_DPSINK5,
-+ DC_IRQ_SOURCE_DPSINK6,
-+
-+ 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/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h
-new file mode 100644
-index 0000000..459a274
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/os_types.h
-@@ -0,0 +1,61 @@
-+/*
-+ * 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 _OS_TYPES_H_
-+#define _OS_TYPES_H_
-+
-+#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)
-+
-+#endif
-+
-+
-+#endif /* _OS_TYPES_H_ */
-diff --git a/drivers/gpu/drm/amd/display/dc/virtual/Makefile b/drivers/gpu/drm/amd/display/dc/virtual/Makefile
-new file mode 100644
-index 0000000..fc0b731
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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_DISPLAY_FILES += $(AMD_DAL_VIRTUAL)
-diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c
-new file mode 100644
-index 0000000..bb4433f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c
-@@ -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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#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 pipe_ctx *pipe_ctx) { 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 dc_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 dc_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_set_dmcu_backlight_level(
-+ struct link_encoder *enc,
-+ uint32_t level,
-+ uint32_t frame_ramp,
-+ uint32_t controller_id) {}
-+
-+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 void virtual_link_encoder_destroy(struct link_encoder **enc)
-+{
-+ dm_free(*enc);
-+ *enc = NULL;
-+}
-+
-+
-+static const 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,
-+ .set_dmcu_backlight_level =
-+ virtual_link_encoder_set_dmcu_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,
-+ .destroy = virtual_link_encoder_destroy
-+};
-+
-+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->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/display/dc/virtual/virtual_link_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h
-new file mode 100644
-index 0000000..eb1a94f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.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 __DC_VIRTUAL_LINK_ENCODER_H__
-+#define __DC_VIRTUAL_LINK_ENCODER_H__
-+
-+#include "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/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c
-new file mode 100644
-index 0000000..8de21d9
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c
-@@ -0,0 +1,132 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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,
-+ enum dc_color_space output_color_space) {}
-+
-+static void virtual_stream_encoder_hdmi_set_stream_attribute(
-+ struct stream_encoder *enc,
-+ struct dc_crtc_timing *crtc_timing,
-+ int actual_pix_clk_khz,
-+ 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 void virtual_audio_mute_control(
-+ struct stream_encoder *enc,
-+ bool mute) {}
-+
-+static const 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,
-+
-+ .audio_mute_control = virtual_audio_mute_control,
-+};
-+
-+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(sizeof(*enc));
-+
-+ if (!enc)
-+ return NULL;
-+
-+ if (virtual_stream_encoder_construct(enc, ctx, bp))
-+ return enc;
-+
-+ BREAK_TO_DEBUGGER();
-+ dm_free(enc);
-+ return NULL;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h
-new file mode 100644
-index 0000000..bf3422c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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 "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__ */
-diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h
-new file mode 100644
-index 0000000..57cc72f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/asic_capability_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 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;
-+ 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/display/include/asic_capability_types.h b/drivers/gpu/drm/amd/display/include/asic_capability_types.h
-new file mode 100644
-index 0000000..c44dae0
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/asic_capability_types.h
-@@ -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
-+ *
-+ */
-+#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 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_DCE_VERSION = ASIC_DATA_FIRST,
-+ ASIC_DATA_DCE_VERSION_MINOR,
-+ ASIC_DATA_LINEBUFFER_SIZE,
-+ ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY,
-+ ASIC_DATA_MC_LATENCY,
-+ ASIC_DATA_MC_LATENCY_SLOW,
-+ ASIC_DATA_MEMORYTYPE_MULTIPLIER,
-+ ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR,
-+ ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE,
-+ ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY,
-+ ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN,
-+ ASIC_DATA_DOWNSCALE_LIMIT,
-+ 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/display/include/audio_types.h b/drivers/gpu/drm/amd/display/include/audio_types.h
-new file mode 100644
-index 0000000..6364fbc
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/audio_types.h
-@@ -0,0 +1,106 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 "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_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;
-+};
-+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
-+};
-+
-+/* 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;
-+};
-+
-+enum audio_payload {
-+ CHANNEL_SPLIT_MAPPINGCHANG = 0x9,
-+};
-+
-+#endif /* __AUDIO_TYPES_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_interface.h b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h
-new file mode 100644
-index 0000000..d51101c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h
-@@ -0,0 +1,44 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 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,
-+ enum dce_version dce_version);
-+
-+void dal_bios_parser_destroy(struct dc_bios **dcb);
-+
-+#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
-new file mode 100644
-index 0000000..9ab9065
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
-@@ -0,0 +1,338 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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/link_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
-+};
-+
-+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,
-+};
-+
-+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 dc_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 dc_link_rate link_rate;
-+ enum dc_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 dc_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 DP_HBR3_EN:1;
-+ uint32_t HDMI_6GB_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/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
-new file mode 100644
-index 0000000..119297e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
-@@ -0,0 +1,125 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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
-+
-+/* DCE112 */
-+#define VI_POLARIS10_P_A0 80
-+#define VI_POLARIS11_M_A0 90
-+
-+#define VI_UNKNOWN 0xFF
-+
-+#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))
-+
-+#define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \
-+ (eChipRev < VI_POLARIS11_M_A0))
-+#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0)
-+
-+/* 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/display/include/dal_register_logger.h b/drivers/gpu/drm/amd/display/include/dal_register_logger.h
-new file mode 100644
-index 0000000..00dfcd7
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/dal_register_logger.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_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/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h
-new file mode 100644
-index 0000000..ada5b19
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/dal_types.h
-@@ -0,0 +1,44 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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),
-+ DCE_VERSION_8_0,
-+ DCE_VERSION_10_0,
-+ DCE_VERSION_11_0,
-+ DCE_VERSION_11_2,
-+ DCE_VERSION_MAX,
-+};
-+
-+#endif /* __DAL_TYPES_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h
-new file mode 100644
-index 0000000..0a6ba91
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h
-@@ -0,0 +1,189 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h
-new file mode 100644
-index 0000000..2006fa2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h
-@@ -0,0 +1,175 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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"
-+
-+/* 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;
-+};
-+
-+/* 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;
-+ enum signal_type signal_type;
-+ enum dc_color_depth deep_color_depth;
-+ enum v_scaler_efficiency scaler_efficiency;
-+ bool line_buffer_prefetch_enabled;
-+};
-+
-+/* 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 = 0,
-+ CLOCKS_STATE_ULTRA_LOW,
-+ CLOCKS_STATE_LOW,
-+ CLOCKS_STATE_NOMINAL,
-+ CLOCKS_STATE_PERFORMANCE,
-+ /* Starting from DCE11, Max 8 level DPM state supported */
-+ CLOCKS_DPM_STATE_LEVEL_INVALID = CLOCKS_STATE_INVALID,
-+ CLOCKS_DPM_STATE_LEVEL_0 = CLOCKS_STATE_ULTRA_LOW,
-+ CLOCKS_DPM_STATE_LEVEL_1 = CLOCKS_STATE_LOW,
-+ CLOCKS_DPM_STATE_LEVEL_2 = CLOCKS_STATE_NOMINAL,
-+ CLOCKS_DPM_STATE_LEVEL_3 = CLOCKS_STATE_PERFORMANCE,
-+ CLOCKS_DPM_STATE_LEVEL_4 = CLOCKS_DPM_STATE_LEVEL_3 + 1,
-+ CLOCKS_DPM_STATE_LEVEL_5 = CLOCKS_DPM_STATE_LEVEL_4 + 1,
-+ CLOCKS_DPM_STATE_LEVEL_6 = CLOCKS_DPM_STATE_LEVEL_5 + 1,
-+ CLOCKS_DPM_STATE_LEVEL_7 = CLOCKS_DPM_STATE_LEVEL_6 + 1,
-+};
-+
-+/* 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;
-+
-+struct display_clock *dal_display_clock_dce112_create(
-+ struct dc_context *ctx);
-+
-+struct display_clock *dal_display_clock_dce110_create(
-+ struct dc_context *ctx);
-+
-+struct display_clock *dal_display_clock_dce80_create(
-+ struct dc_context *ctx);
-+
-+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);
-+bool dal_display_clock_get_min_clocks_state(
-+ struct display_clock *disp_clk,
-+ enum clocks_state *clocks_state);
-+bool dal_display_clock_get_required_clocks_state(
-+ struct display_clock *disp_clk,
-+ struct state_dependent_clocks *req_clocks,
-+ enum clocks_state *clocks_state);
-+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/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
-new file mode 100644
-index 0000000..fbb2729
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.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_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_BRANCH_REVISION_START = 0x0509,
-+ DPCD_ADDRESS_BRANCH_REVISION_END = 0x050B,
-+
-+ 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_SUPPORTED_LINK_RATES = 0x00010, /* edp 1.4 */
-+ 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,
-+
-+ DPCD_ADDRESS_DP13_DPCD_REV = 0x2200,
-+ DPCD_ADDRESS_DP13_MAX_LINK_RATE = 0x2201,
-+
-+ /* 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,
-+ DPCD_REV_13 = 0x13,
-+ DPCD_REV_14 = 0x14
-+};
-+
-+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,
-+ DPCD_TRAINING_PATTERN_4 = 7
-+};
-+
-+/* 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 TPS4_SUPPORTED:1;
-+ } bits;
-+ uint8_t raw;
-+};
-+
-+union mstm_cap {
-+ struct {
-+ uint8_t MST_CAP:1;
-+ uint8_t RESERVED:7;
-+ } 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;
-+};
-+
-+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 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;
-+};
-+
-+union dpcd_training_pattern {
-+ struct {
-+ uint8_t TRAINING_PATTERN_SET:4;
-+ uint8_t RECOVERED_CLOCK_OUT_EN:1;
-+ uint8_t SCRAMBLING_DISABLE:1;
-+ uint8_t SYMBOL_ERROR_COUNT_SEL:2;
-+ } v1_4;
-+ struct {
-+ uint8_t TRAINING_PATTERN_SET:2;
-+ uint8_t LINK_QUAL_PATTERN_SET:2;
-+ uint8_t RESERVED:4;
-+ } v1_3;
-+ 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;
-+};
-+
-+/* 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 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 training_aux_rd_interval {
-+ struct {
-+ uint8_t TRAINIG_AUX_RD_INTERVAL:7;
-+ uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1;
-+ } bits;
-+ uint8_t raw;
-+};
-+
-+/* Automated test structures */
-+union test_request {
-+ struct {
-+ uint8_t LINK_TRAINING :1;
-+ uint8_t LINK_TEST_PATTRN :1;
-+ uint8_t EDID_REAT :1;
-+ uint8_t PHY_TEST_PATTERN :1;
-+ uint8_t AUDIO_TEST_PATTERN :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 phy_test_pattern {
-+ struct {
-+ /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1
-+ * and 3 bits for DP1.2.
-+ */
-+ uint8_t PATTERN :3;
-+ /* BY speci, bit7:2 is 0 for DP1.1. */
-+ uint8_t RESERVED :5;
-+ } bits;
-+ uint8_t raw;
-+};
-+
-+/* States of Compliance Test Specification (CTS DP1.2). */
-+union compliance_test_state {
-+ struct {
-+ unsigned char STEREO_3D_RUNNING : 1;
-+ unsigned char SET_TEST_PATTERN_PENDING : 1;
-+ unsigned char RESERVED : 6;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+union link_test_pattern {
-+ struct {
-+ /* dpcd_link_test_patterns */
-+ unsigned char PATTERN :2;
-+ unsigned char RESERVED:6;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+union test_misc {
-+ struct dpcd_test_misc_bits {
-+ unsigned char SYNC_CLOCK :1;
-+ /* dpcd_test_color_format */
-+ unsigned char CLR_FORMAT :2;
-+ /* dpcd_test_dyn_range */
-+ unsigned char DYN_RANGE :1;
-+ unsigned char YCBCR :1;
-+ /* dpcd_test_bit_depth */
-+ unsigned char BPC :3;
-+ } bits;
-+ unsigned char raw;
-+};
-+
-+#endif /* __DAL_DPCD_DEFS_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
-new file mode 100644
-index 0000000..c28de16
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
-@@ -0,0 +1,390 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__
-+
-+#include "os_types.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/display/include/fixed32_32.h b/drivers/gpu/drm/amd/display/include/fixed32_32.h
-new file mode 100644
-index 0000000..c7ddd0e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/fixed32_32.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_FIXED32_32_H__
-+#define __DAL_FIXED32_32_H__
-+
-+#include "os_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/display/include/gpio_interface.h b/drivers/gpu/drm/amd/display/include/gpio_interface.h
-new file mode 100644
-index 0000000..e4fd310
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/gpio_interface.h
-@@ -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
-+ *
-+ */
-+
-+#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);
-+
-+/* 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/display/include/gpio_service_interface.h b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h
-new file mode 100644
-index 0000000..f40259b
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "hw/gpio.h"
-+
-+struct gpio_service;
-+
-+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);
-+
-+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_irq(
-+ struct gpio_service *service,
-+ uint32_t offset,
-+ uint32_t mask);
-+
-+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);
-+
-+void dal_gpio_service_destroy(
-+ struct gpio_service **ptr);
-+
-+enum dc_irq_source dal_irq_get_source(
-+ const struct gpio *irq);
-+
-+enum dc_irq_source dal_irq_get_rx_source(
-+ const struct gpio *irq);
-+
-+enum gpio_result dal_irq_setup_hpd_filter(
-+ struct gpio *irq,
-+ struct gpio_hpd_config *config);
-+
-+struct gpio *dal_gpio_create_irq(
-+ struct gpio_service *service,
-+ enum gpio_id id,
-+ uint32_t en);
-+
-+void dal_gpio_destroy_irq(
-+ struct gpio **ptr);
-+
-+
-+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_change_mode(
-+ struct ddc *ddc,
-+ enum gpio_mode mode);
-+
-+enum gpio_ddc_line dal_ddc_get_line(
-+ 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/display/include/gpio_types.h b/drivers/gpu/drm/amd/display/include/gpio_types.h
-new file mode 100644
-index 0000000..8dd46ed
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/gpio_types.h
-@@ -0,0 +1,332 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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;
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h
-new file mode 100644
-index 0000000..9c0bf65
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h
-@@ -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
-+ *
-+ */
-+
-+#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 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,
-+};
-+
-+
-+/* 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;
-+ bool realtek_eDPToLVDS;
-+};
-+
-+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;
-+ uint32_t default_memory_clk; /* in KHz */
-+ uint32_t default_engine_clk; /* in KHz */
-+ uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */
-+ uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */
-+
-+
-+};
-+
-+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;
-+ /*
-+ * TODO: added MST and HDMI 6G capable flags
-+ */
-+ 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;
-+};
-+
-+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;
-+};
-+
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h
-new file mode 100644
-index 0000000..2941b88
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.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_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
-+};
-+
-+/* 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
-+};
-+
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h
-new file mode 100644
-index 0000000..e4aa4dd
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h
-@@ -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
-+ *
-+ */
-+
-+#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, /*combo PHY PLL defines (DC 11.2 and up)*/
-+ 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)
-+};
-+
-+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/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
-new file mode 100644
-index 0000000..9a78097
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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"
-+
-+/* define the structure of Dynamic Refresh Mode */
-+struct drr_params {
-+ /* 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;
-+};
-+
-+/* 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;
-+
-+ /* in KHz */
-+ uint32_t pixel_clock;
-+
-+ 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;
-+};
-+
-+/* 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;
-+};
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h
-new file mode 100644
-index 0000000..d2ec04d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "gpio_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 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_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/display/include/irq_interface.h b/drivers/gpu/drm/amd/display/include/irq_interface.h
-new file mode 100644
-index 0000000..077ded3
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/irq_interface.h
-@@ -0,0 +1,31 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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"
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/include/irq_service_interface.h b/drivers/gpu/drm/amd/display/include/irq_service_interface.h
-new file mode 100644
-index 0000000..d6ebed5
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/irq_service_interface.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 __DAL_IRQ_SERVICE_INTERFACE_H__
-+#define __DAL_IRQ_SERVICE_INTERFACE_H__
-+
-+struct irq_service_init_data {
-+ struct dc_context *ctx;
-+};
-+
-+struct irq_service;
-+
-+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/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
-new file mode 100644
-index 0000000..06e6842
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
-@@ -0,0 +1,232 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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
-+};
-+
-+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 {
-+ LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/
-+};
-+
-+struct link_training_settings {
-+ struct dc_link_settings link_settings;
-+ struct dc_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,
-+ HW_DP_TRAINING_PATTERN_4
-+};
-+
-+/*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,
-+ DP_TEST_PATTERN_TRAINING_PATTERN4,
-+
-+ /* 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 dc_context *ctx;
-+ struct topology_mgr *tm;
-+};
-+
-+/* 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;
-+};
-+
-+/**
-+ * @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];
-+};
-+
-+/* 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];
-+};
-+
-+#endif /*__DAL_LINK_SERVICE_TYPES_H__*/
-diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h
-new file mode 100644
-index 0000000..b58d30d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/logger_interface.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_LOGGER_INTERFACE_H__
-+#define __DAL_LOGGER_INTERFACE_H__
-+
-+#include "logger_types.h"
-+
-+struct dc_context;
-+struct dc_link;
-+struct dc_surface_update;
-+
-+/*
-+ *
-+ * DAL logger functionality
-+ *
-+ */
-+
-+struct dal_logger *dal_logger_create(struct dc_context *ctx);
-+
-+uint32_t dal_logger_destroy(struct dal_logger **logger);
-+
-+void dm_logger_write(
-+ struct dal_logger *logger,
-+ enum dc_log_type log_type,
-+ const char *msg,
-+ ...);
-+
-+void dm_logger_append(
-+ struct log_entry *entry,
-+ const char *msg,
-+ ...);
-+
-+void dm_logger_open(
-+ struct dal_logger *logger,
-+ struct log_entry *entry,
-+ enum dc_log_type log_type);
-+
-+void dm_logger_close(struct log_entry *entry);
-+
-+void dc_conn_log(struct dc_context *ctx,
-+ const struct dc_link *link,
-+ uint8_t *hex_data,
-+ int hex_data_count,
-+ enum dc_log_type event,
-+ const char *msg,
-+ ...);
-+
-+void logger_write(struct dal_logger *logger,
-+ enum dc_log_type log_type,
-+ const char *msg,
-+ void *paralist);
-+
-+void pre_surface_trace(
-+ const struct dc *dc,
-+ const struct dc_surface *const *surfaces,
-+ int surface_count);
-+
-+void update_surface_trace(
-+ const struct dc *dc,
-+ const struct dc_surface_update *updates,
-+ int surface_count);
-+
-+void post_surface_trace(const struct dc *dc);
-+
-+
-+/* 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(fmt, ...) \
-+{ \
-+ static bool print_not_impl = true; \
-+\
-+ if (print_not_impl == true) { \
-+ print_not_impl = false; \
-+ dm_logger_write(ctx->logger, LOG_WARNING, \
-+ "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \
-+ } \
-+}
-+
-+/******************************************************************************
-+ * Convenience macros to save on typing.
-+ *****************************************************************************/
-+
-+#define DC_ERROR(...) \
-+ dm_logger_write(dc_ctx->logger, LOG_ERROR, \
-+ __VA_ARGS__);
-+
-+#define DC_SYNC_INFO(...) \
-+ dm_logger_write(dc_ctx->logger, LOG_SYNC, \
-+ __VA_ARGS__);
-+
-+
-+/* Connectivity log format:
-+ * [time stamp] [drm] [Major_minor] [connector name] message.....
-+ * eg:
-+ * [ 26.590965] [drm] [Conn_LKTN] [DP-1] HBRx4 pass VS=0, PE=0^
-+ * [ 26.881060] [drm] [Conn_Mode] [DP-1] {2560x1080, 2784x1111@185580Khz}^
-+ */
-+
-+#define CONN_DATA_DETECT(link, hex_data, hex_len, ...) \
-+ dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \
-+ LOG_EVENT_DETECTION, ##__VA_ARGS__)
-+
-+#define CONN_DATA_LINK_LOSS(link, hex_data, hex_len, ...) \
-+ dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \
-+ LOG_EVENT_LINK_LOSS, ##__VA_ARGS__)
-+
-+#define CONN_MSG_LT(link, ...) \
-+ dc_conn_log(link->ctx, &link->public, NULL, 0, \
-+ LOG_EVENT_LINK_TRAINING, ##__VA_ARGS__)
-+
-+#define CONN_MSG_MODE(link, ...) \
-+ dc_conn_log(link->ctx, &link->public, NULL, 0, \
-+ LOG_EVENT_MODE_SET, ##__VA_ARGS__)
-+
-+#endif /* __DAL_LOGGER_INTERFACE_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h
-new file mode 100644
-index 0000000..babd652
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/logger_types.h
-@@ -0,0 +1,95 @@
-+/*
-+ * Copyright 2012-15 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__
-+
-+#include "os_types.h"
-+
-+#define MAX_NAME_LEN 32
-+
-+struct dal_logger;
-+
-+enum dc_log_type {
-+ LOG_ERROR = 0,
-+ LOG_WARNING,
-+ LOG_DC,
-+ LOG_SURFACE,
-+ LOG_HW_HOTPLUG,
-+ LOG_HW_LINK_TRAINING,
-+ LOG_HW_SET_MODE,
-+ LOG_HW_RESUME_S3,
-+ LOG_HW_AUDIO,
-+ LOG_HW_HPD_IRQ,
-+ LOG_MST,
-+ LOG_SCALER,
-+ LOG_BIOS,
-+ LOG_BANDWIDTH_CALCS,
-+ LOG_BANDWIDTH_VALIDATION,
-+ LOG_I2C_AUX,
-+ LOG_SYNC,
-+ LOG_BACKLIGHT,
-+ LOG_FEATURE_OVERRIDE,
-+ LOG_DETECTION_EDID_PARSER,
-+ LOG_DETECTION_DP_CAPS,
-+ LOG_RESOURCE,
-+ LOG_DML,
-+ LOG_EVENT_MODE_SET,
-+ LOG_EVENT_DETECTION,
-+ LOG_EVENT_LINK_TRAINING,
-+ LOG_EVENT_LINK_LOSS,
-+ LOG_EVENT_UNDERFLOW,
-+ LOG_IF_TRACE,
-+
-+ LOG_SECTION_TOTAL_COUNT
-+};
-+
-+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 dc_log_type type;
-+
-+ char *buf;
-+ uint32_t buf_offset;
-+ uint32_t max_buf_bytes;
-+};
-+
-+/**
-+* Structure for enumerating log types
-+*/
-+struct dc_log_type_info {
-+ enum dc_log_type type;
-+ char name[MAX_NAME_LEN];
-+};
-+
-+#endif /* __DAL_LOGGER_TYPES_H__ */
-diff --git a/drivers/gpu/drm/amd/display/include/set_mode_types.h b/drivers/gpu/drm/amd/display/include/set_mode_types.h
-new file mode 100644
-index 0000000..d18210f
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/include/set_mode_types.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_SET_MODE_TYPES_H__
-+#define __DAL_SET_MODE_TYPES_H__
-+
-+#include "dc_types.h"
-+
-+/* 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/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h
-new file mode 100644
-index 0000000..a50f7ed
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/include/vector.h b/drivers/gpu/drm/amd/display/include/vector.h
-new file mode 100644
-index 0000000..8233b7c2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/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/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c
-new file mode 100644
-index 0000000..cf030b1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/color/color.c
-@@ -0,0 +1,2094 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "dc.h"
-+#include "mod_color.h"
-+#include "core_types.h"
-+#include "fixed31_32.h"
-+#include "core_dc.h"
-+
-+#define MOD_COLOR_MAX_CONCURRENT_SINKS 32
-+#define DIVIDER 10000
-+/* S2D13 value in [-3.00...0.9999] */
-+#define S2D13_MIN (-3 * DIVIDER)
-+#define S2D13_MAX (3 * DIVIDER)
-+#define S0D13_MIN (-1 * DIVIDER)
-+#define S0D13_MAX (1 * DIVIDER)
-+
-+struct sink_caps {
-+ const struct dc_sink *sink;
-+};
-+
-+struct gamut_calculation_matrix {
-+ struct fixed31_32 MTransposed[9];
-+ struct fixed31_32 XYZtoRGB_Custom[9];
-+ struct fixed31_32 XYZtoRGB_Ref[9];
-+ struct fixed31_32 RGBtoXYZ_Final[9];
-+
-+ struct fixed31_32 MResult[9];
-+ struct fixed31_32 fXYZofWhiteRef[9];
-+ struct fixed31_32 fXYZofRGBRef[9];
-+};
-+
-+struct gamut_src_dst_matrix {
-+ struct fixed31_32 rgbCoeffDst[9];
-+ struct fixed31_32 whiteCoeffDst[3];
-+ struct fixed31_32 rgbCoeffSrc[9];
-+ struct fixed31_32 whiteCoeffSrc[3];
-+};
-+
-+struct color_state {
-+ bool user_enable_color_temperature;
-+ int custom_color_temperature;
-+ struct color_space_coordinates source_gamut;
-+ struct color_space_coordinates destination_gamut;
-+ struct color_range contrast;
-+ struct color_range saturation;
-+ struct color_range brightness;
-+ struct color_range hue;
-+ enum dc_quantization_range preferred_quantization_range;
-+};
-+
-+struct core_color {
-+ struct mod_color public;
-+ struct dc *dc;
-+ int num_sinks;
-+ struct sink_caps *caps;
-+ struct color_state *state;
-+};
-+
-+#define MOD_COLOR_TO_CORE(mod_color)\
-+ container_of(mod_color, struct core_color, public)
-+
-+#define COLOR_REGISTRY_NAME "color_v1"
-+
-+/*Matrix Calculation Functions*/
-+/**
-+ *****************************************************************************
-+ * Function: transposeMatrix
-+ *
-+ * @brief
-+ * rotate the matrix 90 degrees clockwise
-+ * rows become a columns and columns to rows
-+ * @param [ in ] M - source matrix
-+ * @param [ in ] Rows - num of Rows of the original matrix
-+ * @param [ in ] Cols - num of Cols of the original matrix
-+ * @param [ out] MTransposed - result matrix
-+ * @return void
-+ *
-+ *****************************************************************************
-+ */
-+static void transpose_matrix(const struct fixed31_32 *M, unsigned int Rows,
-+ unsigned int Cols, struct fixed31_32 *MTransposed)
-+{
-+ unsigned int i, j;
-+
-+ for (i = 0; i < Rows; i++) {
-+ for (j = 0; j < Cols; j++)
-+ MTransposed[(j*Rows)+i] = M[(i*Cols)+j];
-+ }
-+}
-+
-+/**
-+ *****************************************************************************
-+ * Function: multiplyMatrices
-+ *
-+ * @brief
-+ * multiplies produce of two matrices: M = M1[ulRows1 x ulCols1] *
-+ * M2[ulCols1 x ulCols2].
-+ *
-+ * @param [ in ] M1 - first Matrix.
-+ * @param [ in ] M2 - second Matrix.
-+ * @param [ in ] Rows1 - num of Rows of the first Matrix
-+ * @param [ in ] Cols1 - num of Cols of the first Matrix/Num of Rows
-+ * of the second Matrix
-+ * @param [ in ] Cols2 - num of Cols of the second Matrix
-+ * @param [out ] mResult - resulting matrix.
-+ * @return void
-+ *
-+ *****************************************************************************
-+ */
-+static void multiply_matrices(struct fixed31_32 *mResult,
-+ const struct fixed31_32 *M1,
-+ const struct fixed31_32 *M2, unsigned int Rows1,
-+ unsigned int Cols1, unsigned int Cols2)
-+{
-+ unsigned int i, j, k;
-+
-+ for (i = 0; i < Rows1; i++) {
-+ for (j = 0; j < Cols2; j++) {
-+ mResult[(i * Cols2) + j] = dal_fixed31_32_zero;
-+ for (k = 0; k < Cols1; k++)
-+ mResult[(i * Cols2) + j] =
-+ dal_fixed31_32_add
-+ (mResult[(i * Cols2) + j],
-+ dal_fixed31_32_mul(M1[(i * Cols1) + k],
-+ M2[(k * Cols2) + j]));
-+ }
-+ }
-+}
-+
-+/**
-+ *****************************************************************************
-+ * Function: cFind3X3Det
-+ *
-+ * @brief
-+ * finds determinant of given 3x3 matrix
-+ *
-+ * @param [ in ] m - matrix
-+ * @return determinate whioch could not be zero
-+ *
-+ *****************************************************************************
-+ */
-+static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m)
-+{
-+ struct fixed31_32 det, A1, A2, A3;
-+
-+ A1 = dal_fixed31_32_mul(m[0],
-+ dal_fixed31_32_sub(dal_fixed31_32_mul(m[4], m[8]),
-+ dal_fixed31_32_mul(m[5], m[7])));
-+ A2 = dal_fixed31_32_mul(m[1],
-+ dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[8]),
-+ dal_fixed31_32_mul(m[5], m[6])));
-+ A3 = dal_fixed31_32_mul(m[2],
-+ dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[7]),
-+ dal_fixed31_32_mul(m[4], m[6])));
-+ det = dal_fixed31_32_add(dal_fixed31_32_sub(A1, A2), A3);
-+ return det;
-+}
-+
-+
-+/**
-+ *****************************************************************************
-+ * Function: computeInverseMatrix_3x3
-+ *
-+ * @brief
-+ * builds inverse matrix
-+ *
-+ * @param [ in ] m - matrix
-+ * @param [ out ] im - result matrix
-+ * @return true if success
-+ *
-+ *****************************************************************************
-+ */
-+static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m,
-+ struct fixed31_32 *im)
-+{
-+ struct fixed31_32 determinant = find_3X3_det(m);
-+
-+ if (dal_fixed31_32_eq(determinant, dal_fixed31_32_zero) == false) {
-+ im[0] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[4], m[8]),
-+ dal_fixed31_32_mul(m[5], m[7])), determinant);
-+ im[1] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[1], m[8]),
-+ dal_fixed31_32_mul(m[2], m[7])), determinant));
-+ im[2] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[1], m[5]),
-+ dal_fixed31_32_mul(m[2], m[4])), determinant);
-+ im[3] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[3], m[8]),
-+ dal_fixed31_32_mul(m[5], m[6])), determinant));
-+ im[4] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[0], m[8]),
-+ dal_fixed31_32_mul(m[2], m[6])), determinant);
-+ im[5] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[0], m[5]),
-+ dal_fixed31_32_mul(m[2], m[3])), determinant));
-+ im[6] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[3], m[7]),
-+ dal_fixed31_32_mul(m[4], m[6])), determinant);
-+ im[7] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[0], m[7]),
-+ dal_fixed31_32_mul(m[1], m[6])), determinant));
-+ im[8] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_mul(m[0], m[4]),
-+ dal_fixed31_32_mul(m[1], m[3])), determinant);
-+ return true;
-+ }
-+ return false;
-+}
-+
-+/**
-+ *****************************************************************************
-+ * Function: calculateXYZtoRGB_M3x3
-+ *
-+ * @brief
-+ * Calculates transformation matrix from XYZ coordinates to RBG
-+ *
-+ * @param [ in ] XYZofRGB - primaries XYZ
-+ * @param [ in ] XYZofWhite - white point.
-+ * @param [ out ] XYZtoRGB - RGB primires
-+ * @return true if success
-+ *
-+ *****************************************************************************
-+ */
-+static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB,
-+ const struct fixed31_32 *XYZofWhite,
-+ struct fixed31_32 *XYZtoRGB)
-+{
-+
-+ struct fixed31_32 MInversed[9];
-+ struct fixed31_32 SVector[3];
-+
-+ /*1. Find Inverse matrix 3x3 of MTransposed*/
-+ if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed))
-+ return false;
-+
-+ /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/
-+ multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1);
-+
-+ /*3. Calculate matrix XYZtoRGB 3x3*/
-+ XYZtoRGB[0] = dal_fixed31_32_mul(XYZofRGB[0], SVector[0]);
-+ XYZtoRGB[1] = dal_fixed31_32_mul(XYZofRGB[1], SVector[1]);
-+ XYZtoRGB[2] = dal_fixed31_32_mul(XYZofRGB[2], SVector[2]);
-+
-+ XYZtoRGB[3] = dal_fixed31_32_mul(XYZofRGB[3], SVector[0]);
-+ XYZtoRGB[4] = dal_fixed31_32_mul(XYZofRGB[4], SVector[1]);
-+ XYZtoRGB[5] = dal_fixed31_32_mul(XYZofRGB[5], SVector[2]);
-+
-+ XYZtoRGB[6] = dal_fixed31_32_mul(XYZofRGB[6], SVector[0]);
-+ XYZtoRGB[7] = dal_fixed31_32_mul(XYZofRGB[7], SVector[1]);
-+ XYZtoRGB[8] = dal_fixed31_32_mul(XYZofRGB[8], SVector[2]);
-+
-+ return true;
-+}
-+
-+static bool gamut_to_color_matrix(
-+ const struct fixed31_32 *pXYZofRGB,/*destination gamut*/
-+ const struct fixed31_32 *pXYZofWhite,/*destination of white point*/
-+ const struct fixed31_32 *pRefXYZofRGB,/*source gamut*/
-+ const struct fixed31_32 *pRefXYZofWhite,/*source of white point*/
-+ bool invert,
-+ struct fixed31_32 *tempMatrix3X3)
-+{
-+ int i = 0;
-+ struct gamut_calculation_matrix *matrix =
-+ dm_alloc(sizeof(struct gamut_calculation_matrix));
-+
-+ struct fixed31_32 *pXYZtoRGB_Temp;
-+ struct fixed31_32 *pXYZtoRGB_Final;
-+
-+ matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0];
-+ matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1];
-+ matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2];
-+
-+
-+ matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0];
-+ matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1];
-+ matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2];
-+
-+ matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3];
-+ matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4];
-+ matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5];
-+
-+ matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6];
-+ matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7];
-+ matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8];
-+
-+ /*default values - unity matrix*/
-+ while (i < 9) {
-+ if (i == 0 || i == 4 || i == 8)
-+ tempMatrix3X3[i] = dal_fixed31_32_one;
-+ else
-+ tempMatrix3X3[i] = dal_fixed31_32_zero;
-+ i++;
-+ }
-+
-+ /*1. Decide about the order of calculation.
-+ * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom
-+ * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */
-+ if (invert) {
-+ pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom;
-+ pXYZtoRGB_Final = matrix->XYZtoRGB_Ref;
-+ } else {
-+ pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref;
-+ pXYZtoRGB_Final = matrix->XYZtoRGB_Custom;
-+ }
-+
-+ /*2. Calculate XYZtoRGB_Ref*/
-+ transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed);
-+
-+ if (!calculate_XYZ_to_RGB_3x3(
-+ matrix->MTransposed,
-+ matrix->fXYZofWhiteRef,
-+ matrix->XYZtoRGB_Ref))
-+ goto function_fail;
-+
-+ /*3. Calculate XYZtoRGB_Custom*/
-+ transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed);
-+
-+ if (!calculate_XYZ_to_RGB_3x3(
-+ matrix->MTransposed,
-+ pXYZofWhite,
-+ matrix->XYZtoRGB_Custom))
-+ goto function_fail;
-+
-+ /*4. Calculate RGBtoXYZ -
-+ * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/
-+ if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final))
-+ goto function_fail;
-+
-+ /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/
-+ multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final,
-+ pXYZtoRGB_Final, 3, 3, 3);
-+
-+ for (i = 0; i < 9; i++)
-+ tempMatrix3X3[i] = matrix->MResult[i];
-+
-+ dm_free(matrix);
-+
-+ return true;
-+
-+function_fail:
-+ dm_free(matrix);
-+ return false;
-+}
-+
-+static bool build_gamut_remap_matrix
-+ (struct color_space_coordinates gamut_description,
-+ struct fixed31_32 *rgb_matrix,
-+ struct fixed31_32 *white_point_matrix)
-+{
-+ struct fixed31_32 fixed_blueX = dal_fixed31_32_from_fraction
-+ (gamut_description.blueX, DIVIDER);
-+ struct fixed31_32 fixed_blueY = dal_fixed31_32_from_fraction
-+ (gamut_description.blueY, DIVIDER);
-+ struct fixed31_32 fixed_greenX = dal_fixed31_32_from_fraction
-+ (gamut_description.greenX, DIVIDER);
-+ struct fixed31_32 fixed_greenY = dal_fixed31_32_from_fraction
-+ (gamut_description.greenY, DIVIDER);
-+ struct fixed31_32 fixed_redX = dal_fixed31_32_from_fraction
-+ (gamut_description.redX, DIVIDER);
-+ struct fixed31_32 fixed_redY = dal_fixed31_32_from_fraction
-+ (gamut_description.redY, DIVIDER);
-+ struct fixed31_32 fixed_whiteX = dal_fixed31_32_from_fraction
-+ (gamut_description.whiteX, DIVIDER);
-+ struct fixed31_32 fixed_whiteY = dal_fixed31_32_from_fraction
-+ (gamut_description.whiteY, DIVIDER);
-+
-+ rgb_matrix[0] = dal_fixed31_32_div(fixed_redX, fixed_redY);
-+ rgb_matrix[1] = dal_fixed31_32_one;
-+ rgb_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_redX),
-+ fixed_redY), fixed_redY);
-+
-+ rgb_matrix[3] = dal_fixed31_32_div(fixed_greenX, fixed_greenY);
-+ rgb_matrix[4] = dal_fixed31_32_one;
-+ rgb_matrix[5] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_greenX),
-+ fixed_greenY), fixed_greenY);
-+
-+ rgb_matrix[6] = dal_fixed31_32_div(fixed_blueX, fixed_blueY);
-+ rgb_matrix[7] = dal_fixed31_32_one;
-+ rgb_matrix[8] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_blueX),
-+ fixed_blueY), fixed_blueY);
-+
-+ white_point_matrix[0] = dal_fixed31_32_div(fixed_whiteX, fixed_whiteY);
-+ white_point_matrix[1] = dal_fixed31_32_one;
-+ white_point_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub
-+ (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_whiteX),
-+ fixed_whiteY), fixed_whiteY);
-+
-+ return true;
-+}
-+
-+static bool check_dc_support(const struct dc *dc)
-+{
-+ if (dc->stream_funcs.set_gamut_remap == NULL)
-+ return false;
-+
-+ return true;
-+}
-+
-+static 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
-+*/
-+
-+static void convert_float_matrix_legacy(
-+ 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 convert_float_matrix(
-+ uint16_t *matrix,
-+ struct fixed31_32 *flt,
-+ uint32_t buffer_size)
-+{
-+ const struct fixed31_32 min_0_13 =
-+ dal_fixed31_32_from_fraction(S0D13_MIN, DIVIDER);
-+ const struct fixed31_32 max_0_13 =
-+ dal_fixed31_32_from_fraction(S0D13_MAX, DIVIDER);
-+ 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;
-+ uint16_t temp_matrix[12];
-+
-+ for (i = 0; i < buffer_size; ++i) {
-+ if (i == 3 || i == 7 || i == 11) {
-+ uint32_t reg_value =
-+ fixed_point_to_int_frac(
-+ dal_fixed31_32_clamp(
-+ flt[i],
-+ min_0_13,
-+ max_0_13),
-+ 2,
-+ 13);
-+
-+ temp_matrix[i] = (uint16_t)reg_value;
-+ } else {
-+ uint32_t reg_value =
-+ fixed_point_to_int_frac(
-+ dal_fixed31_32_clamp(
-+ flt[i],
-+ min_2_13,
-+ max_2_13),
-+ 2,
-+ 13);
-+
-+ temp_matrix[i] = (uint16_t)reg_value;
-+ }
-+ }
-+
-+ matrix[4] = temp_matrix[0];
-+ matrix[5] = temp_matrix[1];
-+ matrix[6] = temp_matrix[2];
-+ matrix[7] = temp_matrix[3];
-+
-+ matrix[8] = temp_matrix[4];
-+ matrix[9] = temp_matrix[5];
-+ matrix[10] = temp_matrix[6];
-+ matrix[11] = temp_matrix[7];
-+
-+ matrix[0] = temp_matrix[8];
-+ matrix[1] = temp_matrix[9];
-+ matrix[2] = temp_matrix[10];
-+ matrix[3] = temp_matrix[11];
-+}
-+
-+static int get_hw_value_from_sw_value(int swVal, int swMin,
-+ int swMax, int hwMin, int hwMax)
-+{
-+ int dSW = swMax - swMin; /*software adjustment range size*/
-+ int dHW = hwMax - hwMin; /*hardware adjustment range size*/
-+ int hwVal; /*HW adjustment value*/
-+
-+ /* error case, I preserve the behavior from the predecessor
-+ *getHwStepFromSwHwMinMaxValue (removed in Feb 2013)
-+ *which was the FP version that only computed SCLF (i.e. dHW/dSW).
-+ *it would return 0 in this case so
-+ *hwVal = hwMin from the formula given in @brief
-+ */
-+ if (dSW == 0)
-+ return hwMin;
-+
-+ /*it's quite often that ranges match,
-+ *e.g. for overlay colors currently (Feb 2013)
-+ *only brightness has a different
-+ *HW range, and in this case no multiplication or division is needed,
-+ *and if minimums match, no calculation at all
-+ */
-+ if (dSW != dHW) {
-+ hwVal = (swVal - swMin)*dHW/dSW + hwMin;
-+ } else {
-+ hwVal = swVal;
-+ if (swMin != hwMin)
-+ hwVal += (hwMin - swMin);
-+ }
-+
-+ return hwVal;
-+}
-+
-+static void initialize_fix_point_color_values(
-+ struct core_color *core_color,
-+ unsigned int sink_index,
-+ 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
-+ (get_hw_value_from_sw_value
-+ (core_color->state[sink_index].hue.current,
-+ core_color->state[sink_index].hue.min,
-+ core_color->state[sink_index].hue.max,
-+ -30, 30), 180),
-+ dal_fixed31_32_pi);
-+
-+ *sin_grph_hue = dal_fixed31_32_sin(hue);
-+ *cos_grph_hue = dal_fixed31_32_cos(hue);
-+
-+ *grph_cont =
-+ dal_fixed31_32_from_fraction(get_hw_value_from_sw_value
-+ (core_color->state[sink_index].contrast.current,
-+ core_color->state[sink_index].contrast.min,
-+ core_color->state[sink_index].contrast.max,
-+ 50, 150), 100);
-+ *grph_sat =
-+ dal_fixed31_32_from_fraction(get_hw_value_from_sw_value
-+ (core_color->state[sink_index].saturation.current,
-+ core_color->state[sink_index].saturation.min,
-+ core_color->state[sink_index].saturation.max,
-+ 0, 200), 100);
-+ *grph_bright =
-+ dal_fixed31_32_from_fraction(get_hw_value_from_sw_value
-+ (core_color->state[sink_index].brightness.current,
-+ core_color->state[sink_index].brightness.min,
-+ core_color->state[sink_index].brightness.max,
-+ -25, 25), 100);
-+}
-+
-+
-+/* Given a specific dc_sink* this function finds its equivalent
-+ * on the dc_sink array and returns the corresponding index
-+ */
-+static unsigned int sink_index_from_sink(struct core_color *core_color,
-+ const struct dc_sink *sink)
-+{
-+ unsigned int index = 0;
-+
-+ for (index = 0; index < core_color->num_sinks; index++)
-+ if (core_color->caps[index].sink == sink)
-+ return index;
-+
-+ /* Could not find sink requested */
-+ ASSERT(false);
-+ return index;
-+}
-+
-+static void calculate_rgb_matrix_legacy(struct core_color *core_color,
-+ unsigned int sink_index,
-+ struct fixed31_32 *rgb_matrix)
-+{
-+ 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 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_fix_point_color_values(
-+ core_color, sink_index, &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)*/
-+ rgb_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 */
-+ rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]);
-+ /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/
-+ rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]);
-+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/
-+ /* K2))*/
-+ rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]);
-+
-+ /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/
-+ /* Sin(GrphHue) * K4))*/
-+ /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/
-+ rgb_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)*/
-+ rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]);
-+ /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/
-+ rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]);
-+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/
-+ /* K4))*/
-+ rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]);
-+
-+ /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/
-+ /* Sin(GrphHue) * K6))*/
-+ /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/
-+ rgb_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)*/
-+ rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]);
-+ /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/
-+ rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]);
-+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/
-+ /* K6))*/
-+ rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]);
-+
-+ /* COEF_1_4 = GrphBright*/
-+ rgb_matrix[3] = grph_bright;
-+
-+ /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/
-+ /* Sin(GrphHue) * K8))*/
-+ /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/
-+ rgb_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)*/
-+ rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]);
-+ /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/
-+ rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]);
-+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/
-+ /* K8))*/
-+ rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]);
-+
-+ /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/
-+ /* Sin(GrphHue) * K10))*/
-+ /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/
-+ rgb_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))*/
-+ rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]);
-+ /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/
-+ rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]);
-+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/
-+ /* K10))*/
-+ rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]);
-+
-+ /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/
-+ /* Sin(GrphHue) * K12))*/
-+ /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/
-+ rgb_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))*/
-+ rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]);
-+ /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/
-+ rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]);
-+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/
-+ /* K12))*/
-+ rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]);
-+
-+ /* COEF_2_4 = GrphBright*/
-+ rgb_matrix[7] = grph_bright;
-+
-+ /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/
-+ /* Sin(GrphHue) * K14))*/
-+ /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
-+ rgb_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)) */
-+ rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]);
-+ /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
-+ rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]);
-+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/
-+ /* K14)) */
-+ rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]);
-+
-+ /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/
-+ /* Sin(GrphHue) * K16)) */
-+ /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */
-+ rgb_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)) */
-+ rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]);
-+ /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
-+ rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]);
-+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/
-+ /* K16)) */
-+ rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]);
-+
-+ /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/
-+ /* Sin(GrphHue) * K18)) */
-+ /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
-+ rgb_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)) */
-+ rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]);
-+ /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
-+ rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]);
-+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/
-+ /* K18)) */
-+ rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]);
-+
-+ /* COEF_3_4 = GrphBright */
-+ rgb_matrix[11] = grph_bright;
-+}
-+
-+static void calculate_rgb_limited_range_matrix(struct core_color *core_color,
-+ unsigned int sink_index, struct fixed31_32 *rgb_matrix)
-+{
-+ struct fixed31_32 ideal[12];
-+
-+ static const int32_t matrix_[] = {
-+ 85546875, 0, 0, 6250000,
-+ 0, 85546875, 0, 6250000,
-+ 0, 0, 85546875, 6250000
-+ };
-+
-+ uint32_t i = 0;
-+
-+ do {
-+ ideal[i] = dal_fixed31_32_from_fraction(
-+ matrix_[i],
-+ 100000000);
-+ ++i;
-+ } while (i != ARRAY_SIZE(matrix_));
-+
-+
-+ 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_fix_point_color_values(
-+ core_color, sink_index, &grph_cont, &grph_sat,
-+ &grph_bright, &sin_grph_hue, &cos_grph_hue);
-+
-+ const struct fixed31_32 multiplier =
-+ dal_fixed31_32_mul(grph_cont, grph_sat);
-+
-+ rgb_matrix[8] = dal_fixed31_32_mul(ideal[0], grph_cont);
-+
-+ rgb_matrix[9] = dal_fixed31_32_mul(ideal[1], grph_cont);
-+
-+ rgb_matrix[10] = dal_fixed31_32_mul(ideal[2], grph_cont);
-+
-+ rgb_matrix[11] = dal_fixed31_32_add(
-+ ideal[3],
-+ dal_fixed31_32_mul(
-+ grph_bright,
-+ dal_fixed31_32_from_fraction(86, 100)));
-+
-+ rgb_matrix[0] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[8],
-+ sin_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[4],
-+ cos_grph_hue)));
-+
-+ rgb_matrix[1] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[9],
-+ sin_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[5],
-+ cos_grph_hue)));
-+
-+ rgb_matrix[2] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[10],
-+ sin_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[6],
-+ cos_grph_hue)));
-+
-+ rgb_matrix[3] = ideal[7];
-+
-+ rgb_matrix[4] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[8],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[4],
-+ sin_grph_hue)));
-+
-+ rgb_matrix[5] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[9],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[5],
-+ sin_grph_hue)));
-+
-+ rgb_matrix[6] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[10],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[6],
-+ sin_grph_hue)));
-+
-+ rgb_matrix[7] = ideal[11];
-+}
-+
-+static void calculate_yuv_matrix(struct core_color *core_color,
-+ unsigned int sink_index,
-+ enum dc_color_space color_space,
-+ struct fixed31_32 *yuv_matrix)
-+{
-+ struct fixed31_32 ideal[12];
-+ uint32_t i = 0;
-+
-+ if ((color_space == COLOR_SPACE_YPBPR601) ||
-+ (color_space == COLOR_SPACE_YCBCR601) ||
-+ (color_space == COLOR_SPACE_YCBCR601_LIMITED)) {
-+ static const int32_t matrix_[] = {
-+ 25578516, 50216016, 9752344, 6250000,
-+ -14764391, -28985609, 43750000, 50000000,
-+ 43750000, -36635164, -7114836, 50000000
-+ };
-+ do {
-+ ideal[i] = dal_fixed31_32_from_fraction(
-+ matrix_[i],
-+ 100000000);
-+ ++i;
-+ } while (i != ARRAY_SIZE(matrix_));
-+ } else {
-+ static const int32_t matrix_[] = {
-+ 18187266, 61183125, 6176484, 6250000,
-+ -10025059, -33724941, 43750000, 50000000,
-+ 43750000, -39738379, -4011621, 50000000
-+ };
-+ do {
-+ ideal[i] = dal_fixed31_32_from_fraction(
-+ matrix_[i],
-+ 100000000);
-+ ++i;
-+ } while (i != ARRAY_SIZE(matrix_));
-+ }
-+
-+ 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_fix_point_color_values(
-+ core_color, sink_index, &grph_cont, &grph_sat,
-+ &grph_bright, &sin_grph_hue, &cos_grph_hue);
-+
-+ const struct fixed31_32 multiplier =
-+ dal_fixed31_32_mul(grph_cont, grph_sat);
-+
-+ yuv_matrix[0] = dal_fixed31_32_mul(ideal[0], grph_cont);
-+
-+ yuv_matrix[1] = dal_fixed31_32_mul(ideal[1], grph_cont);
-+
-+ yuv_matrix[2] = dal_fixed31_32_mul(ideal[2], grph_cont);
-+
-+ yuv_matrix[4] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[4],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[8],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[5] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[5],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[9],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[6] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_add(
-+ dal_fixed31_32_mul(
-+ ideal[6],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[10],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[7] = ideal[7];
-+
-+ yuv_matrix[8] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[8],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[4],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[9] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[9],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[5],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[10] = dal_fixed31_32_mul(
-+ multiplier,
-+ dal_fixed31_32_sub(
-+ dal_fixed31_32_mul(
-+ ideal[10],
-+ cos_grph_hue),
-+ dal_fixed31_32_mul(
-+ ideal[6],
-+ sin_grph_hue)));
-+
-+ yuv_matrix[11] = ideal[11];
-+
-+ if ((color_space == COLOR_SPACE_YCBCR601_LIMITED) ||
-+ (color_space == COLOR_SPACE_YCBCR709_LIMITED)) {
-+ yuv_matrix[3] = dal_fixed31_32_add(ideal[3], grph_bright);
-+ } else {
-+ yuv_matrix[3] = dal_fixed31_32_add(
-+ ideal[3],
-+ dal_fixed31_32_mul(
-+ grph_bright,
-+ dal_fixed31_32_from_fraction(86, 100)));
-+ }
-+}
-+
-+static void calculate_csc_matrix(struct core_color *core_color,
-+ unsigned int sink_index,
-+ enum dc_color_space color_space,
-+ uint16_t *csc_matrix)
-+{
-+ struct fixed31_32 fixed_csc_matrix[12];
-+ switch (color_space) {
-+ case COLOR_SPACE_SRGB:
-+ calculate_rgb_matrix_legacy
-+ (core_color, sink_index, fixed_csc_matrix);
-+ convert_float_matrix_legacy
-+ (csc_matrix, fixed_csc_matrix, 12);
-+ break;
-+ case COLOR_SPACE_SRGB_LIMITED:
-+ calculate_rgb_limited_range_matrix(core_color, sink_index,
-+ fixed_csc_matrix);
-+ convert_float_matrix(csc_matrix, fixed_csc_matrix, 12);
-+ break;
-+ case COLOR_SPACE_YCBCR601:
-+ case COLOR_SPACE_YCBCR709:
-+ case COLOR_SPACE_YCBCR601_LIMITED:
-+ case COLOR_SPACE_YCBCR709_LIMITED:
-+ case COLOR_SPACE_YPBPR601:
-+ case COLOR_SPACE_YPBPR709:
-+ calculate_yuv_matrix(core_color, sink_index, color_space,
-+ fixed_csc_matrix);
-+ convert_float_matrix(csc_matrix, fixed_csc_matrix, 12);
-+ break;
-+ default:
-+ calculate_rgb_matrix_legacy
-+ (core_color, sink_index, fixed_csc_matrix);
-+ convert_float_matrix_legacy
-+ (csc_matrix, fixed_csc_matrix, 12);
-+ break;
-+ }
-+}
-+
-+struct mod_color *mod_color_create(struct dc *dc)
-+{
-+ int i = 0;
-+ struct core_color *core_color =
-+ dm_alloc(sizeof(struct core_color));
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+ struct persistent_data_flag flag;
-+
-+ if (core_color == NULL)
-+ goto fail_alloc_context;
-+
-+ core_color->caps = dm_alloc(sizeof(struct sink_caps) *
-+ MOD_COLOR_MAX_CONCURRENT_SINKS);
-+
-+ if (core_color->caps == NULL)
-+ goto fail_alloc_caps;
-+
-+ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++)
-+ core_color->caps[i].sink = NULL;
-+
-+ core_color->state = dm_alloc(sizeof(struct color_state) *
-+ MOD_COLOR_MAX_CONCURRENT_SINKS);
-+
-+ /*hardcoded to sRGB with 6500 color temperature*/
-+ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) {
-+ core_color->state[i].source_gamut.blueX = 1500;
-+ core_color->state[i].source_gamut.blueY = 600;
-+ core_color->state[i].source_gamut.greenX = 3000;
-+ core_color->state[i].source_gamut.greenY = 6000;
-+ core_color->state[i].source_gamut.redX = 6400;
-+ core_color->state[i].source_gamut.redY = 3300;
-+ core_color->state[i].source_gamut.whiteX = 3127;
-+ core_color->state[i].source_gamut.whiteY = 3290;
-+
-+ core_color->state[i].destination_gamut.blueX = 1500;
-+ core_color->state[i].destination_gamut.blueY = 600;
-+ core_color->state[i].destination_gamut.greenX = 3000;
-+ core_color->state[i].destination_gamut.greenY = 6000;
-+ core_color->state[i].destination_gamut.redX = 6400;
-+ core_color->state[i].destination_gamut.redY = 3300;
-+ core_color->state[i].destination_gamut.whiteX = 3127;
-+ core_color->state[i].destination_gamut.whiteY = 3290;
-+
-+ core_color->state[i].custom_color_temperature = 6500;
-+
-+ core_color->state[i].contrast.current = 100;
-+ core_color->state[i].contrast.min = 0;
-+ core_color->state[i].contrast.max = 200;
-+
-+ core_color->state[i].saturation.current = 100;
-+ core_color->state[i].saturation.min = 0;
-+ core_color->state[i].saturation.max = 200;
-+
-+ core_color->state[i].brightness.current = 0;
-+ core_color->state[i].brightness.min = -100;
-+ core_color->state[i].brightness.max = 100;
-+
-+ core_color->state[i].hue.current = 0;
-+ core_color->state[i].hue.min = -30;
-+ core_color->state[i].hue.max = 30;
-+ }
-+
-+ if (core_color->state == NULL)
-+ goto fail_alloc_state;
-+
-+ core_color->num_sinks = 0;
-+
-+ if (dc == NULL)
-+ goto fail_construct;
-+
-+ core_color->dc = dc;
-+
-+ if (!check_dc_support(dc))
-+ goto fail_construct;
-+
-+ /* Create initial module folder in registry for color adjustment */
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ dm_write_persistent_data(core_dc->ctx, NULL, COLOR_REGISTRY_NAME, NULL,
-+ NULL, 0, &flag);
-+
-+ return &core_color->public;
-+
-+fail_construct:
-+ dm_free(core_color->state);
-+
-+fail_alloc_state:
-+ dm_free(core_color->caps);
-+
-+fail_alloc_caps:
-+ dm_free(core_color);
-+
-+fail_alloc_context:
-+ return NULL;
-+}
-+
-+void mod_color_destroy(struct mod_color *mod_color)
-+{
-+ if (mod_color != NULL) {
-+ int i;
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ dm_free(core_color->state);
-+
-+ for (i = 0; i < core_color->num_sinks; i++)
-+ dc_sink_release(core_color->caps[i].sink);
-+
-+ dm_free(core_color->caps);
-+
-+ dm_free(core_color);
-+ }
-+}
-+
-+bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ bool persistent_color_temp_enable;
-+ int persistent_custom_color_temp = 0;
-+ struct color_space_coordinates persistent_source_gamut;
-+ struct color_space_coordinates persistent_destination_gamut;
-+ int persistent_brightness;
-+ int persistent_contrast;
-+ int persistent_hue;
-+ int persistent_saturation;
-+ enum dc_quantization_range persistent_quantization_range;
-+ struct persistent_data_flag flag;
-+
-+ if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) {
-+ dc_sink_retain(sink);
-+ core_color->caps[core_color->num_sinks].sink = sink;
-+ core_color->state[core_color->num_sinks].
-+ user_enable_color_temperature = true;
-+
-+ /* get persistent data from registry */
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink,
-+ COLOR_REGISTRY_NAME,
-+ "enablecolortempadj",
-+ &persistent_color_temp_enable,
-+ sizeof(bool), &flag))
-+ core_color->state[core_color->num_sinks].
-+ user_enable_color_temperature =
-+ persistent_color_temp_enable;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ user_enable_color_temperature = true;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink,
-+ COLOR_REGISTRY_NAME,
-+ "customcolortemp",
-+ &persistent_custom_color_temp,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ custom_color_temperature
-+ = persistent_custom_color_temp;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ custom_color_temperature = 6500;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink,
-+ COLOR_REGISTRY_NAME,
-+ "sourcegamut",
-+ &persistent_source_gamut,
-+ sizeof(struct color_space_coordinates),
-+ &flag)) {
-+ memcpy(&core_color->state[core_color->num_sinks].
-+ source_gamut, &persistent_source_gamut,
-+ sizeof(struct color_space_coordinates));
-+ } else {
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.blueX = 1500;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.blueY = 600;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.greenX = 3000;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.greenY = 6000;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.redX = 6400;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.redY = 3300;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.whiteX = 3127;
-+ core_color->state[core_color->num_sinks].
-+ source_gamut.whiteY = 3290;
-+ }
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME,
-+ "destgamut",
-+ &persistent_destination_gamut,
-+ sizeof(struct color_space_coordinates),
-+ &flag)) {
-+ memcpy(&core_color->state[core_color->num_sinks].
-+ destination_gamut,
-+ &persistent_destination_gamut,
-+ sizeof(struct color_space_coordinates));
-+ } else {
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.blueX = 1500;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.blueY = 600;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.greenX = 3000;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.greenY = 6000;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.redX = 6400;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.redY = 3300;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.whiteX = 3127;
-+ core_color->state[core_color->num_sinks].
-+ destination_gamut.whiteY = 3290;
-+ }
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME,
-+ "brightness",
-+ &persistent_brightness,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ brightness.current = persistent_brightness;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ brightness.current = 0;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME,
-+ "contrast",
-+ &persistent_contrast,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ contrast.current = persistent_contrast;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ contrast.current = 100;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME,
-+ "hue",
-+ &persistent_hue,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ hue.current = persistent_hue;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ hue.current = 0;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME,
-+ "saturation",
-+ &persistent_saturation,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ saturation.current = persistent_saturation;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ saturation.current = 100;
-+
-+ if (dm_read_persistent_data(core_dc->ctx, sink,
-+ COLOR_REGISTRY_NAME,
-+ "preferred_quantization_range",
-+ &persistent_quantization_range,
-+ sizeof(int), &flag))
-+ core_color->state[core_color->num_sinks].
-+ preferred_quantization_range =
-+ persistent_quantization_range;
-+ else
-+ core_color->state[core_color->num_sinks].
-+ preferred_quantization_range = QUANTIZATION_RANGE_FULL;
-+
-+ core_color->num_sinks++;
-+ return true;
-+ }
-+ return false;
-+}
-+
-+bool mod_color_remove_sink(struct mod_color *mod_color,
-+ const struct dc_sink *sink)
-+{
-+ int i = 0, j = 0;
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+
-+ for (i = 0; i < core_color->num_sinks; i++) {
-+ if (core_color->caps[i].sink == sink) {
-+ /* To remove this sink, shift everything after down */
-+ for (j = i; j < core_color->num_sinks - 1; j++) {
-+ core_color->caps[j].sink =
-+ core_color->caps[j + 1].sink;
-+
-+ memcpy(&core_color->state[j],
-+ &core_color->state[j + 1],
-+ sizeof(struct color_state));
-+ }
-+
-+ core_color->num_sinks--;
-+
-+ dc_sink_release(sink);
-+
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+bool mod_color_update_gamut_to_stream(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ struct gamut_src_dst_matrix *matrix =
-+ dm_alloc(sizeof(struct gamut_src_dst_matrix));
-+
-+ unsigned int stream_index, sink_index, j;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "sourcegamut",
-+ &core_color->state[sink_index].
-+ source_gamut,
-+ sizeof(struct color_space_coordinates),
-+ &flag);
-+
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "destgamut",
-+ &core_color->state[sink_index].
-+ destination_gamut,
-+ sizeof(struct color_space_coordinates),
-+ &flag);
-+
-+ if (!build_gamut_remap_matrix
-+ (core_color->state[sink_index].source_gamut,
-+ matrix->rgbCoeffSrc,
-+ matrix->whiteCoeffSrc))
-+ goto function_fail;
-+
-+ if (!build_gamut_remap_matrix
-+ (core_color->state[sink_index].
-+ destination_gamut,
-+ matrix->rgbCoeffDst, matrix->whiteCoeffDst))
-+ goto function_fail;
-+
-+ struct fixed31_32 gamut_result[12];
-+ struct fixed31_32 temp_matrix[9];
-+
-+ if (!gamut_to_color_matrix(
-+ matrix->rgbCoeffDst,
-+ matrix->whiteCoeffDst,
-+ matrix->rgbCoeffSrc,
-+ matrix->whiteCoeffSrc,
-+ true,
-+ temp_matrix))
-+ goto function_fail;
-+
-+ gamut_result[0] = temp_matrix[0];
-+ gamut_result[1] = temp_matrix[1];
-+ gamut_result[2] = temp_matrix[2];
-+ gamut_result[3] = matrix->whiteCoeffSrc[0];
-+ gamut_result[4] = temp_matrix[3];
-+ gamut_result[5] = temp_matrix[4];
-+ gamut_result[6] = temp_matrix[5];
-+ gamut_result[7] = matrix->whiteCoeffSrc[1];
-+ gamut_result[8] = temp_matrix[6];
-+ gamut_result[9] = temp_matrix[7];
-+ gamut_result[10] = temp_matrix[8];
-+ gamut_result[11] = matrix->whiteCoeffSrc[2];
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_stream->public.gamut_remap_matrix.enable_remap = true;
-+
-+ for (j = 0; j < 12; j++)
-+ core_stream->public.
-+ gamut_remap_matrix.matrix[j] =
-+ gamut_result[j];
-+ }
-+
-+ dm_free(matrix);
-+ core_color->dc->stream_funcs.set_gamut_remap
-+ (core_color->dc, streams, num_streams);
-+
-+ return true;
-+
-+function_fail:
-+ dm_free(matrix);
-+ return false;
-+}
-+
-+bool mod_color_adjust_source_gamut(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct gamut_space_coordinates *input_gamut_coordinates,
-+ struct white_point_coodinates *input_white_point_coordinates)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ core_color->state[sink_index].source_gamut.blueX =
-+ input_gamut_coordinates->blueX;
-+ core_color->state[sink_index].source_gamut.blueY =
-+ input_gamut_coordinates->blueY;
-+ core_color->state[sink_index].source_gamut.greenX =
-+ input_gamut_coordinates->greenX;
-+ core_color->state[sink_index].source_gamut.greenY =
-+ input_gamut_coordinates->greenY;
-+ core_color->state[sink_index].source_gamut.redX =
-+ input_gamut_coordinates->redX;
-+ core_color->state[sink_index].source_gamut.redY =
-+ input_gamut_coordinates->redY;
-+ core_color->state[sink_index].source_gamut.whiteX =
-+ input_white_point_coordinates->whiteX;
-+ core_color->state[sink_index].source_gamut.whiteY =
-+ input_white_point_coordinates->whiteY;
-+ }
-+
-+ if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams))
-+ return false;
-+
-+ return true;
-+}
-+
-+bool mod_color_adjust_destination_gamut(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct gamut_space_coordinates *input_gamut_coordinates,
-+ struct white_point_coodinates *input_white_point_coordinates)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ core_color->state[sink_index].destination_gamut.blueX =
-+ input_gamut_coordinates->blueX;
-+ core_color->state[sink_index].destination_gamut.blueY =
-+ input_gamut_coordinates->blueY;
-+ core_color->state[sink_index].destination_gamut.greenX =
-+ input_gamut_coordinates->greenX;
-+ core_color->state[sink_index].destination_gamut.greenY =
-+ input_gamut_coordinates->greenY;
-+ core_color->state[sink_index].destination_gamut.redX =
-+ input_gamut_coordinates->redX;
-+ core_color->state[sink_index].destination_gamut.redY =
-+ input_gamut_coordinates->redY;
-+ core_color->state[sink_index].destination_gamut.whiteX =
-+ input_white_point_coordinates->whiteX;
-+ core_color->state[sink_index].destination_gamut.whiteY =
-+ input_white_point_coordinates->whiteY;
-+ }
-+
-+ if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams))
-+ return false;
-+
-+ return true;
-+}
-+
-+bool mod_color_set_white_point(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct white_point_coodinates *white_point)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams;
-+ stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+ core_color->state[sink_index].source_gamut.whiteX =
-+ white_point->whiteX;
-+ core_color->state[sink_index].source_gamut.whiteY =
-+ white_point->whiteY;
-+ }
-+
-+ if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams))
-+ return false;
-+
-+ return true;
-+}
-+
-+bool mod_color_set_user_enable(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ bool user_enable)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+ core_color->state[sink_index].user_enable_color_temperature
-+ = user_enable;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "enablecolortempadj",
-+ &user_enable,
-+ sizeof(bool),
-+ &flag);
-+ }
-+ return true;
-+}
-+
-+bool mod_color_get_user_enable(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ bool *user_enable)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *user_enable = core_color->state[sink_index].
-+ user_enable_color_temperature;
-+
-+ return true;
-+}
-+
-+bool mod_color_get_custom_color_temperature(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ int *color_temperature)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *color_temperature = core_color->state[sink_index].
-+ custom_color_temperature;
-+
-+ return true;
-+}
-+
-+bool mod_color_set_custom_color_temperature(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int color_temperature)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+ core_color->state[sink_index].custom_color_temperature
-+ = color_temperature;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "customcolortemp",
-+ &color_temperature,
-+ sizeof(int),
-+ &flag);
-+ }
-+ return true;
-+}
-+
-+bool mod_color_get_color_saturation(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_saturation)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *color_saturation = core_color->state[sink_index].saturation;
-+
-+ return true;
-+}
-+
-+bool mod_color_get_color_contrast(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_contrast)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *color_contrast = core_color->state[sink_index].contrast;
-+
-+ return true;
-+}
-+
-+bool mod_color_get_color_brightness(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_brightness)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *color_brightness = core_color->state[sink_index].brightness;
-+
-+ return true;
-+}
-+
-+bool mod_color_get_color_hue(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_hue)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *color_hue = core_color->state[sink_index].hue;
-+
-+ return true;
-+}
-+
-+bool mod_color_get_source_gamut(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_space_coordinates *source_gamut)
-+{
-+ struct core_color *core_color =
-+ MOD_COLOR_TO_CORE(mod_color);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_color, sink);
-+
-+ *source_gamut = core_color->state[sink_index].source_gamut;
-+
-+ return true;
-+}
-+
-+bool mod_color_notify_mode_change(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+
-+ struct gamut_src_dst_matrix *matrix =
-+ dm_alloc(sizeof(struct gamut_src_dst_matrix));
-+
-+ unsigned int stream_index, sink_index, j;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ if (!build_gamut_remap_matrix
-+ (core_color->state[sink_index].source_gamut,
-+ matrix->rgbCoeffSrc,
-+ matrix->whiteCoeffSrc))
-+ goto function_fail;
-+
-+ if (!build_gamut_remap_matrix
-+ (core_color->state[sink_index].
-+ destination_gamut,
-+ matrix->rgbCoeffDst, matrix->whiteCoeffDst))
-+ goto function_fail;
-+
-+ struct fixed31_32 gamut_result[12];
-+ struct fixed31_32 temp_matrix[9];
-+
-+ if (!gamut_to_color_matrix(
-+ matrix->rgbCoeffDst,
-+ matrix->whiteCoeffDst,
-+ matrix->rgbCoeffSrc,
-+ matrix->whiteCoeffSrc,
-+ true,
-+ temp_matrix))
-+ goto function_fail;
-+
-+ gamut_result[0] = temp_matrix[0];
-+ gamut_result[1] = temp_matrix[1];
-+ gamut_result[2] = temp_matrix[2];
-+ gamut_result[3] = matrix->whiteCoeffSrc[0];
-+ gamut_result[4] = temp_matrix[3];
-+ gamut_result[5] = temp_matrix[4];
-+ gamut_result[6] = temp_matrix[5];
-+ gamut_result[7] = matrix->whiteCoeffSrc[1];
-+ gamut_result[8] = temp_matrix[6];
-+ gamut_result[9] = temp_matrix[7];
-+ gamut_result[10] = temp_matrix[8];
-+ gamut_result[11] = matrix->whiteCoeffSrc[2];
-+
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_stream->public.gamut_remap_matrix.enable_remap = true;
-+
-+ for (j = 0; j < 12; j++)
-+ core_stream->public.
-+ gamut_remap_matrix.matrix[j] =
-+ gamut_result[j];
-+
-+ calculate_csc_matrix(core_color, sink_index,
-+ core_stream->public.output_color_space,
-+ core_stream->public.csc_color_matrix.matrix);
-+
-+ core_stream->public.csc_color_matrix.enable_adjustment = true;
-+ }
-+
-+ dm_free(matrix);
-+
-+ return true;
-+
-+function_fail:
-+ dm_free(matrix);
-+ return false;
-+}
-+
-+bool mod_color_set_brightness(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int brightness_value)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_color->state[sink_index].brightness.current =
-+ brightness_value;
-+
-+ calculate_csc_matrix(core_color, sink_index,
-+ core_stream->public.output_color_space,
-+ core_stream->public.csc_color_matrix.matrix);
-+
-+ core_stream->public.csc_color_matrix.enable_adjustment = true;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "brightness",
-+ &brightness_value,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ core_color->dc->stream_funcs.set_gamut_remap
-+ (core_color->dc, streams, num_streams);
-+
-+ return true;
-+}
-+
-+bool mod_color_set_contrast(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int contrast_value)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_color->state[sink_index].contrast.current =
-+ contrast_value;
-+
-+ calculate_csc_matrix(core_color, sink_index,
-+ core_stream->public.output_color_space,
-+ core_stream->public.csc_color_matrix.matrix);
-+
-+ core_stream->public.csc_color_matrix.enable_adjustment = true;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "contrast",
-+ &contrast_value,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ core_color->dc->stream_funcs.set_gamut_remap
-+ (core_color->dc, streams, num_streams);
-+
-+ return true;
-+}
-+
-+bool mod_color_set_hue(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int hue_value)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_color->state[sink_index].hue.current = hue_value;
-+
-+ calculate_csc_matrix(core_color, sink_index,
-+ core_stream->public.output_color_space,
-+ core_stream->public.csc_color_matrix.matrix);
-+
-+ core_stream->public.csc_color_matrix.enable_adjustment = true;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "hue",
-+ &hue_value,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ core_color->dc->stream_funcs.set_gamut_remap
-+ (core_color->dc, streams, num_streams);
-+
-+ return true;
-+}
-+
-+bool mod_color_set_saturation(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int saturation_value)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int stream_index, sink_index;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ sink_index = sink_index_from_sink(core_color,
-+ streams[stream_index]->sink);
-+
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE
-+ (streams[stream_index]);
-+
-+ core_color->state[sink_index].saturation.current =
-+ saturation_value;
-+
-+ calculate_csc_matrix(core_color, sink_index,
-+ core_stream->public.output_color_space,
-+ core_stream->public.csc_color_matrix.matrix);
-+
-+ core_stream->public.csc_color_matrix.enable_adjustment = true;
-+
-+ /* Write persistent data in registry*/
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ COLOR_REGISTRY_NAME,
-+ "saturation",
-+ &saturation_value,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ core_color->dc->stream_funcs.set_gamut_remap
-+ (core_color->dc, streams, num_streams);
-+
-+ return true;
-+}
-+
-+bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ enum dc_quantization_range quantization_range)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ struct core_dc *core_dc = DC_TO_CORE(core_color->dc);
-+ struct persistent_data_flag flag;
-+ unsigned int sink_index;
-+
-+ sink_index = sink_index_from_sink(core_color, sink);
-+ if (core_color->state[sink_index].
-+ preferred_quantization_range != quantization_range) {
-+ core_color->state[sink_index].preferred_quantization_range =
-+ quantization_range;
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx,
-+ sink,
-+ COLOR_REGISTRY_NAME,
-+ "quantization_range",
-+ &quantization_range,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ return true;
-+}
-+
-+bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ enum dc_quantization_range *quantization_range)
-+{
-+ struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
-+ unsigned int sink_index;
-+
-+ sink_index = sink_index_from_sink(core_color, sink);
-+ *quantization_range = core_color->state[sink_index].
-+ preferred_quantization_range;
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/display/modules/freesync/Makefile b/drivers/gpu/drm/amd/display/modules/freesync/Makefile
-new file mode 100644
-index 0000000..db8e0ff
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/freesync/Makefile
-@@ -0,0 +1,10 @@
-+#
-+# Makefile for the 'freesync' sub-module of DAL.
-+#
-+
-+FREESYNC = freesync.o
-+
-+AMD_DAL_FREESYNC = $(addprefix $(AMDDALPATH)/modules/freesync/,$(FREESYNC))
-+#$(info ************ DAL-FREE SYNC_MAKEFILE ************)
-+
-+AMD_DISPLAY_FILES += $(AMD_DAL_FREESYNC)
-diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
-new file mode 100644
-index 0000000..eb912ba
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
-@@ -0,0 +1,1158 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "dm_services.h"
-+#include "dc.h"
-+#include "mod_freesync.h"
-+#include "core_types.h"
-+#include "core_dc.h"
-+
-+#define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32
-+
-+/* Refresh rate ramp at a fixed rate of 65 Hz/second */
-+#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
-+/* Number of elements in the render times cache array */
-+#define RENDER_TIMES_MAX_COUNT 20
-+/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
-+#define BTR_EXIT_MARGIN 2000
-+
-+#define FREESYNC_REGISTRY_NAME "freesync_v1"
-+
-+struct gradual_static_ramp {
-+ bool ramp_is_active;
-+ bool ramp_direction_is_up;
-+ unsigned int ramp_current_frame_duration_in_ns;
-+};
-+
-+struct time_cache {
-+ /* video (48Hz feature) related */
-+ unsigned int update_duration_in_ns;
-+
-+ /* BTR/fixed refresh related */
-+ unsigned int prev_time_stamp_in_us;
-+
-+ unsigned int min_render_time_in_us;
-+ unsigned int max_render_time_in_us;
-+
-+ unsigned int render_times_index;
-+ unsigned int render_times[RENDER_TIMES_MAX_COUNT];
-+};
-+
-+struct below_the_range {
-+ bool btr_active;
-+ bool program_btr;
-+
-+ unsigned int mid_point_in_us;
-+
-+ unsigned int inserted_frame_duration_in_us;
-+ unsigned int frames_to_insert;
-+ unsigned int frame_counter;
-+};
-+
-+struct fixed_refresh {
-+ bool fixed_refresh_active;
-+ bool program_fixed_refresh;
-+};
-+
-+struct freesync_state {
-+ bool fullscreen;
-+ bool static_screen;
-+ bool video;
-+
-+ unsigned int nominal_refresh_rate_in_micro_hz;
-+ bool windowed_fullscreen;
-+
-+ struct time_cache time;
-+
-+ struct gradual_static_ramp static_ramp;
-+ struct below_the_range btr;
-+ struct fixed_refresh fixed_refresh;
-+};
-+
-+struct freesync_entity {
-+ const struct dc_stream *stream;
-+ struct mod_freesync_caps *caps;
-+ struct freesync_state state;
-+ struct mod_freesync_user_enable user_enable;
-+};
-+
-+struct core_freesync {
-+ struct mod_freesync public;
-+ struct dc *dc;
-+ struct freesync_entity *map;
-+ int num_entities;
-+};
-+
-+#define MOD_FREESYNC_TO_CORE(mod_freesync)\
-+ container_of(mod_freesync, struct core_freesync, public)
-+
-+static bool check_dc_support(const struct dc *dc)
-+{
-+ if (dc->stream_funcs.adjust_vmin_vmax == NULL)
-+ return false;
-+
-+ return true;
-+}
-+
-+struct mod_freesync *mod_freesync_create(struct dc *dc)
-+{
-+ struct core_freesync *core_freesync =
-+ dm_alloc(sizeof(struct core_freesync));
-+
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+
-+ struct persistent_data_flag flag;
-+
-+ int i = 0;
-+
-+ if (core_freesync == NULL)
-+ goto fail_alloc_context;
-+
-+ core_freesync->map = dm_alloc(sizeof(struct freesync_entity) *
-+ MOD_FREESYNC_MAX_CONCURRENT_STREAMS);
-+
-+ if (core_freesync->map == NULL)
-+ goto fail_alloc_map;
-+
-+ for (i = 0; i < MOD_FREESYNC_MAX_CONCURRENT_STREAMS; i++)
-+ core_freesync->map[i].stream = NULL;
-+
-+ core_freesync->num_entities = 0;
-+
-+ if (dc == NULL)
-+ goto fail_construct;
-+
-+ core_freesync->dc = dc;
-+
-+ if (!check_dc_support(dc))
-+ goto fail_construct;
-+
-+ /* Create initial module folder in registry for freesync enable data */
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+ dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL,
-+ 0, &flag);
-+
-+ return &core_freesync->public;
-+
-+fail_construct:
-+ dm_free(core_freesync->map);
-+
-+fail_alloc_map:
-+ dm_free(core_freesync);
-+
-+fail_alloc_context:
-+ return NULL;
-+}
-+
-+void mod_freesync_destroy(struct mod_freesync *mod_freesync)
-+{
-+ if (mod_freesync != NULL) {
-+ int i;
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ for (i = 0; i < core_freesync->num_entities; i++)
-+ if (core_freesync->map[i].stream)
-+ dc_stream_release(core_freesync->map[i].stream);
-+
-+ dm_free(core_freesync->map);
-+
-+ dm_free(core_freesync);
-+ }
-+}
-+
-+/* Given a specific dc_stream* this function finds its equivalent
-+ * on the core_freesync->map and returns the corresponding index
-+ */
-+static unsigned int map_index_from_stream(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream)
-+{
-+ unsigned int index = 0;
-+
-+ for (index = 0; index < core_freesync->num_entities; index++) {
-+ if (core_freesync->map[index].stream == stream) {
-+ return index;
-+ }
-+ }
-+ /* Could not find stream requested */
-+ ASSERT(false);
-+ return index;
-+}
-+
-+bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream, struct mod_freesync_caps *caps)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+ struct core_stream *core_stream =
-+ DC_STREAM_TO_CORE(stream);
-+ struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc);
-+
-+ int persistent_freesync_enable = 0;
-+ struct persistent_data_flag flag;
-+
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ if (core_freesync->num_entities < MOD_FREESYNC_MAX_CONCURRENT_STREAMS) {
-+
-+ dc_stream_retain(stream);
-+
-+ core_freesync->map[core_freesync->num_entities].stream = stream;
-+ core_freesync->map[core_freesync->num_entities].caps = caps;
-+
-+ core_freesync->map[core_freesync->num_entities].state.
-+ fullscreen = false;
-+ core_freesync->map[core_freesync->num_entities].state.
-+ static_screen = false;
-+ core_freesync->map[core_freesync->num_entities].state.
-+ video = false;
-+ core_freesync->map[core_freesync->num_entities].state.time.
-+ update_duration_in_ns = 0;
-+ core_freesync->map[core_freesync->num_entities].state.
-+ static_ramp.ramp_is_active = false;
-+
-+ /* get persistent data from registry */
-+ if (dm_read_persistent_data(core_dc->ctx, stream->sink,
-+ FREESYNC_REGISTRY_NAME,
-+ "userenable", &persistent_freesync_enable,
-+ sizeof(int), &flag)) {
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_gaming =
-+ (persistent_freesync_enable & 1) ? true : false;
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_static =
-+ (persistent_freesync_enable & 2) ? true : false;
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_video =
-+ (persistent_freesync_enable & 4) ? true : false;
-+ } else {
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_gaming = false;
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_static = false;
-+ core_freesync->map[core_freesync->num_entities].user_enable.
-+ enable_for_video = false;
-+ }
-+
-+ if (caps->supported)
-+ core_stream->public.ignore_msa_timing_param = 1;
-+
-+ core_freesync->num_entities++;
-+ return true;
-+ }
-+ return false;
-+}
-+
-+bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ int i = 0;
-+ unsigned int index = map_index_from_stream(core_freesync, stream);
-+ dc_stream_release(core_freesync->map[index].stream);
-+ core_freesync->map[index].stream = NULL;
-+ /* To remove this entity, shift everything after down */
-+ for (i = index; i < core_freesync->num_entities - 1; i++)
-+ core_freesync->map[i] = core_freesync->map[i + 1];
-+ core_freesync->num_entities--;
-+ return true;
-+}
-+
-+static void update_stream_freesync_context(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream)
-+{
-+ unsigned int index;
-+ struct freesync_context *ctx;
-+ struct core_stream *core_stream;
-+
-+ core_stream = DC_STREAM_TO_CORE(stream);
-+ ctx = &core_stream->public.freesync_ctx;
-+
-+ index = map_index_from_stream(core_freesync, stream);
-+
-+ ctx->supported = core_freesync->map[index].caps->supported;
-+ ctx->enabled = (core_freesync->map[index].user_enable.enable_for_gaming ||
-+ core_freesync->map[index].user_enable.enable_for_video ||
-+ core_freesync->map[index].user_enable.enable_for_static);
-+ ctx->active = (core_freesync->map[index].state.fullscreen ||
-+ core_freesync->map[index].state.video ||
-+ core_freesync->map[index].state.static_ramp.ramp_is_active);
-+ ctx->min_refresh_in_micro_hz =
-+ core_freesync->map[index].caps->min_refresh_in_micro_hz;
-+ ctx->nominal_refresh_in_micro_hz = core_freesync->
-+ map[index].state.nominal_refresh_rate_in_micro_hz;
-+
-+}
-+
-+static void update_stream(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream)
-+{
-+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
-+
-+ unsigned int index = map_index_from_stream(core_freesync, stream);
-+ if (core_freesync->map[index].caps->supported) {
-+ core_stream->public.ignore_msa_timing_param = 1;
-+ update_stream_freesync_context(core_freesync, stream);
-+ }
-+}
-+
-+static void calc_vmin_vmax(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream, int *vmin, int *vmax)
-+{
-+ unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0;
-+ unsigned int index = map_index_from_stream(core_freesync, stream);
-+
-+ min_frame_duration_in_ns = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].state.
-+ nominal_refresh_rate_in_micro_hz)));
-+ max_frame_duration_in_ns = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].caps->min_refresh_in_micro_hz)));
-+
-+ *vmax = div64_u64(div64_u64(((unsigned long long)(
-+ max_frame_duration_in_ns) * stream->timing.pix_clk_khz),
-+ stream->timing.h_total), 1000000);
-+ *vmin = div64_u64(div64_u64(((unsigned long long)(
-+ min_frame_duration_in_ns) * stream->timing.pix_clk_khz),
-+ stream->timing.h_total), 1000000);
-+}
-+
-+static void calc_v_total_from_duration(const struct dc_stream *stream,
-+ unsigned int duration_in_ns, int *v_total_nominal)
-+{
-+ *v_total_nominal = div64_u64(div64_u64(((unsigned long long)(
-+ duration_in_ns) * stream->timing.pix_clk_khz),
-+ stream->timing.h_total), 1000000);
-+}
-+
-+static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream,
-+ unsigned int index, int *v_total)
-+{
-+ unsigned int frame_duration = 0;
-+
-+ struct gradual_static_ramp *static_ramp_variables =
-+ &core_freesync->map[index].state.static_ramp;
-+
-+ /* Calc ratio between new and current frame duration with 3 digit */
-+ unsigned int frame_duration_ratio = div64_u64(1000000,
-+ (1000 + div64_u64(((unsigned long long)(
-+ STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) *
-+ static_ramp_variables->ramp_current_frame_duration_in_ns),
-+ 1000000000)));
-+
-+ /* Calculate delta between new and current frame duration in ns */
-+ unsigned int frame_duration_delta = div64_u64(((unsigned long long)(
-+ static_ramp_variables->ramp_current_frame_duration_in_ns) *
-+ (1000 - frame_duration_ratio)), 1000);
-+
-+ /* Adjust frame duration delta based on ratio between current and
-+ * standard frame duration (frame duration at 60 Hz refresh rate).
-+ */
-+ unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)(
-+ frame_duration_delta) * static_ramp_variables->
-+ ramp_current_frame_duration_in_ns), 16666666);
-+
-+ /* Going to a higher refresh rate (lower frame duration) */
-+ if (static_ramp_variables->ramp_direction_is_up) {
-+ /* reduce frame duration */
-+ static_ramp_variables->ramp_current_frame_duration_in_ns -=
-+ ramp_rate_interpolated;
-+
-+ /* min frame duration */
-+ frame_duration = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].state.
-+ nominal_refresh_rate_in_micro_hz)));
-+
-+ /* adjust for frame duration below min */
-+ if (static_ramp_variables->ramp_current_frame_duration_in_ns <=
-+ frame_duration) {
-+
-+ static_ramp_variables->ramp_is_active = false;
-+ static_ramp_variables->
-+ ramp_current_frame_duration_in_ns =
-+ frame_duration;
-+ }
-+ /* Going to a lower refresh rate (larger frame duration) */
-+ } else {
-+ /* increase frame duration */
-+ static_ramp_variables->ramp_current_frame_duration_in_ns +=
-+ ramp_rate_interpolated;
-+
-+ /* max frame duration */
-+ frame_duration = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].caps->min_refresh_in_micro_hz)));
-+
-+ /* adjust for frame duration above max */
-+ if (static_ramp_variables->ramp_current_frame_duration_in_ns >=
-+ frame_duration) {
-+
-+ static_ramp_variables->ramp_is_active = false;
-+ static_ramp_variables->
-+ ramp_current_frame_duration_in_ns =
-+ frame_duration;
-+ }
-+ }
-+
-+ calc_v_total_from_duration(stream, static_ramp_variables->
-+ ramp_current_frame_duration_in_ns, v_total);
-+}
-+
-+static void reset_freesync_state_variables(struct freesync_state* state)
-+{
-+ state->static_ramp.ramp_is_active = false;
-+ if (state->nominal_refresh_rate_in_micro_hz)
-+ state->static_ramp.ramp_current_frame_duration_in_ns =
-+ ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ state->nominal_refresh_rate_in_micro_hz)));
-+
-+ state->btr.btr_active = false;
-+ state->btr.frame_counter = 0;
-+ state->btr.frames_to_insert = 0;
-+ state->btr.inserted_frame_duration_in_us = 0;
-+ state->btr.program_btr = false;
-+
-+ state->fixed_refresh.fixed_refresh_active = false;
-+ state->fixed_refresh.program_fixed_refresh = false;
-+}
-+/*
-+ * Sets freesync mode on a stream depending on current freesync state.
-+ */
-+static bool set_freesync_on_streams(struct core_freesync *core_freesync,
-+ const struct dc_stream **streams, int num_streams)
-+{
-+ int v_total_nominal = 0, v_total_min = 0, v_total_max = 0;
-+ unsigned int stream_idx, map_index = 0;
-+ struct freesync_state *state;
-+
-+ if (num_streams == 0 || streams == NULL || num_streams > 1)
-+ return false;
-+
-+ for (stream_idx = 0; stream_idx < num_streams; stream_idx++) {
-+
-+ map_index = map_index_from_stream(core_freesync,
-+ streams[stream_idx]);
-+
-+ state = &core_freesync->map[map_index].state;
-+
-+ if (core_freesync->map[map_index].caps->supported) {
-+
-+ /* Fullscreen has the topmost priority. If the
-+ * fullscreen bit is set, we are in a fullscreen
-+ * application where it should not matter if it is
-+ * static screen. We should not check the static_screen
-+ * or video bit.
-+ *
-+ * Special cases of fullscreen include btr and fixed
-+ * refresh. We program btr on every flip and involves
-+ * programming full range right before the last inserted frame.
-+ * However, we do not want to program the full freesync range
-+ * when fixed refresh is active, because we only program
-+ * that logic once and this will override it.
-+ */
-+ if (core_freesync->map[map_index].user_enable.
-+ enable_for_gaming == true &&
-+ state->fullscreen == true &&
-+ state->fixed_refresh.fixed_refresh_active == false) {
-+ /* Enable freesync */
-+
-+ calc_vmin_vmax(core_freesync,
-+ streams[stream_idx],
-+ &v_total_min, &v_total_max);
-+
-+ /* Update the freesync context for the stream */
-+ update_stream_freesync_context(core_freesync,
-+ streams[stream_idx]);
-+
-+ core_freesync->dc->stream_funcs.
-+ adjust_vmin_vmax(core_freesync->dc, streams,
-+ num_streams, v_total_min,
-+ v_total_max);
-+
-+ return true;
-+
-+ } else if (core_freesync->map[map_index].user_enable.
-+ enable_for_video && state->video == true) {
-+ /* Enable 48Hz feature */
-+
-+ calc_v_total_from_duration(streams[stream_idx],
-+ state->time.update_duration_in_ns,
-+ &v_total_nominal);
-+
-+ /* Program only if v_total_nominal is in range*/
-+ if (v_total_nominal >=
-+ streams[stream_idx]->timing.v_total) {
-+
-+ /* Update the freesync context for
-+ * the stream
-+ */
-+ update_stream_freesync_context(
-+ core_freesync,
-+ streams[stream_idx]);
-+
-+ core_freesync->dc->stream_funcs.
-+ adjust_vmin_vmax(
-+ core_freesync->dc, streams,
-+ num_streams, v_total_nominal,
-+ v_total_nominal);
-+ }
-+ return true;
-+
-+ } else {
-+ /* Disable freesync */
-+ v_total_nominal = streams[stream_idx]->
-+ timing.v_total;
-+
-+ /* Update the freesync context for
-+ * the stream
-+ */
-+ update_stream_freesync_context(
-+ core_freesync,
-+ streams[stream_idx]);
-+
-+ core_freesync->dc->stream_funcs.
-+ adjust_vmin_vmax(
-+ core_freesync->dc, streams,
-+ num_streams, v_total_nominal,
-+ v_total_nominal);
-+
-+ /* Reset the cached variables */
-+ reset_freesync_state_variables(state);
-+
-+ return true;
-+ }
-+ } else {
-+ /* Disable freesync */
-+ v_total_nominal = streams[stream_idx]->
-+ timing.v_total;
-+ /*
-+ * we have to reset drr always even sink does
-+ * not support freesync because a former stream has
-+ * be programmed
-+ */
-+ core_freesync->dc->stream_funcs.
-+ adjust_vmin_vmax(
-+ core_freesync->dc, streams,
-+ num_streams, v_total_nominal,
-+ v_total_nominal);
-+ /* Reset the cached variables */
-+ reset_freesync_state_variables(state);
-+ }
-+
-+ }
-+
-+ return false;
-+}
-+
-+static void set_static_ramp_variables(struct core_freesync *core_freesync,
-+ unsigned int index, bool enable_static_screen)
-+{
-+ unsigned int frame_duration = 0;
-+
-+ struct gradual_static_ramp *static_ramp_variables =
-+ &core_freesync->map[index].state.static_ramp;
-+
-+ /* If ramp is not active, set initial frame duration depending on
-+ * whether we are enabling/disabling static screen mode. If the ramp is
-+ * already active, ramp should continue in the opposite direction
-+ * starting with the current frame duration
-+ */
-+ if (!static_ramp_variables->ramp_is_active) {
-+
-+ static_ramp_variables->ramp_is_active = true;
-+
-+ if (enable_static_screen == true) {
-+ /* Going to lower refresh rate, so start from max
-+ * refresh rate (min frame duration)
-+ */
-+ frame_duration = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].state.
-+ nominal_refresh_rate_in_micro_hz)));
-+ } else {
-+ /* Going to higher refresh rate, so start from min
-+ * refresh rate (max frame duration)
-+ */
-+ frame_duration = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[index].caps->min_refresh_in_micro_hz)));
-+ }
-+
-+ static_ramp_variables->
-+ ramp_current_frame_duration_in_ns = frame_duration;
-+ }
-+
-+ /* If we are ENABLING static screen, refresh rate should go DOWN.
-+ * If we are DISABLING static screen, refresh rate should go UP.
-+ */
-+ static_ramp_variables->ramp_direction_is_up = !enable_static_screen;
-+}
-+
-+void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ unsigned int index, v_total = 0;
-+ struct freesync_state *state;
-+
-+ if (core_freesync->num_entities == 0)
-+ return;
-+
-+ index = map_index_from_stream(core_freesync,
-+ streams[0]);
-+
-+ if (core_freesync->map[index].caps->supported == false)
-+ return;
-+
-+ state = &core_freesync->map[index].state;
-+
-+ /* Below the Range Logic */
-+
-+ /* Only execute if in fullscreen mode */
-+ if (state->fullscreen == true &&
-+ core_freesync->map[index].user_enable.enable_for_gaming) {
-+
-+ if (state->btr.btr_active)
-+ if (state->btr.frame_counter > 0)
-+
-+ state->btr.frame_counter--;
-+
-+ if (state->btr.frame_counter == 1) {
-+
-+ /* Restore FreeSync */
-+ set_freesync_on_streams(core_freesync, streams,
-+ num_streams);
-+ }
-+ }
-+
-+ /* If in fullscreen freesync mode or in video, do not program
-+ * static screen ramp values
-+ */
-+ if (state->fullscreen == true || state->video == true) {
-+
-+ state->static_ramp.ramp_is_active = false;
-+
-+ return;
-+ }
-+
-+ /* Gradual Static Screen Ramping Logic */
-+
-+ /* Execute if ramp is active and user enabled freesync static screen*/
-+ if (state->static_ramp.ramp_is_active &&
-+ core_freesync->map[index].user_enable.enable_for_static) {
-+
-+ calc_v_total_for_static_ramp(core_freesync, streams[0],
-+ index, &v_total);
-+
-+ /* Update the freesync context for the stream */
-+ update_stream_freesync_context(core_freesync, streams[0]);
-+
-+ /* Program static screen ramp values */
-+ core_freesync->dc->stream_funcs.adjust_vmin_vmax(
-+ core_freesync->dc, streams,
-+ num_streams, v_total,
-+ v_total);
-+ }
-+}
-+
-+void mod_freesync_update_state(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ struct mod_freesync_params *freesync_params)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+ bool freesync_program_required = false;
-+ unsigned int stream_index;
-+ struct freesync_state *state;
-+
-+ if (core_freesync->num_entities == 0)
-+ return;
-+
-+ for(stream_index = 0; stream_index < num_streams; stream_index++) {
-+
-+ unsigned int map_index = map_index_from_stream(core_freesync,
-+ streams[stream_index]);
-+
-+ state = &core_freesync->map[map_index].state;
-+
-+ switch (freesync_params->state){
-+ case FREESYNC_STATE_FULLSCREEN:
-+ state->fullscreen = freesync_params->enable;
-+ freesync_program_required = true;
-+ state->windowed_fullscreen =
-+ freesync_params->windowed_fullscreen;
-+ break;
-+ case FREESYNC_STATE_STATIC_SCREEN:
-+ /* Static screen ramp is only enabled for embedded
-+ * panels. Also change core variables only if there
-+ * is a change.
-+ */
-+ if (dc_is_embedded_signal(
-+ streams[stream_index]->sink->sink_signal) &&
-+ state->static_screen !=
-+ freesync_params->enable) {
-+
-+ /* Change the state flag */
-+ state->static_screen = freesync_params->enable;
-+
-+ /* Change static screen ramp variables */
-+ set_static_ramp_variables(core_freesync,
-+ map_index,
-+ freesync_params->enable);
-+ }
-+ /* We program the ramp starting next VUpdate */
-+ break;
-+ case FREESYNC_STATE_VIDEO:
-+ /* Change core variables only if there is a change*/
-+ if(freesync_params->update_duration_in_ns !=
-+ state->time.update_duration_in_ns) {
-+
-+ state->video = freesync_params->enable;
-+ state->time.update_duration_in_ns =
-+ freesync_params->update_duration_in_ns;
-+
-+ freesync_program_required = true;
-+ }
-+ break;
-+ }
-+ }
-+
-+ if (freesync_program_required)
-+ /* Program freesync according to current state*/
-+ set_freesync_on_streams(core_freesync, streams, num_streams);
-+}
-+
-+
-+bool mod_freesync_get_state(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream,
-+ struct mod_freesync_params *freesync_params)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ unsigned int index = map_index_from_stream(core_freesync, stream);
-+
-+ if (core_freesync->map[index].state.fullscreen) {
-+ freesync_params->state = FREESYNC_STATE_FULLSCREEN;
-+ freesync_params->enable = true;
-+ } else if (core_freesync->map[index].state.static_screen) {
-+ freesync_params->state = FREESYNC_STATE_STATIC_SCREEN;
-+ freesync_params->enable = true;
-+ } else if (core_freesync->map[index].state.video) {
-+ freesync_params->state = FREESYNC_STATE_VIDEO;
-+ freesync_params->enable = true;
-+ } else {
-+ freesync_params->state = FREESYNC_STATE_NONE;
-+ freesync_params->enable = false;
-+ }
-+
-+ freesync_params->update_duration_in_ns =
-+ core_freesync->map[index].state.time.update_duration_in_ns;
-+
-+ return true;
-+}
-+
-+bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ struct mod_freesync_user_enable *user_enable)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+ struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc);
-+
-+ unsigned int stream_index, map_index;
-+ int persistent_data = 0;
-+ struct persistent_data_flag flag;
-+
-+ flag.save_per_edid = true;
-+ flag.save_per_link = false;
-+
-+ for(stream_index = 0; stream_index < num_streams;
-+ stream_index++){
-+
-+ map_index = map_index_from_stream(core_freesync,
-+ streams[stream_index]);
-+
-+ core_freesync->map[map_index].user_enable = *user_enable;
-+
-+ /* Write persistent data in registry*/
-+ if (core_freesync->map[map_index].user_enable.
-+ enable_for_gaming)
-+ persistent_data = persistent_data | 1;
-+ if (core_freesync->map[map_index].user_enable.
-+ enable_for_static)
-+ persistent_data = persistent_data | 2;
-+ if (core_freesync->map[map_index].user_enable.
-+ enable_for_video)
-+ persistent_data = persistent_data | 4;
-+
-+ dm_write_persistent_data(core_dc->ctx,
-+ streams[stream_index]->sink,
-+ FREESYNC_REGISTRY_NAME,
-+ "userenable",
-+ &persistent_data,
-+ sizeof(int),
-+ &flag);
-+ }
-+
-+ set_freesync_on_streams(core_freesync, streams, num_streams);
-+
-+ return true;
-+}
-+
-+bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream,
-+ struct mod_freesync_user_enable *user_enable)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ unsigned int index = map_index_from_stream(core_freesync, stream);
-+
-+ *user_enable = core_freesync->map[index].user_enable;
-+
-+ return true;
-+}
-+
-+void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams)
-+{
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ unsigned int stream_index, map_index;
-+ unsigned min_frame_duration_in_ns, max_frame_duration_in_ns;
-+ struct freesync_state *state;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+
-+ map_index = map_index_from_stream(core_freesync,
-+ streams[stream_index]);
-+
-+ state = &core_freesync->map[map_index].state;
-+
-+ if (core_freesync->map[map_index].caps->supported) {
-+ /* Update the field rate for new timing */
-+ state->nominal_refresh_rate_in_micro_hz = 1000000 *
-+ div64_u64(div64_u64((streams[stream_index]->
-+ timing.pix_clk_khz * 1000),
-+ streams[stream_index]->timing.v_total),
-+ streams[stream_index]->timing.h_total);
-+
-+ /* Update the stream */
-+ update_stream(core_freesync, streams[stream_index]);
-+
-+ /* Determine whether BTR can be supported */
-+ min_frame_duration_in_ns = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ state->nominal_refresh_rate_in_micro_hz)));
-+
-+ max_frame_duration_in_ns = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ core_freesync->map[map_index].caps->min_refresh_in_micro_hz)));
-+
-+ if (max_frame_duration_in_ns >=
-+ 2 * min_frame_duration_in_ns)
-+ core_freesync->map[map_index].caps->btr_supported = true;
-+ else
-+ core_freesync->map[map_index].caps->btr_supported = false;
-+
-+ /* Cache the time variables */
-+ state->time.max_render_time_in_us =
-+ max_frame_duration_in_ns / 1000;
-+ state->time.min_render_time_in_us =
-+ min_frame_duration_in_ns / 1000;
-+ state->btr.mid_point_in_us =
-+ (max_frame_duration_in_ns +
-+ min_frame_duration_in_ns) / 2000;
-+
-+ }
-+ }
-+
-+ /* Program freesync according to current state*/
-+ set_freesync_on_streams(core_freesync, streams, num_streams);
-+}
-+
-+/* Add the timestamps to the cache and determine whether BTR programming
-+ * is required, depending on the times calculated
-+ */
-+static void update_timestamps(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream, unsigned int map_index,
-+ unsigned int last_render_time_in_us)
-+{
-+ struct freesync_state *state = &core_freesync->map[map_index].state;
-+
-+ state->time.render_times[state->time.render_times_index] =
-+ last_render_time_in_us;
-+ state->time.render_times_index++;
-+
-+ if (state->time.render_times_index >= RENDER_TIMES_MAX_COUNT)
-+ state->time.render_times_index = 0;
-+
-+ if (last_render_time_in_us + BTR_EXIT_MARGIN <
-+ state->time.max_render_time_in_us) {
-+
-+ /* Exit Below the Range */
-+ if (state->btr.btr_active) {
-+
-+ state->btr.program_btr = true;
-+ state->btr.btr_active = false;
-+ state->btr.frame_counter = 0;
-+
-+ /* Exit Fixed Refresh mode */
-+ } else if (state->fixed_refresh.fixed_refresh_active) {
-+
-+ state->fixed_refresh.program_fixed_refresh = true;
-+ state->fixed_refresh.fixed_refresh_active = false;
-+
-+ }
-+
-+ } else if (last_render_time_in_us > state->time.max_render_time_in_us) {
-+
-+ /* Enter Below the Range */
-+ if (!state->btr.btr_active &&
-+ core_freesync->map[map_index].caps->btr_supported) {
-+
-+ state->btr.program_btr = true;
-+ state->btr.btr_active = true;
-+
-+ /* Enter Fixed Refresh mode */
-+ } else if (!state->fixed_refresh.fixed_refresh_active &&
-+ !core_freesync->map[map_index].caps->btr_supported) {
-+
-+ state->fixed_refresh.program_fixed_refresh = true;
-+ state->fixed_refresh.fixed_refresh_active = true;
-+
-+ }
-+ }
-+
-+ /* When Below the Range is active, must react on every frame */
-+ if (state->btr.btr_active)
-+ state->btr.program_btr = true;
-+}
-+
-+static void apply_below_the_range(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream, unsigned int map_index,
-+ unsigned int last_render_time_in_us)
-+{
-+ unsigned int inserted_frame_duration_in_us = 0;
-+ unsigned int mid_point_frames_ceil = 0;
-+ unsigned int mid_point_frames_floor = 0;
-+ unsigned int frame_time_in_us = 0;
-+ unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
-+ unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
-+ unsigned int frames_to_insert = 0;
-+ unsigned int inserted_frame_v_total = 0;
-+ unsigned int vmin = 0, vmax = 0;
-+ unsigned int min_frame_duration_in_ns = 0;
-+ struct freesync_state *state = &core_freesync->map[map_index].state;
-+
-+ if (!state->btr.program_btr)
-+ return;
-+
-+ state->btr.program_btr = false;
-+
-+ min_frame_duration_in_ns = ((unsigned int) (div64_u64(
-+ (1000000000ULL * 1000000),
-+ state->nominal_refresh_rate_in_micro_hz)));
-+
-+ /* Program BTR */
-+
-+ /* BTR set to "not active" so disengage */
-+ if (!state->btr.btr_active)
-+
-+ /* Restore FreeSync */
-+ set_freesync_on_streams(core_freesync, &stream, 1);
-+
-+ /* BTR set to "active" so engage */
-+ else {
-+
-+ /* Calculate number of midPoint frames that could fit within
-+ * the render time interval- take ceil of this value
-+ */
-+ mid_point_frames_ceil = (last_render_time_in_us +
-+ state->btr.mid_point_in_us- 1) /
-+ state->btr.mid_point_in_us;
-+
-+ if (mid_point_frames_ceil > 0) {
-+
-+ frame_time_in_us = last_render_time_in_us /
-+ mid_point_frames_ceil;
-+ delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us >
-+ frame_time_in_us) ?
-+ (state->btr.mid_point_in_us - frame_time_in_us):
-+ (frame_time_in_us - state->btr.mid_point_in_us);
-+ }
-+
-+ /* Calculate number of midPoint frames that could fit within
-+ * the render time interval- take floor of this value
-+ */
-+ mid_point_frames_floor = last_render_time_in_us /
-+ state->btr.mid_point_in_us;
-+
-+ if (mid_point_frames_floor > 0) {
-+
-+ frame_time_in_us = last_render_time_in_us /
-+ mid_point_frames_floor;
-+ delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us >
-+ frame_time_in_us) ?
-+ (state->btr.mid_point_in_us - frame_time_in_us):
-+ (frame_time_in_us - state->btr.mid_point_in_us);
-+ }
-+
-+ /* Choose number of frames to insert based on how close it
-+ * can get to the mid point of the variable range.
-+ */
-+ if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2)
-+ frames_to_insert = mid_point_frames_ceil;
-+ else
-+ frames_to_insert = mid_point_frames_floor;
-+
-+ /* Either we've calculated the number of frames to insert,
-+ * or we need to insert min duration frames
-+ */
-+ if (frames_to_insert > 0)
-+ inserted_frame_duration_in_us = last_render_time_in_us /
-+ frames_to_insert;
-+
-+ if (inserted_frame_duration_in_us <
-+ state->time.min_render_time_in_us)
-+
-+ inserted_frame_duration_in_us =
-+ state->time.min_render_time_in_us;
-+
-+ /* We need the v_total_min from capability */
-+ calc_vmin_vmax(core_freesync, stream, &vmin, &vmax);
-+
-+ inserted_frame_v_total = vmin;
-+ if (min_frame_duration_in_ns / 1000)
-+ inserted_frame_v_total = inserted_frame_duration_in_us *
-+ vmin / (min_frame_duration_in_ns / 1000);
-+
-+ /* Set length of inserted frames as v_total_max*/
-+ vmax = inserted_frame_v_total;
-+
-+ /* Program V_TOTAL */
-+ core_freesync->dc->stream_funcs.adjust_vmin_vmax(
-+ core_freesync->dc, &stream,
-+ 1, vmin,
-+ vmax);
-+
-+ /* Cache the calculated variables */
-+ state->btr.inserted_frame_duration_in_us =
-+ inserted_frame_duration_in_us;
-+ state->btr.frames_to_insert = frames_to_insert;
-+ state->btr.frame_counter = frames_to_insert;
-+
-+ }
-+}
-+
-+static void apply_fixed_refresh(struct core_freesync *core_freesync,
-+ const struct dc_stream *stream, unsigned int map_index)
-+{
-+ unsigned int vmin = 0, vmax = 0;
-+ struct freesync_state *state = &core_freesync->map[map_index].state;
-+
-+ if (!state->fixed_refresh.program_fixed_refresh)
-+ return;
-+
-+ state->fixed_refresh.program_fixed_refresh = false;
-+
-+ /* Program Fixed Refresh */
-+
-+ /* Fixed Refresh set to "not active" so disengage */
-+ if (!state->fixed_refresh.fixed_refresh_active) {
-+ set_freesync_on_streams(core_freesync, &stream, 1);
-+
-+ /* Fixed Refresh set to "active" so engage (fix to max) */
-+ } else {
-+
-+ calc_vmin_vmax(core_freesync, stream, &vmin, &vmax);
-+
-+ vmax = vmin;
-+
-+ core_freesync->dc->stream_funcs.adjust_vmin_vmax(
-+ core_freesync->dc, &stream,
-+ 1, vmin,
-+ vmax);
-+ }
-+}
-+
-+void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ unsigned int curr_time_stamp_in_us)
-+{
-+ unsigned int stream_index, map_index, last_render_time_in_us = 0;
-+ struct core_freesync *core_freesync =
-+ MOD_FREESYNC_TO_CORE(mod_freesync);
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+
-+ map_index = map_index_from_stream(core_freesync,
-+ streams[stream_index]);
-+
-+ if (core_freesync->map[map_index].caps->supported) {
-+
-+ last_render_time_in_us = curr_time_stamp_in_us -
-+ core_freesync->map[map_index].state.time.
-+ prev_time_stamp_in_us;
-+
-+ /* Add the timestamps to the cache and determine
-+ * whether BTR program is required
-+ */
-+ update_timestamps(core_freesync, streams[stream_index],
-+ map_index, last_render_time_in_us);
-+
-+ if (core_freesync->map[map_index].state.fullscreen &&
-+ core_freesync->map[map_index].user_enable.
-+ enable_for_gaming) {
-+
-+ if (core_freesync->map[map_index].caps->btr_supported) {
-+
-+ apply_below_the_range(core_freesync,
-+ streams[stream_index], map_index,
-+ last_render_time_in_us);
-+ } else {
-+ apply_fixed_refresh(core_freesync,
-+ streams[stream_index], map_index);
-+ }
-+ }
-+
-+ core_freesync->map[map_index].state.time.
-+ prev_time_stamp_in_us = curr_time_stamp_in_us;
-+ }
-+
-+ }
-+}
-diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h
-new file mode 100644
-index 0000000..e54fe2c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h
-@@ -0,0 +1,179 @@
-+/*
-+ * 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 MOD_COLOR_H_
-+#define MOD_COLOR_H_
-+
-+#include "dm_services.h"
-+
-+struct mod_color {
-+ int dummy;
-+};
-+
-+struct color_space_coordinates {
-+ unsigned int redX;
-+ unsigned int redY;
-+ unsigned int greenX;
-+ unsigned int greenY;
-+ unsigned int blueX;
-+ unsigned int blueY;
-+ unsigned int whiteX;
-+ unsigned int whiteY;
-+};
-+
-+struct gamut_space_coordinates {
-+ unsigned int redX;
-+ unsigned int redY;
-+ unsigned int greenX;
-+ unsigned int greenY;
-+ unsigned int blueX;
-+ unsigned int blueY;
-+};
-+
-+struct gamut_space_entry {
-+ unsigned int index;
-+ unsigned int redX;
-+ unsigned int redY;
-+ unsigned int greenX;
-+ unsigned int greenY;
-+ unsigned int blueX;
-+ unsigned int blueY;
-+
-+ int a0;
-+ int a1;
-+ int a2;
-+ int a3;
-+ int gamma;
-+};
-+
-+struct white_point_coodinates {
-+ unsigned int whiteX;
-+ unsigned int whiteY;
-+};
-+
-+struct white_point_coodinates_entry {
-+ unsigned int index;
-+ unsigned int whiteX;
-+ unsigned int whiteY;
-+};
-+
-+struct color_range {
-+ int current;
-+ int min;
-+ int max;
-+};
-+
-+struct mod_color *mod_color_create(struct dc *dc);
-+
-+void mod_color_destroy(struct mod_color *mod_color);
-+
-+bool mod_color_add_sink(struct mod_color *mod_color,
-+ const struct dc_sink *sink);
-+
-+bool mod_color_remove_sink(struct mod_color *mod_color,
-+ const struct dc_sink *sink);
-+
-+bool mod_color_update_gamut_to_stream(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams);
-+
-+bool mod_color_set_white_point(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct white_point_coodinates *white_point);
-+
-+bool mod_color_adjust_source_gamut(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct gamut_space_coordinates *input_gamut_coordinates,
-+ struct white_point_coodinates *input_white_point_coordinates);
-+
-+bool mod_color_adjust_destination_gamut(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ struct gamut_space_coordinates *input_gamut_coordinates,
-+ struct white_point_coodinates *input_white_point_coordinates);
-+
-+bool mod_color_get_user_enable(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ bool *user_enable);
-+
-+bool mod_color_set_user_enable(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ bool user_enable);
-+
-+bool mod_color_get_custom_color_temperature(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ int *color_temperature);
-+
-+bool mod_color_set_custom_color_temperature(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int color_temperature);
-+
-+bool mod_color_get_color_saturation(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_saturation);
-+
-+bool mod_color_get_color_contrast(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_contrast);
-+
-+bool mod_color_get_color_brightness(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_brightness);
-+
-+bool mod_color_get_color_hue(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_range *color_hue);
-+
-+bool mod_color_get_source_gamut(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ struct color_space_coordinates *source_gamut);
-+
-+bool mod_color_notify_mode_change(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams);
-+
-+bool mod_color_set_brightness(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int brightness_value);
-+
-+bool mod_color_set_contrast(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int contrast_value);
-+
-+bool mod_color_set_hue(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int hue_value);
-+
-+bool mod_color_set_saturation(struct mod_color *mod_color,
-+ const struct dc_stream **streams, int num_streams,
-+ int saturation_value);
-+
-+bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ enum dc_quantization_range quantization_range);
-+
-+bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color,
-+ const struct dc_sink *sink,
-+ enum dc_quantization_range *quantization_range);
-+
-+#endif /* MOD_COLOR_H_ */
-diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
-new file mode 100644
-index 0000000..7abfe34
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
-@@ -0,0 +1,149 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+
-+
-+
-+/*
-+ * 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 MOD_FREESYNC_H_
-+#define MOD_FREESYNC_H_
-+
-+#include "dm_services.h"
-+
-+struct mod_freesync *mod_freesync_create(struct dc *dc);
-+void mod_freesync_destroy(struct mod_freesync *mod_freesync);
-+
-+struct mod_freesync {
-+ int dummy;
-+};
-+
-+enum mod_freesync_state {
-+ FREESYNC_STATE_NONE,
-+ FREESYNC_STATE_FULLSCREEN,
-+ FREESYNC_STATE_STATIC_SCREEN,
-+ FREESYNC_STATE_VIDEO
-+};
-+
-+enum mod_freesync_user_enable_mask {
-+ FREESYNC_USER_ENABLE_STATIC = 0x1,
-+ FREESYNC_USER_ENABLE_VIDEO = 0x2,
-+ FREESYNC_USER_ENABLE_GAMING = 0x4
-+};
-+
-+struct mod_freesync_user_enable {
-+ bool enable_for_static;
-+ bool enable_for_video;
-+ bool enable_for_gaming;
-+};
-+
-+struct mod_freesync_caps {
-+ bool supported;
-+ unsigned int min_refresh_in_micro_hz;
-+ unsigned int max_refresh_in_micro_hz;
-+
-+ bool btr_supported;
-+};
-+
-+struct mod_freesync_params {
-+ enum mod_freesync_state state;
-+ bool enable;
-+ unsigned int update_duration_in_ns;
-+ bool windowed_fullscreen;
-+};
-+
-+/*
-+ * Add stream to be tracked by module
-+ */
-+bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream, struct mod_freesync_caps *caps);
-+
-+/*
-+ * Remove stream to be tracked by module
-+ */
-+bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream);
-+
-+/*
-+ * Build additional parameters for dc_stream when creating stream for
-+ * sink to support freesync
-+ */
-+void mod_freesync_update_stream(struct mod_freesync *mod_freesync,
-+ struct dc_stream *stream);
-+
-+/*
-+ * Update the freesync state flags for each display and program
-+ * freesync accordingly
-+ */
-+void mod_freesync_update_state(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ struct mod_freesync_params *freesync_params);
-+
-+bool mod_freesync_get_state(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream,
-+ struct mod_freesync_params *freesync_params);
-+
-+bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ struct mod_freesync_user_enable *user_enable);
-+
-+bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync,
-+ const struct dc_stream *stream,
-+ struct mod_freesync_user_enable *user_enable);
-+
-+void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams);
-+
-+void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams);
-+
-+void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
-+ const struct dc_stream **streams, int num_streams,
-+ unsigned int curr_time_stamp);
-+
-+#endif
-diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h
-new file mode 100644
-index 0000000..a204e8d
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h
-@@ -0,0 +1,112 @@
-+/*
-+ * 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 MODULES_INC_MOD_POWER_H_
-+#define MODULES_INC_MOD_POWER_H_
-+
-+#include "dm_services.h"
-+
-+struct mod_power {
-+ int dummy;
-+};
-+
-+/* VariBright related commands */
-+enum varibright_command {
-+ VariBright_Cmd__SetVBLevel = 0,
-+ VariBright_Cmd__UserEnable,
-+ VariBright_Cmd__PreDisplayConfigChange,
-+ VariBright_Cmd__PostDisplayConfigChange,
-+ VariBright_Cmd__SuspendABM,
-+ VariBright_Cmd__ResumeABM,
-+
-+ VariBright_Cmd__Unknown,
-+};
-+
-+/* VariBright settings structure */
-+struct varibright_info {
-+ enum varibright_command cmd;
-+
-+ unsigned int level;
-+ bool enable;
-+ bool activate;
-+};
-+
-+enum dmcu_block_psr_reason {
-+ /* This is a bitfield mask */
-+ dmcu_block_psr_reason_invalid = 0x0,
-+ dmcu_block_psr_reason_vsync_int = 0x1,
-+ dmcu_block_psr_reason_shared_primary = 0x2,
-+ dmcu_block_psr_reason_unsupported_link_rate = 0x4
-+};
-+
-+struct mod_power *mod_power_create(struct dc *dc);
-+
-+void mod_power_destroy(struct mod_power *mod_power);
-+
-+bool mod_power_add_sink(struct mod_power *mod_power,
-+ const struct dc_sink *sink);
-+
-+bool mod_power_remove_sink(struct mod_power *mod_power,
-+ const struct dc_sink *sink);
-+
-+bool mod_power_set_backlight(struct mod_power *mod_power,
-+ const struct dc_stream **streams, int num_streams,
-+ unsigned int backlight_8bit);
-+
-+bool mod_power_get_backlight(struct mod_power *mod_power,
-+ const struct dc_sink *sink,
-+ unsigned int *backlight_8bit);
-+
-+void mod_power_initialize_backlight_caps
-+ (struct mod_power *mod_power);
-+
-+unsigned int mod_power_backlight_level_percentage_to_signal
-+ (struct mod_power *mod_power, unsigned int percentage);
-+
-+unsigned int mod_power_backlight_level_signal_to_percentage
-+ (struct mod_power *mod_power, unsigned int signalLevel8bit);
-+
-+bool mod_power_get_panel_backlight_boundaries
-+ (struct mod_power *mod_power,
-+ unsigned int *min_backlight,
-+ unsigned int *max_backlight,
-+ unsigned int *output_ac_level_percentage,
-+ unsigned int *output_dc_level_percentage);
-+
-+bool mod_power_set_smooth_brightness(struct mod_power *mod_power,
-+ const struct dc_sink *sink, bool enable_brightness);
-+
-+bool mod_power_notify_mode_change(struct mod_power *mod_power,
-+ const struct dc_stream *stream);
-+
-+bool mod_power_varibright_control(struct mod_power *mod_power,
-+ struct varibright_info *input_varibright_info);
-+
-+bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason);
-+
-+bool mod_power_set_psr_enable(struct mod_power *mod_power,
-+ bool psr_enable);
-+
-+#endif /* MODULES_INC_MOD_POWER_H_ */
-diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c
-new file mode 100644
-index 0000000..ea07e84
---- /dev/null
-+++ b/drivers/gpu/drm/amd/display/modules/power/power.c
-@@ -0,0 +1,784 @@
-+/*
-+ * 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
-+ *
-+ */
-+
-+#include "mod_power.h"
-+#include "dm_services.h"
-+#include "dc.h"
-+#include "core_types.h"
-+#include "core_dc.h"
-+
-+#define MOD_POWER_MAX_CONCURRENT_SINKS 32
-+#define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500
-+
-+struct sink_caps {
-+ const struct dc_sink *sink;
-+};
-+
-+struct backlight_state {
-+ unsigned int backlight;
-+ unsigned int frame_ramp;
-+ bool smooth_brightness_enabled;
-+};
-+
-+struct core_power {
-+ struct mod_power public;
-+ struct dc *dc;
-+ int num_sinks;
-+ struct sink_caps *caps;
-+ struct backlight_state *state;
-+};
-+
-+union dmcu_abm_set_bl_params {
-+ struct {
-+ unsigned int gradual_change : 1; /* [0:0] */
-+ unsigned int reserved : 15; /* [15:1] */
-+ unsigned int frame_ramp : 16; /* [31:16] */
-+ } bits;
-+ unsigned int u32All;
-+};
-+
-+/* Backlight cached properties */
-+static unsigned int backlight_8bit_lut_array[101];
-+static unsigned int ac_level_percentage;
-+static unsigned int dc_level_percentage;
-+static bool backlight_caps_valid;
-+/* we use lazy initialization of backlight capabilities cache */
-+static bool backlight_caps_initialized;
-+/* AC/DC levels initialized later in separate context */
-+static bool backlight_def_levels_valid;
-+
-+/* ABM cached properties */
-+static unsigned int abm_level;
-+static bool abm_user_enable;
-+static bool abm_active;
-+
-+/*PSR cached properties*/
-+static unsigned int block_psr;
-+
-+/* Defines default backlight curve F(x) = A(x*x) + Bx + C.
-+ *
-+ * Backlight curve should always satisfy F(0) = min, F(100) = max,
-+ * so polynom 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
-+ */
-+static const unsigned int backlight_curve_coeff_a_factor = 10000;
-+static const unsigned int backlight_curve_coeff_b = 100;
-+static const unsigned int backlight_curve_coeff_b_factor = 100;
-+
-+/* Minimum and maximum backlight input signal levels */
-+static const unsigned int default_min_backlight = 12;
-+static const unsigned int default_max_backlight = 255;
-+
-+/* Other backlight constants */
-+static const unsigned int absolute_backlight_max = 255;
-+
-+#define MOD_POWER_TO_CORE(mod_power)\
-+ container_of(mod_power, struct core_power, public)
-+
-+static bool check_dc_support(const struct dc *dc)
-+{
-+ if (dc->stream_funcs.set_backlight == NULL)
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Given a specific dc_sink* this function finds its equivalent
-+ * on the dc_sink array and returns the corresponding index
-+ */
-+static unsigned int sink_index_from_sink(struct core_power *core_power,
-+ const struct dc_sink *sink)
-+{
-+ unsigned int index = 0;
-+
-+ for (index = 0; index < core_power->num_sinks; index++)
-+ if (core_power->caps[index].sink == sink)
-+ return index;
-+
-+ /* Could not find sink requested */
-+ ASSERT(false);
-+ return index;
-+}
-+
-+static unsigned int convertBL8to17(unsigned int backlight_8bit)
-+{
-+ unsigned int temp_ulong = backlight_8bit * 0x10101;
-+ unsigned char temp_uchar =
-+ (unsigned char)(((temp_ulong & 0x80) >> 7) & 1);
-+
-+ temp_ulong = (temp_ulong >> 8) + temp_uchar;
-+
-+ return temp_ulong;
-+}
-+
-+static uint16_t convertBL8to16(unsigned int backlight_8bit)
-+{
-+ return (uint16_t)((backlight_8bit * 0x10101) >> 8);
-+}
-+
-+/*This is used when OS wants to retrieve the current BL.
-+ * We return the 8bit value to OS.
-+ */
-+static unsigned int convertBL17to8(unsigned int backlight_17bit)
-+{
-+ if (backlight_17bit & 0x10000)
-+ return default_max_backlight;
-+ else
-+ return (backlight_17bit >> 8);
-+}
-+
-+struct mod_power *mod_power_create(struct dc *dc)
-+{
-+ struct core_power *core_power =
-+ dm_alloc(sizeof(struct core_power));
-+
-+ struct core_dc *core_dc = DC_TO_CORE(dc);
-+
-+ int i = 0;
-+
-+ if (core_power == NULL)
-+ goto fail_alloc_context;
-+
-+ core_power->caps = dm_alloc(sizeof(struct sink_caps) *
-+ MOD_POWER_MAX_CONCURRENT_SINKS);
-+
-+ if (core_power->caps == NULL)
-+ goto fail_alloc_caps;
-+
-+ for (i = 0; i < MOD_POWER_MAX_CONCURRENT_SINKS; i++)
-+ core_power->caps[i].sink = NULL;
-+
-+ core_power->state = dm_alloc(sizeof(struct backlight_state) *
-+ MOD_POWER_MAX_CONCURRENT_SINKS);
-+
-+ if (core_power->state == NULL)
-+ goto fail_alloc_state;
-+
-+ core_power->num_sinks = 0;
-+ backlight_caps_valid = false;
-+
-+ if (dc == NULL)
-+ goto fail_construct;
-+
-+ core_power->dc = dc;
-+
-+ if (!check_dc_support(dc))
-+ goto fail_construct;
-+
-+ abm_user_enable = false;
-+ abm_active = false;
-+
-+ return &core_power->public;
-+
-+fail_construct:
-+ dm_free(core_power->state);
-+
-+fail_alloc_state:
-+ dm_free(core_power->caps);
-+
-+fail_alloc_caps:
-+ dm_free(core_power);
-+
-+fail_alloc_context:
-+ return NULL;
-+}
-+
-+
-+void mod_power_destroy(struct mod_power *mod_power)
-+{
-+ if (mod_power != NULL) {
-+ int i;
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ dm_free(core_power->state);
-+
-+ for (i = 0; i < core_power->num_sinks; i++)
-+ dc_sink_release(core_power->caps[i].sink);
-+
-+ dm_free(core_power->caps);
-+
-+ dm_free(core_power);
-+ }
-+}
-+
-+bool mod_power_add_sink(struct mod_power *mod_power,
-+ const struct dc_sink *sink)
-+{
-+ if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
-+ return false;
-+
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ struct core_dc *core_dc = DC_TO_CORE(core_power->dc);
-+
-+ if (core_power->num_sinks < MOD_POWER_MAX_CONCURRENT_SINKS) {
-+ dc_sink_retain(sink);
-+ core_power->caps[core_power->num_sinks].sink = sink;
-+ core_power->state[core_power->num_sinks].
-+ smooth_brightness_enabled = false;
-+ core_power->state[core_power->num_sinks].
-+ backlight = 100;
-+ core_power->num_sinks++;
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+bool mod_power_remove_sink(struct mod_power *mod_power,
-+ const struct dc_sink *sink)
-+{
-+ int i = 0, j = 0;
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ for (i = 0; i < core_power->num_sinks; i++) {
-+ if (core_power->caps[i].sink == sink) {
-+ /* To remove this sink, shift everything after down */
-+ for (j = i; j < core_power->num_sinks - 1; j++) {
-+ core_power->caps[j].sink =
-+ core_power->caps[j + 1].sink;
-+
-+ memcpy(&core_power->state[j],
-+ &core_power->state[j + 1],
-+ sizeof(struct backlight_state));
-+ }
-+ core_power->num_sinks--;
-+ dc_sink_release(sink);
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+bool mod_power_set_backlight(struct mod_power *mod_power,
-+ const struct dc_stream **streams, int num_streams,
-+ unsigned int backlight_8bit)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ unsigned int frame_ramp = 0;
-+
-+ unsigned int stream_index, sink_index, vsync_rate_hz;
-+
-+ union dmcu_abm_set_bl_params params;
-+
-+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
-+ if (streams[stream_index]->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) {
-+ core_power->state[sink_index].backlight = 0;
-+ core_power->state[sink_index].frame_ramp = 0;
-+ core_power->state[sink_index].smooth_brightness_enabled = false;
-+ continue;
-+ }
-+
-+ sink_index = sink_index_from_sink(core_power,
-+ streams[stream_index]->sink);
-+
-+ vsync_rate_hz = div64_u64(div64_u64((streams[stream_index]->
-+ timing.pix_clk_khz * 1000),
-+ streams[stream_index]->timing.v_total),
-+ streams[stream_index]->timing.h_total);
-+
-+ core_power->state[sink_index].backlight = backlight_8bit;
-+
-+ if (core_power->state[sink_index].smooth_brightness_enabled)
-+ frame_ramp = ((vsync_rate_hz *
-+ SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS) + 500)
-+ / 1000;
-+ else
-+ frame_ramp = 0;
-+
-+ core_power->state[sink_index].frame_ramp = frame_ramp;
-+ }
-+
-+ params.u32All = 0;
-+ params.bits.gradual_change = (frame_ramp > 0);
-+ params.bits.frame_ramp = frame_ramp;
-+
-+ core_power->dc->stream_funcs.set_backlight
-+ (core_power->dc, backlight_8bit, params.u32All, streams[0]);
-+
-+ return true;
-+}
-+
-+bool mod_power_get_backlight(struct mod_power *mod_power,
-+ const struct dc_sink *sink,
-+ unsigned int *backlight_8bit)
-+{
-+ if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
-+ return false;
-+
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_power, sink);
-+
-+ *backlight_8bit = core_power->state[sink_index].backlight;
-+
-+ return true;
-+}
-+
-+/* hard coded to default backlight curve. */
-+void mod_power_initialize_backlight_caps(struct mod_power
-+ *mod_power)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ struct core_dc *core_dc = DC_TO_CORE(core_power->dc);
-+ unsigned int i;
-+
-+ backlight_caps_initialized = true;
-+
-+ struct dm_acpi_atif_backlight_caps *pExtCaps = NULL;
-+ bool customCurvePresent = false;
-+ bool customMinMaxPresent = false;
-+ bool customDefLevelsPresent = false;
-+
-+ /* Allocate memory for ATIF output
-+ * (do not want to use 256 bytes on the stack)
-+ */
-+ pExtCaps = (struct dm_acpi_atif_backlight_caps *)
-+ (dm_alloc(sizeof(struct dm_acpi_atif_backlight_caps)));
-+ if (pExtCaps == NULL)
-+ return;
-+
-+ /* Retrieve ACPI extended brightness caps */
-+ if (dm_query_extended_brightness_caps
-+ (core_dc->ctx, AcpiDisplayType_LCD1, pExtCaps)) {
-+ ac_level_percentage = pExtCaps->acLevelPercentage;
-+ dc_level_percentage = pExtCaps->dcLevelPercentage;
-+ customMinMaxPresent = true;
-+ customDefLevelsPresent = true;
-+ customCurvePresent = (pExtCaps->numOfDataPoints > 0);
-+
-+ ASSERT(pExtCaps->numOfDataPoints <= 99);
-+ } else {
-+ dm_free(pExtCaps);
-+ return;
-+ }
-+
-+ if (customMinMaxPresent)
-+ backlight_8bit_lut_array[0] = pExtCaps->minInputSignal;
-+ else
-+ backlight_8bit_lut_array[0] = default_min_backlight;
-+
-+ if (customMinMaxPresent)
-+ backlight_8bit_lut_array[100] = pExtCaps->maxInputSignal;
-+ else
-+ backlight_8bit_lut_array[100] = default_max_backlight;
-+
-+ ASSERT(backlight_8bit_lut_array[100] <= absolute_backlight_max);
-+ ASSERT(backlight_8bit_lut_array[0] <=
-+ backlight_8bit_lut_array[100]);
-+
-+ /* Just to make sure we use valid values */
-+ if (backlight_8bit_lut_array[100] > absolute_backlight_max)
-+ backlight_8bit_lut_array[100] = absolute_backlight_max;
-+ if (backlight_8bit_lut_array[0] > backlight_8bit_lut_array[100]) {
-+ unsigned int swap;
-+
-+ swap = backlight_8bit_lut_array[0];
-+ backlight_8bit_lut_array[0] = backlight_8bit_lut_array[100];
-+ backlight_8bit_lut_array[100] = swap;
-+ }
-+
-+ /* Build backlight translation table for custom curve */
-+ if (customCurvePresent) {
-+ unsigned int index = 1;
-+ unsigned int numOfDataPoints =
-+ (pExtCaps->numOfDataPoints <= 99 ?
-+ pExtCaps->numOfDataPoints : 99);
-+
-+ /* Filling translation table from data points -
-+ * between every two provided data points we
-+ * lineary interpolate missing values
-+ */
-+ for (i = 0; i < numOfDataPoints; i++) {
-+ /* Clamp signal level between min and max
-+ * (since min and max might come other
-+ * soruce like registry)
-+ */
-+ unsigned int luminance =
-+ pExtCaps->dataPoints[i].luminance;
-+ unsigned int signalLevel =
-+ pExtCaps->dataPoints[i].signalLevel;
-+
-+ if (signalLevel < backlight_8bit_lut_array[0])
-+ signalLevel = backlight_8bit_lut_array[0];
-+ if (signalLevel > backlight_8bit_lut_array[100])
-+ signalLevel = backlight_8bit_lut_array[100];
-+
-+ /* Lineary interpolate missing values */
-+ if (index < luminance) {
-+ unsigned int baseValue =
-+ backlight_8bit_lut_array[index-1];
-+ unsigned int deltaSignal =
-+ signalLevel - baseValue;
-+ unsigned int deltaLuma =
-+ luminance - index + 1;
-+ unsigned int step = deltaSignal;
-+
-+ for (; index < luminance; index++) {
-+ backlight_8bit_lut_array[index] =
-+ baseValue + (step / deltaLuma);
-+ step += deltaSignal;
-+ }
-+ }
-+
-+ /* Now [index == luminance],
-+ * so we can add data point to the translation table
-+ */
-+ backlight_8bit_lut_array[index++] = signalLevel;
-+ }
-+
-+ /* Complete the final segment of interpolation -
-+ * between last datapoint and maximum value
-+ */
-+ if (index < 100) {
-+ unsigned int baseValue =
-+ backlight_8bit_lut_array[index-1];
-+ unsigned int deltaSignal =
-+ backlight_8bit_lut_array[100] -
-+ baseValue;
-+ unsigned int deltaLuma = 100 - index + 1;
-+ unsigned int step = deltaSignal;
-+
-+ for (; index < 100; index++) {
-+ backlight_8bit_lut_array[index] =
-+ baseValue + (step / deltaLuma);
-+ step += deltaSignal;
-+ }
-+ }
-+ /* Build backlight translation table based on default curve */
-+ } else {
-+ unsigned int delta =
-+ backlight_8bit_lut_array[100] -
-+ backlight_8bit_lut_array[0];
-+ unsigned int coeffC = backlight_8bit_lut_array[0];
-+ unsigned int coeffB =
-+ (backlight_curve_coeff_b < delta ?
-+ backlight_curve_coeff_b : delta);
-+ unsigned int coeffA = delta - coeffB; /* coeffB is B*100 */
-+
-+ for (i = 1; i < 100; i++) {
-+ backlight_8bit_lut_array[i] =
-+ (coeffA * i * i) /
-+ backlight_curve_coeff_a_factor +
-+ (coeffB * i) /
-+ backlight_curve_coeff_b_factor +
-+ coeffC;
-+ }
-+ }
-+
-+ if (pExtCaps != NULL)
-+ dm_free(pExtCaps);
-+
-+ /* Successfully initialized */
-+ backlight_caps_valid = true;
-+ backlight_def_levels_valid = customDefLevelsPresent;
-+}
-+
-+unsigned int mod_power_backlight_level_percentage_to_signal(
-+ struct mod_power *mod_power, unsigned int percentage)
-+{
-+ /* Do lazy initialization of backlight capabilities*/
-+ if (!backlight_caps_initialized)
-+ mod_power_initialize_backlight_caps(mod_power);
-+
-+ /* Since the translation table is indexed by percentage,
-+ * we simply return backlight value at given percent
-+ */
-+ if (backlight_caps_valid && percentage <= 100)
-+ return backlight_8bit_lut_array[percentage];
-+
-+ return -1;
-+}
-+
-+unsigned int mod_power_backlight_level_signal_to_percentage(
-+ struct mod_power *mod_power,
-+ unsigned int signalLevel8bit)
-+{
-+ unsigned int invalid_backlight = (unsigned int)(-1);
-+ /* Do lazy initialization of backlight capabilities */
-+ if (!backlight_caps_initialized)
-+ mod_power_initialize_backlight_caps(mod_power);
-+
-+ /* If customer curve cannot convert to differentiated value near min
-+ * it is important to report 0 for min signal to pass setting "Dimmed"
-+ * setting in HCK brightness2 tests.
-+ */
-+ if (signalLevel8bit <= backlight_8bit_lut_array[0])
-+ return 0;
-+
-+ /* Since the translation table is indexed by percentage
-+ * we need to do a binary search over the array
-+ * Another option would be to guess entry based on linear distribution
-+ * and then do linear search in correct direction
-+ */
-+ if (backlight_caps_valid && signalLevel8bit <=
-+ absolute_backlight_max) {
-+ unsigned int min = 0;
-+ unsigned int max = 100;
-+ unsigned int mid = invalid_backlight;
-+
-+ while (max >= min) {
-+ mid = (min + max) / 2; /* floor of half range */
-+
-+ if (backlight_8bit_lut_array[mid] < signalLevel8bit)
-+ min = mid + 1;
-+ else if (backlight_8bit_lut_array[mid] >
-+ signalLevel8bit)
-+ max = mid - 1;
-+ else
-+ break;
-+
-+ if (max == 0 || max == 1)
-+ return invalid_backlight;
-+ }
-+ return mid;
-+ }
-+
-+ return invalid_backlight;
-+}
-+
-+
-+bool mod_power_get_panel_backlight_boundaries(
-+ struct mod_power *mod_power,
-+ unsigned int *min_backlight,
-+ unsigned int *max_backlight,
-+ unsigned int *output_ac_level_percentage,
-+ unsigned int *output_dc_level_percentage)
-+{
-+ /* Do lazy initialization of backlight capabilities */
-+ if (!backlight_caps_initialized)
-+ mod_power_initialize_backlight_caps(mod_power);
-+
-+ /* If cache was successfully updated,
-+ * copy the values to output structure and return success
-+ */
-+ if (backlight_caps_valid) {
-+ *min_backlight = backlight_8bit_lut_array[0];
-+ *max_backlight = backlight_8bit_lut_array[100];
-+
-+ *output_ac_level_percentage = ac_level_percentage;
-+ *output_dc_level_percentage = dc_level_percentage;
-+
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+bool mod_power_set_smooth_brightness(struct mod_power *mod_power,
-+ const struct dc_sink *sink, bool enable_brightness)
-+{
-+ if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
-+ return false;
-+
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ unsigned int sink_index = sink_index_from_sink(core_power, sink);
-+
-+ core_power->state[sink_index].smooth_brightness_enabled
-+ = enable_brightness;
-+ return true;
-+}
-+
-+bool mod_power_notify_mode_change(struct mod_power *mod_power,
-+ const struct dc_stream *stream)
-+{
-+ if (stream->sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
-+ return false;
-+
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ unsigned int sink_index = sink_index_from_sink(core_power,
-+ stream->sink);
-+ unsigned int frame_ramp = core_power->state[sink_index].frame_ramp;
-+ union dmcu_abm_set_bl_params params;
-+
-+ params.u32All = 0;
-+ params.bits.gradual_change = (frame_ramp > 0);
-+ params.bits.frame_ramp = frame_ramp;
-+
-+ core_power->dc->stream_funcs.set_backlight
-+ (core_power->dc,
-+ core_power->state[sink_index].backlight,
-+ params.u32All, stream);
-+
-+ core_power->dc->stream_funcs.setup_psr
-+ (core_power->dc, stream);
-+
-+ return true;
-+}
-+
-+
-+static bool mod_power_abm_feature_enable(struct mod_power
-+ *mod_power, bool enable)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ if (abm_user_enable == enable)
-+ return true;
-+
-+ abm_user_enable = enable;
-+
-+ if (enable) {
-+ if (abm_level != 0 && abm_active)
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, abm_level);
-+ } else {
-+ if (abm_level != 0 && abm_active) {
-+ abm_level = 0;
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, abm_level);
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+static bool mod_power_abm_activate(struct mod_power
-+ *mod_power, bool activate)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ if (abm_active == activate)
-+ return true;
-+
-+ abm_active = activate;
-+
-+ if (activate) {
-+ if (abm_level != 0 && abm_user_enable)
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, abm_level);
-+ } else {
-+ if (abm_level != 0 && abm_user_enable) {
-+ abm_level = 0;
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, abm_level);
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+static bool mod_power_abm_set_level(struct mod_power *mod_power,
-+ unsigned int level)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+ if (abm_level == level)
-+ return true;
-+
-+ if (abm_active && abm_user_enable && level == 0)
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, 0);
-+ else if (abm_active && abm_user_enable && level != 0)
-+ core_power->dc->stream_funcs.set_abm_level
-+ (core_power->dc, level);
-+
-+ abm_level = level;
-+
-+ return true;
-+}
-+
-+bool mod_power_varibright_control(struct mod_power *mod_power,
-+ struct varibright_info *input_varibright_info)
-+{
-+ switch (input_varibright_info->cmd) {
-+ case VariBright_Cmd__SetVBLevel:
-+ {
-+ /* Set VariBright user level. */
-+ mod_power_abm_set_level(mod_power,
-+ input_varibright_info->level);
-+ }
-+ break;
-+
-+ case VariBright_Cmd__UserEnable:
-+ {
-+ /* Set VariBright user enable state. */
-+ mod_power_abm_feature_enable(mod_power,
-+ input_varibright_info->enable);
-+ }
-+ break;
-+
-+ case VariBright_Cmd__PostDisplayConfigChange:
-+ {
-+ /* Set VariBright user level. */
-+ mod_power_abm_set_level(mod_power,
-+ input_varibright_info->level);
-+
-+ /* Set VariBright user enable state. */
-+ mod_power_abm_feature_enable(mod_power,
-+ input_varibright_info->enable);
-+
-+ /* Set VariBright activate based on power state. */
-+ mod_power_abm_activate(mod_power,
-+ input_varibright_info->activate);
-+ }
-+ break;
-+
-+ default:
-+ {
-+ return false;
-+ }
-+ break;
-+ }
-+
-+ return true;
-+}
-+
-+bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason)
-+{
-+ if (block_enable)
-+ block_psr |= reason;
-+ else
-+ block_psr &= ~reason;
-+
-+ return true;
-+}
-+
-+
-+bool mod_power_set_psr_enable(struct mod_power *mod_power,
-+ bool psr_enable)
-+{
-+ struct core_power *core_power =
-+ MOD_POWER_TO_CORE(mod_power);
-+
-+ if (block_psr == 0)
-+ return core_power->dc->stream_funcs.set_psr_enable
-+ (core_power->dc, psr_enable);
-+
-+ return false;
-+}
-+
-+
-diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
-index bb5cc15..69aeec3 100644
---- a/drivers/gpu/drm/drm_atomic.c
-+++ b/drivers/gpu/drm/drm_atomic.c
-@@ -1152,7 +1152,7 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
- * RETURNS:
- * Zero on success, error code on failure
- */
--static int drm_atomic_connector_set_property(struct drm_connector *connector,
-+int drm_atomic_connector_set_property(struct drm_connector *connector,
- struct drm_connector_state *state, struct drm_property *property,
- uint64_t val)
- {
-@@ -1219,6 +1219,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
-
- return 0;
- }
-+EXPORT_SYMBOL(drm_atomic_connector_set_property);
-
- static void drm_atomic_connector_print_state(struct drm_printer *p,
- const struct drm_connector_state *state)
-@@ -1598,6 +1599,38 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
- EXPORT_SYMBOL(drm_atomic_add_affected_planes);
-
- /**
-+ * drm_atomic_legacy_backoff - locking backoff for legacy ioctls
-+ * @state: atomic state
-+ *
-+ * This function should be used by legacy entry points which don't understand
-+ * -EDEADLK semantics. For simplicity this one will grab all modeset locks after
-+ * the slowpath completed.
-+ */
-+void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
-+{
-+ struct drm_device *dev = state->dev;
-+ int ret;
-+ bool global = false;
-+
-+ if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
-+ global = true;
-+
-+ dev->mode_config.acquire_ctx = NULL;
-+ }
-+
-+retry:
-+ drm_modeset_backoff(state->acquire_ctx);
-+
-+ ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx);
-+ if (ret)
-+ goto retry;
-+
-+ if (global)
-+ dev->mode_config.acquire_ctx = state->acquire_ctx;
-+}
-+EXPORT_SYMBOL(drm_atomic_legacy_backoff);
-+
-+/**
- * drm_atomic_check_only - check whether a given config would work
- * @state: atomic configuration to check
- *
-diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
-index 1f08d59..decb9f8f 100644
---- a/drivers/gpu/drm/drm_atomic_helper.c
-+++ b/drivers/gpu/drm/drm_atomic_helper.c
-@@ -2968,6 +2968,116 @@ int drm_atomic_helper_resume(struct drm_device *dev,
- }
- EXPORT_SYMBOL(drm_atomic_helper_resume);
-
-+/**
-+ * drm_atomic_helper_crtc_set_property - helper for crtc properties
-+ * @crtc: DRM crtc
-+ * @property: DRM property
-+ * @val: value of property
-+ *
-+ * Provides a default crtc set_property handler using the atomic driver
-+ * interface.
-+ *
-+ * RETURNS:
-+ * Zero on success, error code on failure
-+ */
-+int
-+drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
-+ struct drm_property *property,
-+ uint64_t val)
-+{
-+ struct drm_atomic_state *state;
-+ struct drm_crtc_state *crtc_state;
-+ int ret = 0;
-+
-+ state = drm_atomic_state_alloc(crtc->dev);
-+ if (!state)
-+ return -ENOMEM;
-+
-+ /* ->set_property is always called with all locks held. */
-+ state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
-+retry:
-+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
-+ if (IS_ERR(crtc_state)) {
-+ ret = PTR_ERR(crtc_state);
-+ goto fail;
-+ }
-+
-+ ret = drm_atomic_crtc_set_property(crtc, crtc_state,
-+ property, val);
-+ if (ret)
-+ goto fail;
-+
-+ ret = drm_atomic_commit(state);
-+fail:
-+ if (ret == -EDEADLK)
-+ goto backoff;
-+
-+ drm_atomic_state_put(state);
-+ return ret;
-+
-+backoff:
-+ drm_atomic_state_clear(state);
-+ drm_atomic_legacy_backoff(state);
-+
-+ goto retry;
-+}
-+EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
-+
-+/**
-+ * drm_atomic_helper_connector_set_property - helper for connector properties
-+ * @connector: DRM connector
-+ * @property: DRM property
-+ * @val: value of property
-+ *
-+ * Provides a default connector set_property handler using the atomic driver
-+ * interface.
-+ *
-+ * RETURNS:
-+ * Zero on success, error code on failure
-+ */
-+int
-+drm_atomic_helper_connector_set_property(struct drm_connector *connector,
-+ struct drm_property *property,
-+ uint64_t val)
-+{
-+ struct drm_atomic_state *state;
-+ struct drm_connector_state *connector_state;
-+ int ret = 0;
-+
-+ state = drm_atomic_state_alloc(connector->dev);
-+ if (!state)
-+ return -ENOMEM;
-+
-+ /* ->set_property is always called with all locks held. */
-+ state->acquire_ctx = connector->dev->mode_config.acquire_ctx;
-+retry:
-+ connector_state = drm_atomic_get_connector_state(state, connector);
-+ if (IS_ERR(connector_state)) {
-+ ret = PTR_ERR(connector_state);
-+ goto fail;
-+ }
-+
-+ ret = drm_atomic_connector_set_property(connector, connector_state,
-+ property, val);
-+ if (ret)
-+ goto fail;
-+
-+ ret = drm_atomic_commit(state);
-+fail:
-+ if (ret == -EDEADLK)
-+ goto backoff;
-+
-+ drm_atomic_state_put(state);
-+ return ret;
-+
-+backoff:
-+ drm_atomic_state_clear(state);
-+ drm_atomic_legacy_backoff(state);
-+
-+ goto retry;
-+}
-+EXPORT_SYMBOL(drm_atomic_helper_connector_set_property);
-+
- static int page_flip_common(struct drm_atomic_state *state,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
-@@ -3103,6 +3213,85 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc,
- EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-
- /**
-+ * drm_atomic_helper_connector_dpms() - connector dpms helper implementation
-+ * @connector: affected connector
-+ * @mode: DPMS mode
-+ *
-+ * This is the main helper function provided by the atomic helper framework for
-+ * implementing the legacy DPMS connector interface. It computes the new desired
-+ * &drm_crtc_state.active state for the corresponding CRTC (if the connector is
-+ * enabled) and updates it.
-+ *
-+ * Returns:
-+ * Returns 0 on success, negative errno numbers on failure.
-+ */
-+int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
-+ int mode)
-+{
-+ struct drm_mode_config *config = &connector->dev->mode_config;
-+ struct drm_atomic_state *state;
-+ struct drm_crtc_state *crtc_state;
-+ struct drm_crtc *crtc;
-+ struct drm_connector *tmp_connector;
-+ struct drm_connector_list_iter conn_iter;
-+ int ret;
-+ bool active = false;
-+ int old_mode = connector->dpms;
-+
-+ if (mode != DRM_MODE_DPMS_ON)
-+ mode = DRM_MODE_DPMS_OFF;
-+
-+ connector->dpms = mode;
-+ crtc = connector->state->crtc;
-+
-+ if (!crtc)
-+ return 0;
-+
-+ state = drm_atomic_state_alloc(connector->dev);
-+ if (!state)
-+ return -ENOMEM;
-+
-+ state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
-+retry:
-+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
-+ if (IS_ERR(crtc_state)) {
-+ ret = PTR_ERR(crtc_state);
-+ goto fail;
-+ }
-+
-+ WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
-+
-+ drm_connector_list_iter_begin(connector->dev, &conn_iter);
-+ drm_for_each_connector_iter(tmp_connector, &conn_iter) {
-+ if (tmp_connector->state->crtc != crtc)
-+ continue;
-+
-+ if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
-+ active = true;
-+ break;
-+ }
-+ }
-+ drm_connector_list_iter_end(&conn_iter);
-+ crtc_state->active = active;
-+
-+ ret = drm_atomic_commit(state);
-+fail:
-+ if (ret == -EDEADLK)
-+ goto backoff;
-+ if (ret != 0)
-+ connector->dpms = old_mode;
-+ drm_atomic_state_put(state);
-+ return ret;
-+
-+backoff:
-+ drm_atomic_state_clear(state);
-+ drm_atomic_legacy_backoff(state);
-+
-+ goto retry;
-+}
-+EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
-+
-+/**
- * drm_atomic_helper_best_encoder - Helper for
- * &drm_connector_helper_funcs.best_encoder callback
- * @connector: Connector control structure
-diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
-index 56b9f9b..5f5324a 100644
---- a/drivers/gpu/drm/drm_modeset_lock.c
-+++ b/drivers/gpu/drm/drm_modeset_lock.c
-@@ -154,6 +154,27 @@ void drm_modeset_unlock_all(struct drm_device *dev)
- EXPORT_SYMBOL(drm_modeset_unlock_all);
-
- /**
-+ * drm_modeset_legacy_acquire_ctx - find acquire ctx for legacy ioctls
-+ * crtc: drm crtc
-+ *
-+ * Legacy ioctl operations like cursor updates or page flips only have per-crtc
-+ * locking, and store the acquire ctx in the corresponding crtc. All other
-+ * legacy operations take all locks and use a global acquire context. This
-+ * function grabs the right one.
-+ */
-+struct drm_modeset_acquire_ctx *
-+drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc)
-+{
-+ if (crtc->acquire_ctx)
-+ return crtc->acquire_ctx;
-+
-+ WARN_ON(!crtc->dev->mode_config.acquire_ctx);
-+
-+ return crtc->dev->mode_config.acquire_ctx;
-+}
-+EXPORT_SYMBOL(drm_modeset_legacy_acquire_ctx);
-+
-+/**
- * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
- * @dev: device
- *
-diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
-index 8a5808e..7c0f63c 100644
---- a/include/drm/drm_atomic.h
-+++ b/include/drm/drm_atomic.h
-@@ -318,6 +318,9 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
- struct drm_connector_state * __must_check
- drm_atomic_get_connector_state(struct drm_atomic_state *state,
- struct drm_connector *connector);
-+int drm_atomic_connector_set_property(struct drm_connector *connector,
-+ struct drm_connector_state *state, struct drm_property *property,
-+ uint64_t val);
-
- void drm_atomic_private_obj_init(struct drm_private_obj *obj,
- struct drm_private_state *state,
-@@ -545,6 +548,8 @@ int __must_check
- drm_atomic_add_affected_planes(struct drm_atomic_state *state,
- struct drm_crtc *crtc);
-
-+void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
-+
- void
- drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
-
-diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
-index d2b56cc..f3743d9 100644
---- a/include/drm/drm_atomic_helper.h
-+++ b/include/drm/drm_atomic_helper.h
-@@ -124,6 +124,12 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
- int drm_atomic_helper_resume(struct drm_device *dev,
- struct drm_atomic_state *state);
-
-+int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
-+ struct drm_property *property,
-+ uint64_t val);
-+int drm_atomic_helper_connector_set_property(struct drm_connector *connector,
-+ struct drm_property *property,
-+ uint64_t val);
- int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event,
-@@ -136,6 +142,8 @@ int drm_atomic_helper_page_flip_target(
- uint32_t flags,
- uint32_t target,
- struct drm_modeset_acquire_ctx *ctx);
-+int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
-+ int mode);
- struct drm_encoder *
- drm_atomic_helper_best_encoder(struct drm_connector *connector);
-
-diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
-index 1a64202..fa7732d 100644
---- a/include/drm/drm_crtc.h
-+++ b/include/drm/drm_crtc.h
-@@ -66,6 +66,18 @@ static inline uint64_t I642U64(int64_t val)
- return (uint64_t)*((uint64_t *)&val);
- }
-
-+/*
-+ * Rotation property bits. DRM_ROTATE_<degrees> rotates the image by the
-+ * specified amount in degrees in counter clockwise direction. DRM_REFLECT_X and
-+ * DRM_REFLECT_Y reflects the image along the specified axis prior to rotation
-+ */
-+#define DRM_ROTATE_0 BIT(0)
-+#define DRM_ROTATE_90 BIT(1)
-+#define DRM_ROTATE_180 BIT(2)
-+#define DRM_ROTATE_270 BIT(3)
-+#define DRM_ROTATE_MASK (DRM_ROTATE_0 | DRM_ROTATE_90 | \
-+ DRM_ROTATE_180 | DRM_ROTATE_270)
-+
- struct drm_crtc;
- struct drm_pending_vblank_event;
- struct drm_plane;
-@@ -733,6 +745,7 @@ struct drm_crtc_funcs {
- * allows the CRTC to be controlled.
- */
- struct drm_crtc {
-+ struct drm_modeset_acquire_ctx *acquire_ctx;
- struct drm_device *dev;
- struct device_node *port;
- struct list_head head;
-diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
-index 4b27c2b..2bb065b 100644
---- a/include/drm/drm_modeset_lock.h
-+++ b/include/drm/drm_modeset_lock.h
-@@ -122,6 +122,8 @@ struct drm_plane;
- void drm_modeset_lock_all(struct drm_device *dev);
- void drm_modeset_unlock_all(struct drm_device *dev);
- void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
-+struct drm_modeset_acquire_ctx *
-+drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
-
- int drm_modeset_lock_all_ctx(struct drm_device *dev,
- struct drm_modeset_acquire_ctx *ctx);
-diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
-index 7b8fa11..30a0693 100644
---- a/include/uapi/drm/amdgpu_drm.h
-+++ b/include/uapi/drm/amdgpu_drm.h
-@@ -53,6 +53,9 @@ extern "C" {
- #define DRM_AMDGPU_WAIT_FENCES 0x12
- #define DRM_AMDGPU_VM 0x13
-
-+/* hybrid specific ioctls */
-+#define DRM_AMDGPU_FREESYNC 0x5d
-+
- #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
- #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
- #define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx)
-@@ -68,6 +71,9 @@ extern "C" {
- #define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
- #define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm)
-
-+/* hybrid specific ioctls */
-+#define DRM_IOCTL_AMDGPU_FREESYNC DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FREESYNC, struct drm_amdgpu_freesync)
-+
- #define AMDGPU_GEM_DOMAIN_CPU 0x1
- #define AMDGPU_GEM_DOMAIN_GTT 0x2
- #define AMDGPU_GEM_DOMAIN_VRAM 0x4
-@@ -875,6 +881,19 @@ struct drm_amdgpu_info_vce_clock_table {
- #define AMDGPU_FAMILY_AI 141 /* Vega10 */
- #define AMDGPU_FAMILY_RV 142 /* Raven */
-
-+/*
-+ * Definition of free sync enter and exit signals
-+ * We may have more options in the future
-+ */
-+#define AMDGPU_FREESYNC_FULLSCREEN_ENTER 1
-+#define AMDGPU_FREESYNC_FULLSCREEN_EXIT 2
-+
-+struct drm_amdgpu_freesync {
-+ __u32 op; /* AMDGPU_FREESYNC_FULLSCREEN_ENTER or */
-+ /* AMDGPU_FREESYNC_FULLSCREEN_ENTER */
-+ __u32 spare[7];
-+};
-+
- #if defined(__cplusplus)
- }
- #endif
---
-2.7.4
-