diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0510-drm-amd-dal-Add-dal-display-driver.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0510-drm-amd-dal-Add-dal-display-driver.patch | 90113 |
1 files changed, 0 insertions, 90113 deletions
diff --git a/common/recipes-kernel/linux/files/0510-drm-amd-dal-Add-dal-display-driver.patch b/common/recipes-kernel/linux/files/0510-drm-amd-dal-Add-dal-display-driver.patch deleted file mode 100644 index 1606a1aa..00000000 --- a/common/recipes-kernel/linux/files/0510-drm-amd-dal-Add-dal-display-driver.patch +++ /dev/null @@ -1,90113 +0,0 @@ -From 35eea4f1b20ded08fc0d65891163d03238e3adf6 Mon Sep 17 00:00:00 2001 -From: Harry Wentland <harry.wentland@amd.com> -Date: Wed, 25 Nov 2015 14:45:50 -0500 -Subject: [PATCH 0510/1110] drm/amd/dal: Add dal display driver - -Signed-off-by: Harry Wentland <harry.wentland@amd.com> -Acked-by: Alex Deucher <alexander.deucher@amd.com> ---- - drivers/gpu/drm/amd/dal/Kconfig | 39 + - drivers/gpu/drm/amd/dal/Makefile | 19 + - .../gpu/drm/amd/dal/dal_power_interface_types.h | 76 + - drivers/gpu/drm/amd/dal/dal_services.h | 266 ++ - drivers/gpu/drm/amd/dal/dal_services_types.h | 62 + - drivers/gpu/drm/amd/dal/dc/Makefile | 24 + - drivers/gpu/drm/amd/dal/dc/adapter/Makefile | 18 + - .../gpu/drm/amd/dal/dc/adapter/adapter_service.c | 2037 +++++++++ - .../gpu/drm/amd/dal/dc/adapter/adapter_service.h | 67 + - .../adapter/dce110/hw_ctx_adapter_service_dce110.c | 303 ++ - .../adapter/dce110/hw_ctx_adapter_service_dce110.h | 40 + - .../amd/dal/dc/adapter/hw_ctx_adapter_service.c | 164 + - .../amd/dal/dc/adapter/hw_ctx_adapter_service.h | 86 + - .../drm/amd/dal/dc/adapter/wireless_data_source.c | 209 + - .../drm/amd/dal/dc/adapter/wireless_data_source.h | 80 + - .../gpu/drm/amd/dal/dc/asic_capability/Makefile | 23 + - .../amd/dal/dc/asic_capability/asic_capability.c | 178 + - .../dc/asic_capability/carrizo_asic_capability.c | 146 + - .../dc/asic_capability/carrizo_asic_capability.h | 36 + - drivers/gpu/drm/amd/dal/dc/audio/Makefile | 22 + - drivers/gpu/drm/amd/dal/dc/audio/audio.h | 195 + - drivers/gpu/drm/amd/dal/dc/audio/audio_base.c | 463 ++ - .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c | 452 ++ - .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h | 42 + - .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c | 1929 ++++++++ - .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h | 47 + - drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c | 771 ++++ - drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h | 285 ++ - drivers/gpu/drm/amd/dal/dc/basics/Makefile | 10 + - drivers/gpu/drm/amd/dal/dc/basics/conversion.c | 223 + - drivers/gpu/drm/amd/dal/dc/basics/conversion.h | 49 + - drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c | 692 +++ - drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c | 223 + - drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c | 135 + - drivers/gpu/drm/amd/dal/dc/basics/logger.c | 947 ++++ - drivers/gpu/drm/amd/dal/dc/basics/logger.h | 64 + - .../gpu/drm/amd/dal/dc/basics/register_logger.c | 197 + - drivers/gpu/drm/amd/dal/dc/basics/signal_types.c | 116 + - drivers/gpu/drm/amd/dal/dc/basics/vector.c | 309 ++ - drivers/gpu/drm/amd/dal/dc/bios/Makefile | 27 + - drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c | 4758 ++++++++++++++++++++ - drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h | 78 + - .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c | 193 + - .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h | 108 + - drivers/gpu/drm/amd/dal/dc/bios/command_table.c | 2616 +++++++++++ - drivers/gpu/drm/amd/dal/dc/bios/command_table.h | 117 + - .../gpu/drm/amd/dal/dc/bios/command_table_helper.c | 315 ++ - .../gpu/drm/amd/dal/dc/bios/command_table_helper.h | 87 + - .../dal/dc/bios/dce110/bios_parser_helper_dce110.c | 484 ++ - .../dal/dc/bios/dce110/bios_parser_helper_dce110.h | 34 + - .../dc/bios/dce110/command_table_helper_dce110.c | 369 ++ - .../dc/bios/dce110/command_table_helper_dce110.h | 34 + - drivers/gpu/drm/amd/dal/dc/calcs/Makefile | 10 + - drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3478 ++++++++++++++ - drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c | 278 ++ - drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c | 1992 ++++++++ - drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h | 74 + - drivers/gpu/drm/amd/dal/dc/connector/Makefile | 10 + - drivers/gpu/drm/amd/dal/dc/connector/connector.h | 39 + - .../gpu/drm/amd/dal/dc/connector/connector_base.c | 421 ++ - .../drm/amd/dal/dc/connector/connector_signals.c | 204 + - drivers/gpu/drm/amd/dal/dc/core/dc.c | 849 ++++ - drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c | 49 + - drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 1081 +++++ - drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c | 1689 +++++++ - drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c | 188 + - drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 378 ++ - drivers/gpu/drm/amd/dal/dc/core/dc_sink.c | 118 + - drivers/gpu/drm/amd/dal/dc/core/dc_stream.c | 172 + - drivers/gpu/drm/amd/dal/dc/core/dc_surface.c | 124 + - drivers/gpu/drm/amd/dal/dc/core/dc_target.c | 473 ++ - drivers/gpu/drm/amd/dal/dc/dc.h | 440 ++ - drivers/gpu/drm/amd/dal/dc/dc_helpers.h | 75 + - drivers/gpu/drm/amd/dal/dc/dc_services.h | 174 + - drivers/gpu/drm/amd/dal/dc/dc_temp.h | 508 +++ - drivers/gpu/drm/amd/dal/dc/dc_types.h | 677 +++ - drivers/gpu/drm/amd/dal/dc/dce110/Makefile | 33 + - .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c | 886 ++++ - .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h | 84 + - .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 1825 ++++++++ - .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h | 36 + - drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c | 85 + - drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h | 90 + - .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c | 256 ++ - .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c | 877 ++++ - .../drm/amd/dal/dc/dce110/dce110_link_encoder.c | 2049 +++++++++ - .../drm/amd/dal/dc/dce110/dce110_link_encoder.h | 91 + - .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c | 969 ++++ - .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h | 88 + - drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c | 296 ++ - drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h | 140 + - drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c | 904 ++++ - .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c | 610 +++ - .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2473 ++++++++++ - .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 1276 ++++++ - .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h | 55 + - .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c | 1168 +++++ - .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h | 64 + - .../amd/dal/dc/dce110/dce110_timing_generator.c | 1878 ++++++++ - .../amd/dal/dc/dce110/dce110_timing_generator.h | 178 + - .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c | 116 + - .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h | 91 + - .../amd/dal/dc/dce110/dce110_transform_bit_depth.c | 840 ++++ - .../amd/dal/dc/dce110/dce110_transform_bit_depth.h | 51 + - .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c | 297 ++ - .../drm/amd/dal/dc/dce110/dce110_transform_scl.c | 818 ++++ - .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c | 531 +++ - drivers/gpu/drm/amd/dal/dc/dcs/Makefile | 10 + - drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c | 159 + - drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h | 60 + - drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c | 1034 +++++ - drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h | 38 + - drivers/gpu/drm/amd/dal/dc/gpio/Makefile | 24 + - .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c | 883 ++++ - .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h | 46 + - .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c | 84 + - .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h | 32 + - .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c | 367 ++ - .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h | 47 + - .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c | 440 ++ - .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h | 34 + - drivers/gpu/drm/amd/dal/dc/gpio/ddc.c | 290 ++ - drivers/gpu/drm/amd/dal/dc/gpio/ddc.h | 45 + - drivers/gpu/drm/amd/dal/dc/gpio/dvo.c | 138 + - drivers/gpu/drm/amd/dal/dc/gpio/dvo.h | 42 + - drivers/gpu/drm/amd/dal/dc/gpio/gpio.h | 48 + - drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c | 279 ++ - drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c | 470 ++ - drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h | 57 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c | 105 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h | 60 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.c | 318 ++ - drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.h | 89 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c | 80 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h | 74 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c | 408 ++ - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h | 129 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c | 93 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h | 47 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c | 86 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h | 79 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c | 88 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h | 45 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c | 67 + - drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h | 49 + - drivers/gpu/drm/amd/dal/dc/gpio/irq.c | 181 + - drivers/gpu/drm/amd/dal/dc/gpio/irq.h | 42 + - drivers/gpu/drm/amd/dal/dc/gpu/Makefile | 26 + - .../gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c | 407 ++ - .../gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h | 79 + - drivers/gpu/drm/amd/dal/dc/gpu/clock_source.c | 649 +++ - drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h | 136 + - .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c | 92 + - .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h | 63 + - .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c | 90 + - .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h | 33 + - .../amd/dal/dc/gpu/dce110/display_clock_dce110.c | 958 ++++ - .../amd/dal/dc/gpu/dce110/display_clock_dce110.h | 53 + - .../dal/dc/gpu/dce110/ext_clock_source_dce110.c | 383 ++ - .../dal/dc/gpu/dce110/ext_clock_source_dce110.h | 38 + - .../dal/dc/gpu/dce110/pll_clock_source_dce110.c | 718 +++ - .../dal/dc/gpu/dce110/pll_clock_source_dce110.h | 55 + - .../dal/dc/gpu/dce110/vce_clock_source_dce110.c | 193 + - .../dal/dc/gpu/dce110/vce_clock_source_dce110.h | 32 + - drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c | 204 + - drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h | 82 + - drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c | 127 + - drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h | 63 + - drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c | 119 + - drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h | 47 + - drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c | 141 + - drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h | 52 + - drivers/gpu/drm/amd/dal/dc/i2caux/Makefile | 23 + - drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c | 568 +++ - drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h | 119 + - .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c | 789 ++++ - .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h | 56 + - .../i2caux/dce110/i2c_generic_hw_engine_dce110.h | 25 + - .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c | 954 ++++ - .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h | 58 + - .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c | 172 + - .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h | 43 + - .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c | 260 ++ - .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h | 39 + - drivers/gpu/drm/amd/dal/dc/i2caux/engine.h | 129 + - drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c | 68 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c | 122 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h | 113 + - .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c | 287 ++ - .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h | 77 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c | 247 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h | 80 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c | 615 +++ - drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h | 81 + - drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c | 519 +++ - drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h | 123 + - drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h | 463 ++ - drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h | 60 + - drivers/gpu/drm/amd/dal/dc/inc/compressor.h | 140 + - drivers/gpu/drm/amd/dal/dc/inc/core_dc.h | 39 + - drivers/gpu/drm/amd/dal/dc/inc/core_status.h | 46 + - drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 308 ++ - drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h | 51 + - drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 170 + - drivers/gpu/drm/amd/dal/dc/inc/ipp.h | 66 + - drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h | 67 + - drivers/gpu/drm/amd/dal/dc/inc/mem_input.h | 55 + - drivers/gpu/drm/amd/dal/dc/inc/opp.h | 206 + - drivers/gpu/drm/amd/dal/dc/inc/resource.h | 61 + - drivers/gpu/drm/amd/dal/dc/inc/transform.h | 81 + - drivers/gpu/drm/amd/dal/dc/irq/Makefile | 21 + - .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c | 389 ++ - .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h | 34 + - drivers/gpu/drm/amd/dal/dc/irq/irq_service.c | 173 + - drivers/gpu/drm/amd/dal/dc/irq/irq_service.h | 85 + - drivers/gpu/drm/amd/dal/dc/irq_types.h | 199 + - .../amd/dal/include/adapter_service_interface.h | 628 +++ - .../drm/amd/dal/include/adapter_service_types.h | 70 + - .../gpu/drm/amd/dal/include/adjustment_interface.h | 230 + - drivers/gpu/drm/amd/dal/include/adjustment_types.h | 420 ++ - .../amd/dal/include/asic_capability_interface.h | 58 + - .../drm/amd/dal/include/asic_capability_types.h | 134 + - drivers/gpu/drm/amd/dal/include/audio_interface.h | 184 + - drivers/gpu/drm/amd/dal/include/audio_types.h | 275 ++ - .../drm/amd/dal/include/bios_parser_interface.h | 294 ++ - .../gpu/drm/amd/dal/include/bios_parser_types.h | 305 ++ - drivers/gpu/drm/amd/dal/include/bit_set.h | 61 + - .../drm/amd/dal/include/clock_source_interface.h | 89 + - .../gpu/drm/amd/dal/include/clock_source_types.h | 118 + - .../gpu/drm/amd/dal/include/connector_interface.h | 82 + - drivers/gpu/drm/amd/dal/include/dal_asic_id.h | 106 + - .../gpu/drm/amd/dal/include/dal_register_logger.h | 43 + - drivers/gpu/drm/amd/dal/include/dal_types.h | 292 ++ - .../amd/dal/include/dc_clock_generator_interface.h | 77 + - drivers/gpu/drm/amd/dal/include/dcs_interface.h | 351 ++ - drivers/gpu/drm/amd/dal/include/dcs_types.h | 742 +++ - drivers/gpu/drm/amd/dal/include/ddc_interface.h | 74 + - .../drm/amd/dal/include/ddc_service_interface.h | 100 + - .../gpu/drm/amd/dal/include/ddc_service_types.h | 220 + - .../amd/dal/include/default_mode_list_interface.h | 37 + - .../drm/amd/dal/include/display_clock_interface.h | 189 + - .../drm/amd/dal/include/display_path_interface.h | 436 ++ - .../gpu/drm/amd/dal/include/display_path_types.h | 132 + - .../amd/dal/include/display_service_interface.h | 165 + - .../drm/amd/dal/include/display_service_types.h | 167 + - drivers/gpu/drm/amd/dal/include/dmcu_interface.h | 87 + - drivers/gpu/drm/amd/dal/include/dmcu_types.h | 199 + - .../dal/include/dpcd_access_service_interface.h | 65 + - drivers/gpu/drm/amd/dal/include/dpcd_defs.h | 869 ++++ - drivers/gpu/drm/amd/dal/include/dvo_interface.h | 48 + - .../gpu/drm/amd/dal/include/encoder_interface.h | 278 ++ - drivers/gpu/drm/amd/dal/include/encoder_types.h | 216 + - drivers/gpu/drm/amd/dal/include/fixed31_32.h | 389 ++ - drivers/gpu/drm/amd/dal/include/fixed32_32.h | 80 + - drivers/gpu/drm/amd/dal/include/gpio_interface.h | 93 + - .../drm/amd/dal/include/gpio_service_interface.h | 94 + - drivers/gpu/drm/amd/dal/include/gpio_types.h | 393 ++ - drivers/gpu/drm/amd/dal/include/gpu_clock_info.h | 43 + - drivers/gpu/drm/amd/dal/include/gpu_interface.h | 91 + - drivers/gpu/drm/amd/dal/include/grph_csc_types.h | 98 + - .../drm/amd/dal/include/grph_object_ctrl_defs.h | 598 +++ - drivers/gpu/drm/amd/dal/include/grph_object_defs.h | 328 ++ - drivers/gpu/drm/amd/dal/include/grph_object_id.h | 285 ++ - .../gpu/drm/amd/dal/include/hw_adjustment_set.h | 50 + - .../gpu/drm/amd/dal/include/hw_adjustment_types.h | 205 + - .../amd/dal/include/hw_path_mode_set_interface.h | 48 + - .../drm/amd/dal/include/hw_sequencer_interface.h | 388 ++ - .../gpu/drm/amd/dal/include/hw_sequencer_types.h | 305 ++ - drivers/gpu/drm/amd/dal/include/i2caux_interface.h | 127 + - drivers/gpu/drm/amd/dal/include/irq_interface.h | 53 + - .../drm/amd/dal/include/irq_service_interface.h | 55 + - drivers/gpu/drm/amd/dal/include/isr_config_types.h | 157 + - .../gpu/drm/amd/dal/include/link_encoder_types.h | 32 + - .../drm/amd/dal/include/link_service_interface.h | 202 + - .../gpu/drm/amd/dal/include/link_service_types.h | 428 ++ - drivers/gpu/drm/amd/dal/include/logger_interface.h | 153 + - drivers/gpu/drm/amd/dal/include/logger_types.h | 356 ++ - .../gpu/drm/amd/dal/include/mode_manager_types.h | 71 + - .../gpu/drm/amd/dal/include/mode_query_interface.h | 93 + - .../amd/dal/include/mode_timing_list_interface.h | 51 + - .../gpu/drm/amd/dal/include/overlay_interface.h | 137 + - drivers/gpu/drm/amd/dal/include/overlay_types.h | 164 + - .../drm/amd/dal/include/path_mode_set_interface.h | 107 + - drivers/gpu/drm/amd/dal/include/plane_types.h | 309 ++ - drivers/gpu/drm/amd/dal/include/scaler_types.h | 196 + - .../amd/dal/include/set_mode_params_interface.h | 101 + - drivers/gpu/drm/amd/dal/include/set_mode_types.h | 285 ++ - drivers/gpu/drm/amd/dal/include/signal_types.h | 58 + - .../gpu/drm/amd/dal/include/stream_encoder_types.h | 16 + - .../drm/amd/dal/include/timing_generator_types.h | 150 + - .../amd/dal/include/timing_list_query_interface.h | 69 + - drivers/gpu/drm/amd/dal/include/vector.h | 150 + - drivers/gpu/drm/amd/dal/include/video_csc_types.h | 135 + - .../gpu/drm/amd/dal/include/video_gamma_types.h | 56 + - 294 files changed, 87748 insertions(+) - create mode 100644 drivers/gpu/drm/amd/dal/Kconfig - create mode 100644 drivers/gpu/drm/amd/dal/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dal_power_interface_types.h - create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h - create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/connector/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/connector/connector.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/connector/connector_base.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/connector/connector_signals.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_helpers.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_services.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_temp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dvo.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dvo.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/clock_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h - create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/adjustment_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/adjustment_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/bit_set.h - create mode 100644 drivers/gpu/drm/amd/dal/include/clock_source_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/clock_source_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/connector_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/default_mode_list_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/display_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/display_service_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_access_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h - create mode 100644 drivers/gpu/drm/amd/dal/include/dvo_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h - create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h - create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/gpu_clock_info.h - create mode 100644 drivers/gpu/drm/amd/dal/include/gpu_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h - create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h - create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h - create mode 100644 drivers/gpu/drm/amd/dal/include/hw_adjustment_set.h - create mode 100644 drivers/gpu/drm/amd/dal/include/hw_adjustment_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/hw_path_mode_set_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/isr_config_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/link_encoder_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/mode_manager_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/mode_query_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/mode_timing_list_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/overlay_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/overlay_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/path_mode_set_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/plane_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_params_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/stream_encoder_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/timing_generator_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h - create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h - create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h - create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h - -diff --git a/drivers/gpu/drm/amd/dal/Kconfig b/drivers/gpu/drm/amd/dal/Kconfig -new file mode 100644 -index 0000000..14df02e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/Kconfig -@@ -0,0 +1,39 @@ -+menu "Display Engine Configuration" -+ depends on DRM && (DRM_AMDSOC || DRM_AMDGPU) -+ -+config DRM_AMD_DAL -+ bool "AMD DAL - 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 AMD SOC. -+ -+ Will be deprecated when the DAL component becomes stable and -+ AMDSOC will fully switch to it. -+ -+config DRM_AMD_DAL_VBIOS_PRESENT -+ bool "Video Bios available on board" -+ depends on DRM_AMD_DAL -+ help -+ This option is needed to allow a full range of feature -+ support when working on -+ x86 platforms and there is a VBIOS -+ present in the system -+ -+config DRM_AMD_DAL_DCE11_0 -+ bool "Carrizo family" -+ depends on DRM_AMD_DAL -+ help -+ Choose this option -+ if you want to have -+ CZ family -+ for display engine -+ -+config DEBUG_KERNEL_DAL -+ bool "Enable kgdb break in DAL" -+ depends on DRM_AMD_DAL -+ help -+ Choose this option -+ if you want to hit -+ kdgb_break in assert. -+ -+endmenu -diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile -new file mode 100644 -index 0000000..bdf5d18 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/Makefile -@@ -0,0 +1,19 @@ -+# -+# Makefile for the DAL (Display Abstract Layer), which is a sub-component -+# of the AMDGPU drm driver. -+# It provides the HW control for display related functionalities. -+ -+AMDDALPATH = $(RELATIVE_AMD_DAL_PATH) -+ -+subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include -DDAL_CZ_BRINGUP -+ -+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc/inc/ -+ -+#TODO: remove when Timing Sync feature is complete -+subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 -+ -+DAL_LIBS = amdgpu_dm dc -+ -+AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS))) -+ -+include $(AMD_DAL) -diff --git a/drivers/gpu/drm/amd/dal/dal_power_interface_types.h b/drivers/gpu/drm/amd/dal/dal_power_interface_types.h -new file mode 100644 -index 0000000..82e8ca2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dal_power_interface_types.h -@@ -0,0 +1,76 @@ -+/* -+ * 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_POWER_INTERFACE_TYPES_H__ -+#define __DAL_POWER_INTERFACE_TYPES_H__ -+ -+enum dal_to_power_clocks_state { -+ PP_CLOCKS_STATE_INVALID, -+ PP_CLOCKS_STATE_ULTRA_LOW, -+ PP_CLOCKS_STATE_LOW, -+ PP_CLOCKS_STATE_NOMINAL, -+ PP_CLOCKS_STATE_PERFORMANCE -+}; -+ -+/* clocks in khz */ -+struct dal_to_power_info { -+ enum dal_to_power_clocks_state required_clock; -+ uint32_t min_sclk; -+ uint32_t min_mclk; -+ uint32_t min_deep_sleep_sclk; -+}; -+ -+/* clocks in khz */ -+struct power_to_dal_info { -+ uint32_t min_sclk; -+ uint32_t max_sclk; -+ uint32_t min_mclk; -+ uint32_t max_mclk; -+}; -+ -+/* clocks in khz */ -+struct dal_system_clock_range { -+ uint32_t min_sclk; -+ uint32_t max_sclk; -+ -+ uint32_t min_mclk; -+ uint32_t max_mclk; -+ -+ uint32_t min_dclk; -+ uint32_t max_dclk; -+ -+ /* Wireless Display */ -+ uint32_t min_eclk; -+ uint32_t max_eclk; -+}; -+ -+/* clocks in khz */ -+struct dal_to_power_dclk { -+ uint32_t optimal; /* input: best optimizes for stutter efficiency */ -+ uint32_t minimal; /* input: the lowest clk that DAL can support */ -+ uint32_t established; /* output: the actually set one */ -+}; -+ -+#endif /* __DAL_POWER_INTERFACE_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dal_services.h b/drivers/gpu/drm/amd/dal/dal_services.h -new file mode 100644 -index 0000000..398e4e5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dal_services.h -@@ -0,0 +1,266 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_SERVICES_H__ -+#define __DAL_SERVICES_H__ -+ -+/* DC headers*/ -+#include "dc/dc_services.h" -+ -+#include "dal_power_interface_types.h" -+ -+#include "irq_types.h" -+#include "include/dal_types.h" -+ -+/* TODO: investigate if it can be removed. */ -+/* Undefine DEPRECATED because it conflicts with printk.h */ -+#undef DEPRECATED -+ -+/* -+ * -+ * interrupt services to register and unregister handlers -+ * -+ */ -+ -+/* the timer "interrupt" current implementation supports only -+'one-shot' type, and LOW level (asynchronous) context */ -+void dal_register_timer_interrupt( -+ struct dc_context *ctx, -+ struct dc_timer_interrupt_params *int_params, -+ interrupt_handler ih, -+ void *handler_args); -+ -+/* -+ * -+ * kernel memory manipulation -+ * -+ */ -+ -+/* Reallocate memory. The contents will remain unchanged.*/ -+void *dc_service_realloc(struct dc_context *ctx, const void *ptr, uint32_t size); -+ -+void dc_service_memmove(void *dst, const void *src, uint32_t size); -+ -+void dc_service_memset(void *p, int32_t c, uint32_t count); -+ -+int32_t dal_memcmp(const void *p1, const void *p2, uint32_t count); -+ -+int32_t dal_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count); -+ -+/* -+ * -+ * GPU registers access -+ * -+ */ -+static inline uint32_t dal_read_reg( -+ const struct dc_context *ctx, -+ uint32_t address) -+{ -+ uint32_t value = cgs_read_register(ctx->cgs_device, address); -+ -+#if defined(__DAL_REGISTER_LOGGER__) -+ if (true == dal_reg_logger_should_dump_register()) { -+ dal_reg_logger_rw_count_increment(); -+ DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value); -+ } -+#endif -+ return value; -+} -+ -+static inline uint32_t get_reg_field_value_ex( -+ uint32_t reg_value, -+ uint32_t mask, -+ uint8_t shift) -+{ -+ return (mask & reg_value) >> shift; -+} -+ -+#define get_reg_field_value(reg_value, reg_name, reg_field)\ -+ get_reg_field_value_ex(\ -+ (reg_value),\ -+ reg_name ## __ ## reg_field ## _MASK,\ -+ reg_name ## __ ## reg_field ## __SHIFT) -+ -+static inline uint32_t set_reg_field_value_ex( -+ uint32_t reg_value, -+ uint32_t value, -+ uint32_t mask, -+ uint8_t shift) -+{ -+ return (reg_value & ~mask) | (mask & (value << shift)); -+} -+ -+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\ -+ (reg_value) = set_reg_field_value_ex(\ -+ (reg_value),\ -+ (value),\ -+ reg_name ## __ ## reg_field ## _MASK,\ -+ reg_name ## __ ## reg_field ## __SHIFT) -+ -+static inline void dal_write_reg( -+ const struct dc_context *ctx, -+ uint32_t address, -+ uint32_t value) -+{ -+#if defined(__DAL_REGISTER_LOGGER__) -+ if (true == dal_reg_logger_should_dump_register()) { -+ dal_reg_logger_rw_count_increment(); -+ DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value); -+ } -+#endif -+ cgs_write_register(ctx->cgs_device, address, value); -+} -+ -+static inline uint32_t dal_read_index_reg( -+ const struct dc_context *ctx, -+ enum cgs_ind_reg addr_space, -+ uint32_t index) -+{ -+ return cgs_read_ind_register(ctx->cgs_device,addr_space,index); -+} -+ -+static inline void dal_write_index_reg( -+ const struct dc_context *ctx, -+ enum cgs_ind_reg addr_space, -+ uint32_t index, -+ uint32_t value) -+{ -+ cgs_write_ind_register(ctx->cgs_device,addr_space,index,value); -+} -+ -+enum platform_method { -+ PM_GET_AVAILABLE_METHODS = 1 << 0, -+ PM_GET_LID_STATE = 1 << 1, -+ PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2 -+}; -+ -+struct platform_info_params { -+ enum platform_method method; -+ void *data; -+}; -+ -+struct platform_info_brightness_caps { -+ uint8_t ac_level_percentage; -+ uint8_t dc_level_percentage; -+}; -+ -+struct platform_info_ext_brightness_caps { -+ struct platform_info_brightness_caps basic_caps; -+ struct data_point { -+ uint8_t luminance; -+ uint8_t signal_level; -+ } data_points[99]; -+ -+ uint8_t data_points_num; -+ uint8_t min_input_signal; -+ uint8_t max_input_signal; -+}; -+ -+bool dal_get_platform_info( -+ struct dc_context *ctx, -+ struct platform_info_params *params); -+ -+ -+static inline uint32_t dal_bios_cmd_table_para_revision( -+ struct dc_context *ctx, -+ uint32_t index) -+{ -+ uint8_t frev; -+ uint8_t crev; -+ -+ if (cgs_atom_get_cmd_table_revs( -+ ctx->cgs_device, -+ index, -+ &frev, -+ &crev) != 0) -+ return 0; -+ -+ return crev; -+} -+ -+/* Calls to notification */ -+ -+/* Notify display manager for hotplug event */ -+void dal_notify_hotplug( -+ struct dc_context *ctx, -+ uint32_t display_index, -+ bool is_connected); -+ -+ -+void dal_notify_setmode_complete( -+ struct dc_context *ctx, -+ uint32_t h_total, -+ uint32_t v_total, -+ uint32_t h_active, -+ uint32_t v_active, -+ uint32_t pix_clk_in_khz); -+ -+/* End of notification calls */ -+ -+/* -+ * -+ * Delay functions. -+ * -+ * -+ */ -+ -+/* Following the guidance: -+ * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt -+ * -+ * This is a busy wait for nano seconds and should be used only for -+ * extremely short ranges -+ */ -+void dal_delay_in_nanoseconds(uint32_t nanoseconds); -+ -+ -+/* -+ * -+ * atombios services -+ * -+ */ -+ -+bool dal_exec_bios_cmd_table( -+ struct dc_context *ctx, -+ uint32_t index, -+ void *params); -+ -+/* -+ * -+ * print-out services -+ * -+ */ -+#define dal_log_to_buffer(buffer, size, fmt, args)\ -+ vsnprintf(buffer, size, fmt, args) -+ -+long dal_get_pid(void); -+long dal_get_tgid(void); -+ -+/* -+ * -+ * general debug capabilities -+ * -+ */ -+ -+#endif /* __DAL_SERVICES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dal_services_types.h b/drivers/gpu/drm/amd/dal/dal_services_types.h -new file mode 100644 -index 0000000..89c73c6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dal_services_types.h -@@ -0,0 +1,62 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_SERVICES_TYPES_H__ -+#define __DAL_SERVICES_TYPES_H__ -+ -+#define INVALID_DISPLAY_INDEX 0xffffffff -+ -+#if defined __KERNEL__ -+ -+#include <asm/byteorder.h> -+#include <linux/types.h> -+#include <drm/drmP.h> -+ -+#include "cgs_linux.h" -+ -+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU) -+#define BIGENDIAN_CPU -+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU) -+#define LITTLEENDIAN_CPU -+#endif -+ -+#undef READ -+#undef WRITE -+#undef FRAME_SIZE -+ -+#define dal_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__) -+ -+#define dal_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) -+ -+#define dal_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) -+ -+#define dal_vlog(fmt, args) vprintk(fmt, args) -+ -+#define dal_min(x, y) min(x, y) -+#define dal_max(x, y) max(x, y) -+ -+#endif -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile -new file mode 100644 -index 0000000..6926356 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/Makefile -@@ -0,0 +1,24 @@ -+# -+# Makefile for Display Core (dc) component. -+# -+ -+DC_LIBS = adapter asic_capability audio basics bios calcs connector \ -+dcs gpio gpu i2caux irq -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+DC_LIBS += dce110 -+endif -+ -+AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/dc/,$(DC_LIBS))) -+ -+include $(AMD_DC) -+ -+DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_target.o dc_sink.o dc_stream.o \ -+dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o -+ -+AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) -+ -+AMD_DAL_FILES += $(AMD_DISPLAY_CORE) -+ -+ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile -new file mode 100644 -index 0000000..8ede504 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile -@@ -0,0 +1,18 @@ -+# -+# Makefile for the 'adapter' sub-component of DAL. -+# It provides the control and status of HW adapter. -+ -+ADAPTER = adapter_service.o hw_ctx_adapter_service.o wireless_data_source.o -+ -+AMD_DAL_ADAPTER = $(addprefix $(AMDDALPATH)/dc/adapter/,$(ADAPTER)) -+ -+AMD_DAL_FILES += $(AMD_DAL_ADAPTER) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce110/hw_ctx_adapter_service_dce110.o -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c -new file mode 100644 -index 0000000..4f9a637 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c -@@ -0,0 +1,2037 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+ -+#include "dal_services.h" -+ -+#include "include/adapter_service_interface.h" -+#include "include/i2caux_interface.h" -+#include "include/asic_capability_types.h" -+#include "include/bios_parser_interface.h" -+#include "include/gpio_service_interface.h" -+#include "include/asic_capability_interface.h" -+#include "include/logger_interface.h" -+ -+#include "adapter_service.h" -+#include "hw_ctx_adapter_service.h" -+#include "wireless_data_source.h" -+ -+#include "atom.h" -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/hw_ctx_adapter_service_dce110.h" -+#endif -+ -+/* -+ * Adapter service feature entry table. -+ * -+ * This is an array of features that is used to generate feature set. Each -+ * entry consists three element: -+ * -+ * Feature name, default value, and if this feature is a boolean type. A -+ * feature can only be a boolean or int type. -+ * -+ * Example 1: a boolean type feature -+ * FEATURE_ENABLE_HW_EDID_POLLING, false, true -+ * -+ * First element is feature name: EATURE_ENABLE_HW_EDID_POLLING, it has a -+ * default value 0, and it is a boolean feature. -+ * -+ * Example 2: an int type feature -+ * FEATURE_DCP_PROGRAMMING_WA, 0x1FF7, false -+ * -+ * In this case, the default value is 0x1FF7 and not a boolean type, which -+ * makes it an int type. -+ */ -+ -+static -+#if !defined(DAL_CZ_BRINGUP) -+const -+#endif -+struct feature_source_entry feature_entry_table[] = { -+ /* Feature name | default value | is boolean type */ -+ {FEATURE_ENABLE_HW_EDID_POLLING, false, true}, -+ {FEATURE_DP_SINK_DETECT_POLL_DATA_PIN, false, true}, -+ {FEATURE_UNDERFLOW_INTERRUPT, false, true}, -+ {FEATURE_ALLOW_WATERMARK_ADJUSTMENT, false, true}, -+ {FEATURE_LIGHT_SLEEP, false, true}, -+ {FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE, false, true}, -+ {FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE, false, true}, -+ {FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE, false, true}, -+ {FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, false, true}, -+ {FEATURE_MAXIMIZE_URGENCY_WATERMARKS, false, true}, -+ {FEATURE_MAXIMIZE_STUTTER_MARKS, false, true}, -+ {FEATURE_MAXIMIZE_NBP_MARKS, false, true}, -+ /* -+ * We meet HW I2C issue when test S3 resume on KB. -+ * An EPR is created for debug the issue. -+ * Make Test has already been implemented -+ * with HW I2C. The work load for revert back to SW I2C in make test -+ * is big. Below is workaround for this issue. -+ * Driver uses SW I2C. -+ * Make Test uses HW I2C. -+ */ -+#if defined(DAL_CZ_BRINGUP) -+ {FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, true, true}, -+#else -+ {FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, false, true}, -+#endif -+ {FEATURE_USE_MAX_DISPLAY_CLK, false, true}, -+ {FEATURE_ALLOW_EDP_RESOURCE_SHARING, false, true}, -+ {FEATURE_SUPPORT_DP_YUV, false, true}, -+ {FEATURE_SUPPORT_DP_Y_ONLY, false, true}, -+ {FEATURE_DISABLE_DP_GTC_SYNC, true, true}, -+ {FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true}, -+ {FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE, 0, false}, -+ {FEATURE_DCP_DITHER_MODE, 0, false}, -+ {FEATURE_DCP_PROGRAMMING_WA, 0, false}, -+ {FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true}, -+ {FEATURE_ENABLE_DFS_BYPASS, false, true}, -+ {FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT, false, true}, -+ {FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, 2, false}, -+ {FEATURE_WIRELESS_LIMIT_720P, false, true}, -+ {FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true}, -+ {FEATURE_SUPPORTED_HDMI_CONNECTION_NUM, 0, false}, -+ {FEATURE_DETECT_REQUIRE_HPD_HIGH, false, true}, -+ {FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true}, -+ {FEATURE_LB_HIGH_RESOLUTION, false, true}, -+ {FEATURE_MAX_CONTROLLER_NUM, 0, false}, -+ {FEATURE_DRR_SUPPORT, AS_DRR_SUPPORT_ENABLED, false}, -+ {FEATURE_STUTTER_MODE, 15, false}, -+ {FEATURE_DP_DISPLAY_FORCE_SS_ENABLE, false, true}, -+ {FEATURE_REPORT_CE_MODE_ONLY, false, true}, -+ {FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT, false, true}, -+ {FEATURE_DDC_READ_FORCE_REPEATED_START, false, true}, -+ {FEATURE_FORCE_TIMING_RESYNC, false, true}, -+ {FEATURE_TMDS_DISABLE_DITHERING, false, true}, -+ {FEATURE_HDMI_DISABLE_DITHERING, false, true}, -+ {FEATURE_DP_DISABLE_DITHERING, false, true}, -+ {FEATURE_EMBEDDED_DISABLE_DITHERING, true, true}, -+ {FEATURE_ALLOW_SELF_REFRESH, false, true}, -+ {FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE, false, true}, -+ {FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT, false, true}, -+ {FEATURE_FORCE_PSR, false, true}, -+ {FEATURE_PSR_SETUP_TIME_TEST, 0, false}, -+ {FEATURE_POWER_GATING_PIPE_IN_TILE, true, true}, -+ {FEATURE_POWER_GATING_LB_PORTION, true, true}, -+ {FEATURE_PREFER_3D_TIMING, false, true}, -+ {FEATURE_VARI_BRIGHT_ENABLE, true, true}, -+ {FEATURE_PSR_ENABLE, false, true}, -+ {FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO, false, true}, -+ {FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS, true, true}, -+ {FEATURE_EDID_STRESS_READ, false, true}, -+ {FEATURE_DP_FRAME_PACK_STEREO3D, false, true}, -+ {FEATURE_DISPLAY_PREFERRED_VIEW, 0, false}, -+ {FEATURE_ALLOW_HDMI_WITHOUT_AUDIO, false, true}, -+ {FEATURE_ABM_2_0, false, true}, -+ {FEATURE_SUPPORT_MIRABILIS, false, true}, -+ {FEATURE_OPTIMIZATION, 0xFFFF, false}, -+ {FEATURE_PERF_MEASURE, 0, false}, -+ {FEATURE_MIN_BACKLIGHT_LEVEL, 0, false}, -+ {FEATURE_MAX_BACKLIGHT_LEVEL, 255, false}, -+ {FEATURE_LOAD_DMCU_FIRMWARE, true, true}, -+ {FEATURE_DISABLE_AZ_CLOCK_GATING, false, true}, -+ {FEATURE_ENABLE_GPU_SCALING, false, true}, -+ {FEATURE_DONGLE_SINK_COUNT_CHECK, true, true}, -+ {FEATURE_INSTANT_UP_SCALE_DOWN_SCALE, false, true}, -+ {FEATURE_TILED_DISPLAY, false, true}, -+ {FEATURE_PREFERRED_ABM_CONFIG_SET, 0, false}, -+ {FEATURE_CHANGE_SW_I2C_SPEED, 50, false}, -+ {FEATURE_CHANGE_HW_I2C_SPEED, 50, false}, -+ {FEATURE_CHANGE_I2C_SPEED_CONTROL, false, true}, -+ {FEATURE_DEFAULT_PSR_LEVEL, 0, false}, -+ {FEATURE_MAX_CLOCK_SOURCE_NUM, 0, false}, -+ {FEATURE_REPORT_SINGLE_SELECTED_TIMING, false, true}, -+ {FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE, true, true}, -+ {FEATURE_SUPPORT_EXTERNAL_PANEL_DRR, false, true}, -+ {FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE, 0, false}, -+ {FEATURE_ABM_CONFIG, 0, false}, -+ {FEATURE_WIRELESS_ENABLE, false, true}, -+ {FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, false, true}, -+ {FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS, 0, false}, -+ {FEATURE_USE_PPLIB, true, true}, -+ {FEATURE_DISABLE_LPT_SUPPORT, false, true}, -+ {FEATURE_DUMMY_FBC_BACKEND, false, true}, -+ {FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL, true, true}, -+ {FEATURE_DISABLE_FBC_COMP_CLK_GATE, false, true}, -+ {FEATURE_PIXEL_PERFECT_OUTPUT, false, true}, -+ {FEATURE_8BPP_SUPPORTED, false, true} -+}; -+ -+ -+/* Stores entire ASIC features by sets */ -+uint32_t adapter_feature_set[FEATURE_MAXIMUM/32]; -+ -+enum { -+ LEGACY_MAX_NUM_OF_CONTROLLERS = 2, -+ DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS = 2 -+}; -+ -+/* -+ * get_feature_entries_num -+ * -+ * Get number of feature entries -+ */ -+static inline uint32_t get_feature_entries_num(void) -+{ -+ return ARRAY_SIZE(feature_entry_table); -+} -+ -+static void get_platform_info_methods( -+ struct adapter_service *as) -+{ -+ struct platform_info_params params; -+ uint32_t mask = 0; -+ -+ params.data = &mask; -+ params.method = PM_GET_AVAILABLE_METHODS; -+ -+ if (dal_get_platform_info(as->ctx, ¶ms)) -+ as->platform_methods_mask = mask; -+ -+ -+} -+ -+static void initialize_backlight_caps( -+ struct adapter_service *as) -+{ -+ struct firmware_info fw_info; -+ struct embedded_panel_info panel_info; -+ struct platform_info_ext_brightness_caps caps; -+ struct platform_info_params params; -+ bool custom_curve_present = false; -+ bool custom_min_max_present = false; -+ -+ if (!(PM_GET_EXTENDED_BRIGHNESS_CAPS & as->platform_methods_mask)) { -+ dal_logger_write(as->ctx->logger, -+ LOG_MAJOR_BACKLIGHT, -+ LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, -+ "This method is not supported\n"); -+ return; -+ } -+ -+ if (dal_bios_parser_get_firmware_info -+ (as->bios_parser, &fw_info) != BP_RESULT_OK || -+ dal_bios_parser_get_embedded_panel_info -+ (as->bios_parser, &panel_info) != BP_RESULT_OK) -+ return; -+ -+ params.data = ∩︀ -+ params.method = PM_GET_EXTENDED_BRIGHNESS_CAPS; -+ -+ if (dal_get_platform_info(as->ctx, ¶ms)) { -+ as->ac_level_percentage = caps.basic_caps.ac_level_percentage; -+ as->dc_level_percentage = caps.basic_caps.dc_level_percentage; -+ custom_curve_present = (caps.data_points_num > 0); -+ custom_min_max_present = true; -+ } else -+ return; -+ /* Choose minimum backlight level base on priority: -+ * extended caps,VBIOS,default */ -+ if (custom_min_max_present) -+ as->backlight_8bit_lut[0] = caps.min_input_signal; -+ -+ else if (fw_info.min_allowed_bl_level > 0) -+ as->backlight_8bit_lut[0] = fw_info.min_allowed_bl_level; -+ -+ else -+ as->backlight_8bit_lut[0] = DEFAULT_MIN_BACKLIGHT; -+ -+ /* Choose maximum backlight level base on priority: -+ * extended caps,default */ -+ if (custom_min_max_present) -+ as->backlight_8bit_lut[100] = caps.max_input_signal; -+ -+ else -+ as->backlight_8bit_lut[100] = DEFAULT_MAX_BACKLIGHT; -+ -+ if (as->backlight_8bit_lut[100] > ABSOLUTE_BACKLIGHT_MAX) -+ as->backlight_8bit_lut[100] = ABSOLUTE_BACKLIGHT_MAX; -+ -+ if (as->backlight_8bit_lut[0] > as->backlight_8bit_lut[100]) -+ as->backlight_8bit_lut[0] = as->backlight_8bit_lut[100]; -+ -+ if (custom_curve_present) { -+ uint16_t index = 1; -+ uint16_t i; -+ uint16_t num_of_data_points = (caps.data_points_num <= 99 ? -+ caps.data_points_num : 99); -+ /* Filling translation table from data points - -+ * between every two provided data points we -+ * lineary interpolate missing values -+ */ -+ for (i = 0 ; i < num_of_data_points; i++) { -+ uint16_t luminance = caps.data_points[i].luminance; -+ uint16_t signal_level = -+ caps.data_points[i].signal_level; -+ -+ if (signal_level < as->backlight_8bit_lut[0]) -+ signal_level = as->backlight_8bit_lut[0]; -+ -+ if (signal_level > as->backlight_8bit_lut[100]) -+ signal_level = as->backlight_8bit_lut[100]; -+ -+ /* Lineary interpolate missing values */ -+ if (index < luminance) { -+ uint16_t base_value = -+ as->backlight_8bit_lut[index-1]; -+ uint16_t delta_signal = -+ signal_level - base_value; -+ uint16_t delta_luma = luminance - index + 1; -+ uint16_t step = delta_signal; -+ -+ for (; index < luminance ; index++) { -+ as->backlight_8bit_lut[index] = -+ base_value + -+ (step / delta_luma); -+ step += delta_signal; -+ } -+ } -+ /* Now [index == luminance], so we can add -+ * data point to the translation table */ -+ as->backlight_8bit_lut[index++] = signal_level; -+ } -+ /* Complete the final segment of interpolation - -+ * between last datapoint and maximum value */ -+ if (index < 100) { -+ uint16_t base_value = as->backlight_8bit_lut[index-1]; -+ uint16_t delta_signal = -+ as->backlight_8bit_lut[100]-base_value; -+ uint16_t delta_luma = 100 - index + 1; -+ uint16_t step = delta_signal; -+ -+ for (; index < 100 ; index++) { -+ as->backlight_8bit_lut[index] = base_value + -+ (step / delta_luma); -+ step += delta_signal; -+ } -+ } -+ } -+ /* build backlight translation table based on default curve */ -+ else { -+ /* Default backlight curve can be defined by -+ * polinomial F(x) = A(x*x) + Bx + C. -+ * Backlight curve should always satisfy -+ * F(0) = min, F(100) = max, so polinomial coefficients are: -+ * A is 0.0255 - B/100 - min/10000 - -+ * (255-max)/10000 = (max - min)/10000 - B/100 -+ * B is adjustable factor to modify the curve. -+ * Bigger B results in less concave curve. -+ * B range is [0..(max-min)/100] -+ * C is backlight minimum -+ */ -+ uint16_t delta = as->backlight_8bit_lut[100] - -+ as->backlight_8bit_lut[0]; -+ uint16_t coeffc = as->backlight_8bit_lut[0]; -+ uint16_t coeffb = (BACKLIGHT_CURVE_COEFFB < delta ? -+ BACKLIGHT_CURVE_COEFFB : delta); -+ uint16_t coeffa = delta - coeffb; -+ uint16_t i; -+ uint32_t temp; -+ -+ for (i = 1; i < 100 ; i++) { -+ temp = (coeffa * i * i) / BACKLIGHT_CURVE_COEFFA_FACTOR; -+ as->backlight_8bit_lut[i] = temp + (coeffb * i) / -+ BACKLIGHT_CURVE_COEFFB_FACTOR + coeffc; -+ } -+ } -+ as->backlight_caps_initialized = true; -+} -+ -+static void log_overriden_features( -+ struct adapter_service *as, -+ const char *feature_name, -+ enum adapter_feature_id id, -+ bool bool_feature, -+ uint32_t value) -+{ -+ if (bool_feature) -+ dal_logger_write(as->ctx->logger, -+ LOG_MAJOR_FEATURE_OVERRIDE, -+ LOG_MINOR_FEATURE_OVERRIDE, -+ "Overridden %s is %s now\n", -+ feature_name, -+ (value == 0) ? "disabled" : "enabled"); -+ else -+ dal_logger_write(as->ctx->logger, -+ LOG_MAJOR_FEATURE_OVERRIDE, -+ LOG_MINOR_FEATURE_OVERRIDE, -+ "Overridden %s new value: %d\n", -+ feature_name, -+ value); -+} -+ -+/************************************* -+ * Local static functions definition * -+ *************************************/ -+ -+#define check_bool_feature(feature) \ -+case FEATURE_ ## feature: \ -+ if (param->bool_param_enable_mask & \ -+ (1 << DAL_PARAM_ ## feature)) { \ -+ *data = param->bool_param_values & \ -+ (1 << DAL_PARAM_ ## feature); \ -+ ret = true; \ -+ feature_name = "FEATURE_" #feature; \ -+ } \ -+ break -+ -+#define check_int_feature(feature) \ -+case FEATURE_ ## feature: \ -+ if (param->int_param_values[DAL_PARAM_ ## feature] != \ -+ DAL_PARAM_INVALID_INT) { \ -+ *data = param->int_param_values[DAL_PARAM_ ## feature];\ -+ ret = true;\ -+ bool_feature = false;\ -+ feature_name = "FEATURE_" #feature;\ -+ } \ -+ break -+ -+/* -+ * override_default_parameters -+ * -+ * Override features (from runtime parameter) -+ * corresponding to Adapter Service Feature ID -+ */ -+static bool override_default_parameters( -+ struct adapter_service *as, -+ const struct dal_override_parameters *param, -+ const uint32_t idx, -+ uint32_t *data) -+{ -+ bool ret = false; -+ bool bool_feature = true; -+ char *feature_name; -+ -+ if (idx >= get_feature_entries_num()) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ switch (feature_entry_table[idx].feature_id) { -+ check_int_feature(MAX_COFUNC_NON_DP_DISPLAYS); -+ check_int_feature(DRR_SUPPORT); -+ check_bool_feature(LIGHT_SLEEP); -+ check_bool_feature(MAXIMIZE_STUTTER_MARKS); -+ check_bool_feature(MAXIMIZE_URGENCY_WATERMARKS); -+ check_bool_feature(USE_MAX_DISPLAY_CLK); -+ check_bool_feature(ENABLE_DFS_BYPASS); -+ check_bool_feature(POWER_GATING_PIPE_IN_TILE); -+ check_bool_feature(POWER_GATING_LB_PORTION); -+ check_bool_feature(PSR_ENABLE); -+ check_bool_feature(VARI_BRIGHT_ENABLE); -+ check_bool_feature(USE_PPLIB); -+ check_bool_feature(DISABLE_LPT_SUPPORT); -+ check_bool_feature(DUMMY_FBC_BACKEND); -+ check_bool_feature(ENABLE_GPU_SCALING); -+ default: -+ return false; -+ } -+ if (ret) -+ log_overriden_features( -+ as, -+ feature_name, -+ feature_entry_table[idx].feature_id, -+ bool_feature, -+ *data); -+ -+ return ret; -+} -+ -+/* -+ * get_feature_value_from_data_sources -+ * -+ * For a given feature, determine its value from ASIC cap and wireless -+ * data source. -+ * idx : index of feature_entry_table for the feature id. -+ */ -+static bool get_feature_value_from_data_sources( -+ const struct adapter_service *as, -+ const uint32_t idx, -+ uint32_t *data) -+{ -+ if (idx >= get_feature_entries_num()) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ switch (feature_entry_table[idx].feature_id) { -+ case FEATURE_MAX_COFUNC_NON_DP_DISPLAYS: -+ *data = as->asic_cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS]; -+ break; -+ -+ case FEATURE_WIRELESS_LIMIT_720P: -+ *data = as->asic_cap->caps.WIRELESS_LIMIT_TO_720P; -+ break; -+ -+ case FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT: -+ *data = as->asic_cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT; -+ break; -+ -+ case FEATURE_MODIFY_TIMINGS_FOR_WIRELESS: -+ *data = as->asic_cap->caps.WIRELESS_TIMING_ADJUSTMENT; -+ break; -+ -+ case FEATURE_SUPPORTED_HDMI_CONNECTION_NUM: -+ *data = -+ as->asic_cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM]; -+ break; -+ -+ case FEATURE_DETECT_REQUIRE_HPD_HIGH: -+ *data = as->asic_cap->caps.HPD_CHECK_FOR_EDID; -+ break; -+ -+ case FEATURE_NO_HPD_LOW_POLLING_VCC_OFF: -+ *data = as->asic_cap->caps.NO_VCC_OFF_HPD_POLLING; -+ break; -+ -+ case FEATURE_STUTTER_MODE: -+ *data = as->asic_cap->data[ASIC_DATA_STUTTERMODE]; -+ break; -+ -+ case FEATURE_WIRELESS_ENABLE: -+ *data = as->wireless_data.wireless_enable; -+ break; -+ -+ case FEATURE_8BPP_SUPPORTED: -+ *data = as->asic_cap->caps.SUPPORT_8BPP; -+ break; -+ -+ default: -+ return false; -+ } -+ -+ return true; -+} -+ -+/* get_bool_value -+ * -+ * Get the boolean value of a given feature -+ */ -+static bool get_bool_value( -+ const uint32_t set, -+ const uint32_t idx) -+{ -+ if (idx >= 32) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ return ((set & (1 << idx)) != 0); -+} -+ -+/* -+ * get_hpd_info -+ * -+ * Get HPD information from BIOS -+ */ -+static bool get_hpd_info(struct adapter_service *as, -+ struct graphics_object_id id, -+ struct graphics_object_hpd_info *info) -+{ -+ return BP_RESULT_OK == -+ dal_bios_parser_get_hpd_info(as->bios_parser, id, info); -+} -+ -+/* -+ * lookup_feature_entry -+ * -+ * Find the entry index of a given feature in feature table -+ */ -+static uint32_t lookup_feature_entry( -+ enum adapter_feature_id feature_id) -+{ -+ uint32_t entries_num = get_feature_entries_num(); -+ uint32_t i = 0; -+ -+ while (i != entries_num) { -+ if (feature_entry_table[i].feature_id == feature_id) -+ break; -+ -+ ++i; -+ } -+ -+ return i; -+} -+ -+/* -+ * set_bool_value -+ * -+ * Set the boolean value of a given feature -+ */ -+static void set_bool_value( -+ uint32_t *set, -+ const uint32_t idx, -+ bool value) -+{ -+ if (idx >= 32) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ if (value) -+ *set |= (1 << idx); -+ else -+ *set &= ~(1 << idx); -+} -+ -+/* -+ * generate_feature_set -+ * -+ * Generate the internal feature set from multiple data sources -+ */ -+static bool generate_feature_set( -+ struct adapter_service *as, -+ const struct dal_override_parameters *param) -+{ -+ uint32_t i = 0; -+ uint32_t value = 0; -+ uint32_t set_idx = 0; -+ uint32_t internal_idx = 0; -+ uint32_t entry_num = 0; -+ const struct feature_source_entry *entry = NULL; -+ -+ dc_service_memset(adapter_feature_set, 0, sizeof(adapter_feature_set)); -+ entry_num = get_feature_entries_num(); -+ -+ -+ while (i != entry_num) { -+ entry = &feature_entry_table[i]; -+ -+ if (entry->feature_id <= FEATURE_UNKNOWN || -+ entry->feature_id >= FEATURE_MAXIMUM) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ set_idx = (uint32_t)((entry->feature_id - 1) / 32); -+ internal_idx = (uint32_t)((entry->feature_id - 1) % 32); -+ -+ /* TODO: wireless, runtime parameter, vbios */ -+ if (!override_default_parameters(as, param, i, &value)) { -+ if (!get_feature_value_from_data_sources( -+ as, i, &value)) { -+ /* -+ * Can't find feature values from -+ * above data sources -+ * Assign default value -+ */ -+ value = entry->default_value; -+ } -+ } -+ -+ if (entry->is_boolean_type) -+ set_bool_value(&adapter_feature_set[set_idx], -+ internal_idx, -+ value != 0); -+ else -+ adapter_feature_set[set_idx] = value; -+ -+ i++; -+ } -+ -+ return true; -+} -+ -+ -+/* -+ * create_hw_ctx -+ * -+ * Create HW context for adapter service. This is DCE specific. -+ */ -+static struct hw_ctx_adapter_service *create_hw_ctx( -+ enum dce_version dce_version, -+ struct dc_context *ctx) -+{ -+ switch (dce_version) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ return dal_adapter_service_create_hw_ctx_dce110(ctx); -+#endif -+ default: -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+} -+ -+/* -+ * adapter_service_destruct -+ * -+ * Release memory of objects in adapter service -+ */ -+static void adapter_service_destruct( -+ struct adapter_service *as) -+{ -+ dal_adapter_service_destroy_hw_ctx(&as->hw_ctx); -+ dal_i2caux_destroy(&as->i2caux); -+ dal_bios_parser_destroy(&as->bios_parser); -+ dal_gpio_service_destroy(&as->gpio_service); -+ dal_asic_capability_destroy(&as->asic_cap); -+ dal_bios_parser_destroy_integrated_info(as->ctx, &as->integrated_info); -+} -+ -+/* -+ * adapter_service_construct -+ * -+ * Construct the derived type of adapter service -+ */ -+static bool adapter_service_construct( -+ struct adapter_service *as, -+ struct as_init_data *init_data) -+{ -+ if (!init_data) -+ return false; -+ -+ /* Create ASIC capability */ -+ as->ctx = init_data->ctx; -+ as->asic_cap = dal_asic_capability_create( -+ &init_data->hw_init_data, as->ctx); -+ -+ if (!as->asic_cap) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+#if defined(DAL_CZ_BRINGUP) -+ if (dal_adapter_service_get_dce_version(as) == DCE_VERSION_11_0) { -+ uint32_t i; -+ -+ for (i = 0; i < ARRAY_SIZE(feature_entry_table); i++) { -+ enum adapter_feature_id id = -+ feature_entry_table[i].feature_id; -+ if (id == FEATURE_MAXIMIZE_URGENCY_WATERMARKS || -+ id == FEATURE_MAXIMIZE_STUTTER_MARKS || -+ id == FEATURE_MAXIMIZE_NBP_MARKS) -+ feature_entry_table[i].default_value = true; -+ } -+ } -+#endif -+ -+ /* Generate feature set table */ -+ if (!generate_feature_set(as, init_data->display_param)) { -+ ASSERT_CRITICAL(false); -+ goto failed_to_generate_features; -+ } -+ -+ /* Create BIOS parser */ -+ init_data->bp_init_data.ctx = init_data->ctx; -+ as->bios_parser = -+ dal_bios_parser_create(&init_data->bp_init_data, as); -+ -+ if (!as->bios_parser) { -+ ASSERT_CRITICAL(false); -+ goto failed_to_create_bios_parser; -+ } -+ -+ /* Create GPIO service */ -+ as->gpio_service = -+ dal_gpio_service_create( -+ dal_adapter_service_get_dce_version(as), -+ as->ctx); -+ -+ if (!as->gpio_service) { -+ ASSERT_CRITICAL(false); -+ goto failed_to_create_gpio_service; -+ } -+ -+ /* Create I2C AUX */ -+ as->i2caux = dal_i2caux_create(as, as->ctx); -+ -+ if (!as->i2caux) { -+ ASSERT_CRITICAL(false); -+ goto failed_to_create_i2caux; -+ } -+ -+ /* Create Adapter Service HW Context*/ -+ as->hw_ctx = create_hw_ctx( -+ dal_adapter_service_get_dce_version(as), -+ as->ctx); -+ -+ if (!as->hw_ctx) { -+ ASSERT_CRITICAL(false); -+ goto failed_to_create_hw_ctx; -+ } -+ -+ /* Avoid wireless encoder creation in upstream branch. */ -+ -+ /* Integrated info is not provided on discrete ASIC. NULL is allowed */ -+ as->integrated_info = dal_bios_parser_create_integrated_info( -+ as->bios_parser); -+ -+ dal_bios_parser_post_init(as->bios_parser); -+ -+ /* Generate backlight translation table and initializes -+ other brightness properties */ -+ as->backlight_caps_initialized = false; -+ -+ get_platform_info_methods(as); -+ -+ initialize_backlight_caps(as); -+ -+ return true; -+ -+failed_to_generate_features: -+ dal_adapter_service_destroy_hw_ctx(&as->hw_ctx); -+ -+failed_to_create_hw_ctx: -+ dal_i2caux_destroy(&as->i2caux); -+ -+failed_to_create_i2caux: -+ dal_gpio_service_destroy(&as->gpio_service); -+ -+failed_to_create_gpio_service: -+ dal_bios_parser_destroy(&as->bios_parser); -+ -+failed_to_create_bios_parser: -+ dal_asic_capability_destroy(&as->asic_cap); -+ -+ return false; -+} -+ -+/* -+ * Global function definition -+ */ -+ -+/* -+ * dal_adapter_service_create -+ * -+ * Create adapter service -+ */ -+struct adapter_service *dal_adapter_service_create( -+ struct as_init_data *init_data) -+{ -+ struct adapter_service *as; -+ -+ as = dc_service_alloc(init_data->ctx, sizeof(struct adapter_service)); -+ -+ if (!as) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (adapter_service_construct(as, init_data)) -+ return as; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(init_data->ctx, as); -+ -+ return NULL; -+} -+ -+/* -+ * dal_adapter_service_destroy -+ * -+ * Destroy adapter service and objects it contains -+ */ -+void dal_adapter_service_destroy( -+ struct adapter_service **as) -+{ -+ if (!as) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ if (!*as) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ adapter_service_destruct(*as); -+ -+ dc_service_free((*as)->ctx, *as); -+ -+ *as = NULL; -+} -+ -+/* -+ * dal_adapter_service_get_dce_version -+ * -+ * Get the DCE version of current ASIC -+ */ -+enum dce_version dal_adapter_service_get_dce_version( -+ const struct adapter_service *as) -+{ -+ uint32_t version = as->asic_cap->data[ASIC_DATA_DCE_VERSION]; -+ -+ switch (version) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case 0x110: -+ return DCE_VERSION_11_0; -+#endif -+ default: -+ ASSERT_CRITICAL(false); -+ return DCE_VERSION_UNKNOWN; -+ } -+} -+ -+/* -+ * dal_adapter_service_get_controllers_num -+ * -+ * Get number of controllers -+ */ -+uint8_t dal_adapter_service_get_controllers_num( -+ struct adapter_service *as) -+{ -+ uint32_t result = as->asic_cap->data[ASIC_DATA_CONTROLLERS_NUM]; -+ -+ /* Check the "max num of controllers" feature, -+ * use it for debugging purposes only */ -+ /* TODO implement -+ * dal_adapter_service_get_feature_value(as, ) */ -+ -+ return result; -+} -+ -+ -+/** Get total number of connectors. -+ * -+ * \param as Adapter Service -+ * -+ * \return Total number of connectors. It is up-to-the caller to decide -+ * if the number is valid. -+ */ -+uint8_t dal_adapter_service_get_connectors_num( -+ struct adapter_service *as) -+{ -+ uint8_t vbios_connectors_num = 0; -+ uint8_t wireless_connectors_num = 0; -+ -+ vbios_connectors_num = dal_bios_parser_get_connectors_number( -+ as->bios_parser); -+ wireless_connectors_num = wireless_get_connectors_num(as); -+ -+ return vbios_connectors_num + wireless_connectors_num; -+} -+ -+static bool is_wireless_object(struct graphics_object_id id) -+{ -+ if ((id.type == OBJECT_TYPE_ENCODER && -+ id.id == ENCODER_ID_INTERNAL_WIRELESS) || -+ (id.type == OBJECT_TYPE_CONNECTOR && id.id == -+ CONNECTOR_ID_WIRELESS) || -+ (id.type == OBJECT_TYPE_CONNECTOR && id.id == -+ CONNECTOR_ID_MIRACAST)) -+ return true; -+ return false; -+} -+ -+/** -+ * Get the number of source objects of an object -+ * -+ * \param [in] as: Adapter Service -+ * -+ * \param [in] id: The graphics object id -+ * -+ * \return -+ * The number of the source objects of an object -+ */ -+uint32_t dal_adapter_service_get_src_num( -+ struct adapter_service *as, struct graphics_object_id id) -+{ -+ if (is_wireless_object(id)) -+ return wireless_get_srcs_num(as, id); -+ else -+ return dal_bios_parser_get_src_number(as->bios_parser, id); -+} -+ -+/** -+ * Get the source objects of an object -+ * -+ * \param [in] id The graphics object id -+ * \param [in] index Enumerating index which starts at 0 -+ * -+ * \return If enumerating successfully, return the VALID source object id, -+ * otherwise, returns "zeroed out" object id. -+ * Client should call dal_graphics_object_id_is_valid() to check -+ * weather the id is valid. -+ */ -+struct graphics_object_id dal_adapter_service_get_src_obj( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ uint32_t index) -+{ -+ struct graphics_object_id src_object_id; -+ -+ if (is_wireless_object(id)) -+ src_object_id = wireless_get_src_obj_id(as, id, index); -+ else { -+ if (BP_RESULT_OK != -+ dal_bios_parser_get_src_obj( -+ as->bios_parser, id, index, &src_object_id)) -+ src_object_id = -+ dal_graphics_object_id_init( -+ 0, -+ ENUM_ID_UNKNOWN, -+ OBJECT_TYPE_UNKNOWN); -+ } -+ -+ return src_object_id; -+} -+ -+/** Get connector object id associated with a connector index. -+ * -+ * \param as Adapter Service -+ * -+ * \param connector_index Index of connector between zero and total number -+ * returned by dal_adapter_service_get_connectors_num() -+ * -+ * \return graphics object id corresponding to the connector_index. -+ */ -+struct graphics_object_id dal_adapter_service_get_connector_obj_id( -+ struct adapter_service *as, -+ uint8_t connector_index) -+{ -+ uint8_t bios_connectors_num = -+ dal_bios_parser_get_connectors_number(as->bios_parser); -+ -+ if (connector_index >= bios_connectors_num) -+ return wireless_get_connector_id( -+ as, -+ connector_index); -+ else -+ return dal_bios_parser_get_connector_id( -+ as->bios_parser, -+ connector_index); -+} -+ -+bool dal_adapter_service_get_device_tag( -+ struct adapter_service *as, -+ struct graphics_object_id connector_object_id, -+ uint32_t device_tag_index, -+ struct connector_device_tag_info *info) -+{ -+ if (BP_RESULT_OK == dal_bios_parser_get_device_tag(as->bios_parser, -+ connector_object_id, device_tag_index, info)) -+ return true; -+ else -+ return false; -+} -+ -+/* Check if DeviceId is supported by ATOM_OBJECT_HEADER support info */ -+bool dal_adapter_service_is_device_id_supported(struct adapter_service *as, -+ struct device_id id) -+{ -+ return dal_bios_parser_is_device_id_supported(as->bios_parser, id); -+} -+ -+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as) -+{ -+ struct firmware_info fw_info; -+ enum bp_result bp_result = dal_adapter_service_get_firmware_info( -+ as, &fw_info); -+ uint32_t disp_clk_limit = -+ as->asic_cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN]; -+ if (BP_RESULT_OK == bp_result) { -+ dal_logger_write(as->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_ADAPTER_SERVICE, -+ "Read firmware is NULL"); -+ return false; -+ } -+ if (fw_info.default_display_engine_pll_frequency < disp_clk_limit) -+ return false; -+ return true; -+} -+ -+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as) -+{ -+ return as->asic_cap->caps.UNDERSCAN_FOR_HDMI_ONLY; -+} -+/* -+ * dal_adapter_service_get_clock_sources_num -+ * -+ * Get number of clock sources -+ */ -+uint8_t dal_adapter_service_get_clock_sources_num( -+ struct adapter_service *as) -+{ -+ struct firmware_info fw_info; -+ uint32_t max_clk_src = 0; -+ uint32_t num = as->asic_cap->data[ASIC_DATA_CLOCKSOURCES_NUM]; -+ -+ /* -+ * Check is system supports the use of the External clock source -+ * as a clock source for DP -+ */ -+ enum bp_result bp_result = -+ dal_bios_parser_get_firmware_info(as->bios_parser, -+ &fw_info); -+ -+ if (BP_RESULT_OK == bp_result && -+ fw_info.external_clock_source_frequency_for_dp != 0) -+ ++num; -+ -+ /* -+ * Add clock source for wireless if supported -+ */ -+ num += (uint32_t)wireless_get_clocks_num(as); -+ -+ /* Check the "max number of clock sources" feature */ -+ if (dal_adapter_service_get_feature_value( -+ FEATURE_MAX_CLOCK_SOURCE_NUM, -+ &max_clk_src, -+ sizeof(uint32_t))) -+ if ((max_clk_src != 0) && (max_clk_src < num)) -+ num = max_clk_src; -+ -+ return num; -+} -+ -+/* -+ * dal_adapter_service_get_func_controllers_num -+ * -+ * Get number of controllers -+ */ -+uint8_t dal_adapter_service_get_func_controllers_num( -+ struct adapter_service *as) -+{ -+ uint32_t result = -+ as->asic_cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM]; -+ -+ /* Check the "max num of controllers" feature, -+ * use it for debugging purposes only */ -+ -+ /* Limit number of controllers by OS */ -+ -+ struct asic_feature_flags flags; -+ -+ flags.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS]; -+ -+ if (flags.bits.LEGACY_CLIENT && -+ (result > LEGACY_MAX_NUM_OF_CONTROLLERS)) -+ result = LEGACY_MAX_NUM_OF_CONTROLLERS; -+ -+ return result; -+} -+ -+/* -+ * dal_adapter_service_is_feature_supported -+ * -+ * Return if a given feature is supported by the ASIC. The feature has to be -+ * a boolean type. -+ */ -+bool dal_adapter_service_is_feature_supported( -+ enum adapter_feature_id feature_id) -+{ -+ bool data = 0; -+ -+ dal_adapter_service_get_feature_value(feature_id, &data, sizeof(bool)); -+ -+ return data; -+} -+ -+/** -+ * Reports maximum number of confunctional non-DP displays. -+ * Value can be overriden if FEATURE_REPORT_SINGLE_SELECTED_TIMING feature is -+ * enabled. -+ * -+ * \return -+ * Maximum number of confunctional non-DP displays -+ */ -+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void) -+{ -+ uint32_t non_dp_displays = DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS; -+ -+ if (true == dal_adapter_service_get_feature_value( -+ FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, -+ &non_dp_displays, -+ sizeof(non_dp_displays))) { -+ /* the cached value exist */ -+ /* TODO: add more logic as per-DAL2 */ -+ } -+ -+ return non_dp_displays; -+} -+ -+uint32_t dal_adapter_service_get_single_selected_timing_signals(void) -+{ -+ uint32_t signals_bitmap = 0; -+ -+ if (dal_adapter_service_is_feature_supported( -+ FEATURE_REPORT_SINGLE_SELECTED_TIMING)) { -+ /* the cached value exist */ -+ /* TODO: add more logic as per-DAL2 */ -+ signals_bitmap = 0; -+ } -+ -+ return signals_bitmap; -+} -+ -+/* -+ * dal_adapter_service_get_i2c_info -+ * -+ * Get I2C information from BIOS -+ */ -+bool dal_adapter_service_get_i2c_info( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ struct graphics_object_i2c_info *i2c_info) -+{ -+ if (!i2c_info) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ return BP_RESULT_OK == -+ dal_bios_parser_get_i2c_info(as->bios_parser, id, i2c_info); -+} -+ -+/* -+ * dal_adapter_service_obtain_ddc -+ * -+ * Obtain DDC -+ */ -+struct ddc *dal_adapter_service_obtain_ddc( -+ struct adapter_service *as, -+ struct graphics_object_id id) -+{ -+ struct graphics_object_i2c_info i2c_info; -+ struct gpio_ddc_hw_info hw_info; -+ -+ -+ if (!dal_adapter_service_get_i2c_info(as, id, &i2c_info)) -+ return NULL; -+ -+ hw_info.ddc_channel = i2c_info.i2c_line; -+ hw_info.hw_supported = i2c_info.i2c_hw_assist; -+ -+ return dal_gpio_service_create_ddc( -+ as->gpio_service, -+ i2c_info.gpio_info.clk_a_register_index, -+ 1 << i2c_info.gpio_info.clk_a_shift, -+ &hw_info); -+} -+ -+/* -+ * dal_adapter_service_release_ddc -+ * -+ * Release DDC -+ */ -+void dal_adapter_service_release_ddc( -+ struct adapter_service *as, -+ struct ddc *ddc) -+{ -+ dal_gpio_service_destroy_ddc(&ddc); -+} -+ -+/* -+ * dal_adapter_service_obtain_hpd_irq -+ * -+ * Obtain HPD interrupt request -+ */ -+struct irq *dal_adapter_service_obtain_hpd_irq( -+ struct adapter_service *as, -+ struct graphics_object_id id) -+{ -+ enum bp_result bp_result; -+ -+ struct graphics_object_hpd_info hpd_info; -+ struct gpio_pin_info pin_info; -+ -+ if (!get_hpd_info(as, id, &hpd_info)) -+ return NULL; -+ -+ bp_result = dal_bios_parser_get_gpio_pin_info(as->bios_parser, -+ hpd_info.hpd_int_gpio_uid, &pin_info); -+ -+ if (bp_result != BP_RESULT_OK) { -+ ASSERT(bp_result == BP_RESULT_NORECORD); -+ return NULL; -+ } -+ -+ return dal_gpio_service_create_irq( -+ as->gpio_service, -+ pin_info.offset, -+ pin_info.mask); -+} -+ -+/* -+ * dal_adapter_service_release_irq -+ * -+ * Release interrupt request -+ */ -+void dal_adapter_service_release_irq( -+ struct adapter_service *as, -+ struct irq *irq) -+{ -+ dal_gpio_service_destroy_irq(&irq); -+} -+ -+/* -+ * dal_adapter_service_get_ss_info_num -+ * -+ * Get number of spread spectrum entries from BIOS -+ */ -+uint32_t dal_adapter_service_get_ss_info_num( -+ struct adapter_service *as, -+ enum as_signal_type signal) -+{ -+ return dal_bios_parser_get_ss_entry_number(as->bios_parser, signal); -+} -+ -+/* -+ * dal_adapter_service_get_ss_info -+ * -+ * Get spread spectrum info from BIOS -+ */ -+bool dal_adapter_service_get_ss_info( -+ struct adapter_service *as, -+ enum as_signal_type signal, -+ uint32_t idx, -+ struct spread_spectrum_info *info) -+{ -+ enum bp_result bp_result = -+ dal_bios_parser_get_spread_spectrum_info( -+ as->bios_parser, signal, idx, info); -+ -+ return BP_RESULT_OK == bp_result; -+} -+ -+/* -+ * dal_adapter_service_get_integrated_info -+ * -+ * Get integrated information on BIOS -+ */ -+bool dal_adapter_service_get_integrated_info( -+ struct adapter_service *as, -+ struct integrated_info *info) -+{ -+ if (info == NULL || as->integrated_info == NULL) -+ return false; -+ -+ dc_service_memmove(info, as->integrated_info, sizeof(struct integrated_info)); -+ -+ return true; -+} -+ -+/* -+ * dal_adapter_service_is_dfs_bypass_enabled -+ * -+ * Check if DFS bypass is enabled -+ */ -+bool dal_adapter_service_is_dfs_bypass_enabled( -+ struct adapter_service *as) -+{ -+ if (as->integrated_info == NULL) -+ return false; -+ if ((as->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) && -+ dal_adapter_service_is_feature_supported( -+ FEATURE_ENABLE_DFS_BYPASS)) -+ return true; -+ else -+ return false; -+} -+ -+/* -+ * dal_adapter_service_get_sw_i2c_speed -+ * -+ * Get SW I2C speed -+ */ -+uint32_t dal_adapter_service_get_sw_i2c_speed( -+ struct adapter_service *as) -+{ -+ /* TODO: only from ASIC caps. Feature key is not implemented*/ -+ return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ]; -+} -+ -+/* -+ * dal_adapter_service_get_hw_i2c_speed -+ * -+ * Get HW I2C speed -+ */ -+uint32_t dal_adapter_service_get_hw_i2c_speed( -+ struct adapter_service *as) -+{ -+ /* TODO: only from ASIC caps. Feature key is not implemented*/ -+ return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ]; -+} -+ -+/* -+ * dal_adapter_service_get_mc_latency -+ * -+ * Get memory controller latency -+ */ -+uint32_t dal_adapter_service_get_mc_latency( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_MC_LATENCY]; -+} -+ -+/* -+ * dal_adapter_service_get_asic_vram_bit_width -+ * -+ * Get the video RAM bit width set on the ASIC -+ */ -+uint32_t dal_adapter_service_get_asic_vram_bit_width( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_VRAM_BITWIDTH]; -+} -+ -+/* -+ * dal_adapter_service_get_asic_bugs -+ * -+ * Get the bug flags set on this ASIC -+ */ -+struct asic_bugs dal_adapter_service_get_asic_bugs( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->bugs; -+} -+ -+ -+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->runtime_flags; -+} -+ -+/* -+ * dal_adapter_service_get_line_buffer_size -+ * -+ * Get line buffer size -+ */ -+uint32_t dal_adapter_service_get_line_buffer_size( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_LINEBUFFER_SIZE]; -+} -+ -+/* -+ * dal_adapter_service_get_bandwidth_tuning_params -+ * -+ * Get parameters for bandwidth tuning -+ */ -+bool dal_adapter_service_get_bandwidth_tuning_params( -+ struct adapter_service *as, -+ union bandwidth_tuning_params *params) -+{ -+ /* TODO: add implementation */ -+ /* note: data comes from runtime parameters */ -+ return false; -+} -+ -+/* -+ * dal_adapter_service_get_feature_flags -+ * -+ * Get a copy of ASIC feature flags -+ */ -+struct asic_feature_flags dal_adapter_service_get_feature_flags( -+ struct adapter_service *as) -+{ -+ struct asic_feature_flags result = { { 0 } }; -+ -+ if (!as) { -+ ASSERT_CRITICAL(false); -+ return result; -+ } -+ -+ result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS]; -+ -+ return result; -+} -+ -+/* -+ * dal_adapter_service_get_dram_bandwidth_efficiency -+ * -+ * Get efficiency of DRAM -+ */ -+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY]; -+} -+ -+/* -+ * dal_adapter_service_obtain_gpio -+ * -+ * Obtain GPIO -+ */ -+struct gpio *dal_adapter_service_obtain_gpio( -+ struct adapter_service *as, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ return dal_gpio_service_create_gpio_ex( -+ as->gpio_service, id, en, -+ GPIO_PIN_OUTPUT_STATE_DEFAULT); -+} -+ -+/* -+ * dal_adapter_service_obtain_stereo_gpio -+ * -+ * Obtain GPIO for stereo3D -+ */ -+struct gpio *dal_adapter_service_obtain_stereo_gpio( -+ struct adapter_service *as) -+{ -+ const bool have_param_stereo_gpio = false; -+ -+ struct asic_feature_flags result; -+ -+ result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS]; -+ -+ /* Case 1 : Workstation stereo */ -+ if (result.bits.WORKSTATION_STEREO) -+ /* "active low" <--> "default 3d right eye polarity" = false */ -+ return dal_gpio_service_create_gpio_ex( -+ as->gpio_service, GPIO_ID_GENERIC, GPIO_GENERIC_A, -+ GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW); -+ /* Case 2 : runtime parameter override for sideband stereo */ -+ else if (have_param_stereo_gpio) { -+ /* TODO implement */ -+ return NULL; -+ /* Case 3 : VBIOS gives us GPIO for sideband stereo */ -+ } else { -+ const struct graphics_object_id id = -+ dal_graphics_object_id_init( -+ GENERIC_ID_STEREO, -+ ENUM_ID_1, -+ OBJECT_TYPE_GENERIC); -+ -+ struct bp_gpio_cntl_info cntl_info; -+ struct gpio_pin_info pin_info; -+ -+ /* Get GPIO record for this object. -+ * Stereo GPIO record should have exactly one entry -+ * where active state defines stereosync polarity */ -+ if (1 != dal_bios_parser_get_gpio_record( -+ as->bios_parser, id, &cntl_info, 1)) { -+ return NULL; -+ } else if (BP_RESULT_OK != dal_bios_parser_get_gpio_pin_info( -+ as->bios_parser, cntl_info.id, &pin_info)) { -+ /*ASSERT_CRITICAL(false);*/ -+ return NULL; -+ } else -+ return dal_gpio_service_create_gpio_ex( -+ as->gpio_service, -+ pin_info.offset, pin_info.mask, -+ cntl_info.state); -+ } -+} -+ -+/* -+ * dal_adapter_service_release_gpio -+ * -+ * Release GPIO -+ */ -+void dal_adapter_service_release_gpio( -+ struct adapter_service *as, -+ struct gpio *gpio) -+{ -+ dal_gpio_service_destroy_gpio(&gpio); -+} -+ -+/* -+ * dal_adapter_service_get_firmware_info -+ * -+ * Get firmware information from BIOS -+ */ -+bool dal_adapter_service_get_firmware_info( -+ struct adapter_service *as, -+ struct firmware_info *info) -+{ -+ return dal_bios_parser_get_firmware_info(as->bios_parser, info) == -+ BP_RESULT_OK; -+} -+ -+/* -+ * dal_adapter_service_get_audio_support -+ * -+ * Get information on audio support -+ */ -+union audio_support dal_adapter_service_get_audio_support( -+ struct adapter_service *as) -+{ -+ return dal_adapter_service_hw_ctx_get_audio_support(as->hw_ctx); -+} -+ -+/* -+ * dal_adapter_service_get_stream_engines_num -+ * -+ * Get number of stream engines -+ */ -+uint8_t dal_adapter_service_get_stream_engines_num( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_DIGFE_NUM]; -+} -+ -+/* -+ * dal_adapter_service_get_feature_value -+ * -+ * Get the cached value of a given feature. This value can be a boolean, int, -+ * or characters. -+ */ -+bool dal_adapter_service_get_feature_value( -+ const enum adapter_feature_id feature_id, -+ void *data, -+ uint32_t size) -+{ -+ uint32_t entry_idx = 0; -+ uint32_t set_idx = 0; -+ uint32_t set_internal_idx = 0; -+ -+ if (feature_id >= FEATURE_MAXIMUM || feature_id <= FEATURE_UNKNOWN) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (data == NULL) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ entry_idx = lookup_feature_entry(feature_id); -+ set_idx = (uint32_t)((feature_id - 1)/32); -+ set_internal_idx = (uint32_t)((feature_id - 1) % 32); -+ -+ if (entry_idx >= get_feature_entries_num()) { -+ /* Cannot find this entry */ -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (feature_entry_table[entry_idx].is_boolean_type) { -+ if (size != sizeof(bool)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ *(bool *)data = get_bool_value(adapter_feature_set[set_idx], -+ set_internal_idx); -+ } else { -+ if (size != sizeof(uint32_t)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ *(uint32_t *)data = adapter_feature_set[set_idx]; -+ } -+ -+ return true; -+} -+ -+/* -+ * dal_adapter_service_get_memory_type_multiplier -+ * -+ * Get multiplier for the memory type -+ */ -+uint32_t dal_adapter_service_get_memory_type_multiplier( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER]; -+} -+ -+/* -+ * dal_adapter_service_get_bios_parser -+ * -+ * Get BIOS parser handler -+ */ -+struct bios_parser *dal_adapter_service_get_bios_parser( -+ struct adapter_service *as) -+{ -+ return as->bios_parser; -+} -+ -+/* -+ * dal_adapter_service_get_i2caux -+ * -+ * Get i2c aux handler -+ */ -+struct i2caux *dal_adapter_service_get_i2caux( -+ struct adapter_service *as) -+{ -+ return as->i2caux; -+} -+ -+bool dal_adapter_service_initialize_hw_data( -+ struct adapter_service *as) -+{ -+ return as->hw_ctx->funcs->power_up(as->hw_ctx); -+} -+ -+struct graphics_object_id dal_adapter_service_enum_fake_path_resource( -+ struct adapter_service *as, -+ uint32_t index) -+{ -+ return as->hw_ctx->funcs->enum_fake_path_resource(as->hw_ctx, index); -+} -+ -+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object( -+ struct adapter_service *as, -+ uint32_t index) -+{ -+ return as->hw_ctx->funcs->enum_stereo_sync_object(as->hw_ctx, index); -+} -+ -+struct graphics_object_id dal_adapter_service_enum_sync_output_object( -+ struct adapter_service *as, -+ uint32_t index) -+{ -+ return as->hw_ctx->funcs->enum_sync_output_object(as->hw_ctx, index); -+} -+ -+struct graphics_object_id dal_adapter_service_enum_audio_object( -+ struct adapter_service *as, -+ uint32_t index) -+{ -+ return as->hw_ctx->funcs->enum_audio_object(as->hw_ctx, index); -+} -+ -+ -+void dal_adapter_service_update_audio_connectivity( -+ struct adapter_service *as, -+ uint32_t number_of_audio_capable_display_path) -+{ -+ as->hw_ctx->funcs->update_audio_connectivity( -+ as->hw_ctx, -+ number_of_audio_capable_display_path, -+ dal_adapter_service_get_controllers_num(as)); -+} -+ -+bool dal_adapter_service_has_embedded_display_connector( -+ struct adapter_service *as) -+{ -+ uint8_t index; -+ uint8_t num_connectors = dal_adapter_service_get_connectors_num(as); -+ -+ if (num_connectors == 0 || num_connectors > ENUM_ID_COUNT) -+ return false; -+ -+ for (index = 0; index < num_connectors; index++) { -+ struct graphics_object_id obj_id = -+ dal_adapter_service_get_connector_obj_id(as, index); -+ enum connector_id connector_id = -+ dal_graphics_object_id_get_connector_id(obj_id); -+ -+ if ((connector_id == CONNECTOR_ID_LVDS) || -+ (connector_id == CONNECTOR_ID_EDP)) -+ return true; -+ } -+ -+ return false; -+} -+ -+bool dal_adapter_service_get_embedded_panel_info( -+ struct adapter_service *as, -+ struct embedded_panel_info *info) -+{ -+ enum bp_result result; -+ -+ if (info == NULL) -+ /*TODO: add DALASSERT_MSG here*/ -+ return false; -+ -+ result = dal_bios_parser_get_embedded_panel_info( -+ as->bios_parser, info); -+ -+ return result == BP_RESULT_OK; -+} -+ -+bool dal_adapter_service_enum_embedded_panel_patch_mode( -+ struct adapter_service *as, -+ uint32_t index, -+ struct embedded_panel_patch_mode *mode) -+{ -+ enum bp_result result; -+ -+ if (mode == NULL) -+ /*TODO: add DALASSERT_MSG here*/ -+ return false; -+ -+ result = dal_bios_parser_enum_embedded_panel_patch_mode( -+ as->bios_parser, index, mode); -+ -+ return result == BP_RESULT_OK; -+} -+ -+bool dal_adapter_service_get_faked_edid_len( -+ struct adapter_service *as, -+ uint32_t *len) -+{ -+ enum bp_result result; -+ -+ result = dal_bios_parser_get_faked_edid_len( -+ as->bios_parser, -+ len); -+ return result == BP_RESULT_OK; -+} -+ -+bool dal_adapter_service_get_faked_edid_buf( -+ struct adapter_service *as, -+ uint8_t *buf, -+ uint32_t len) -+{ -+ enum bp_result result; -+ -+ result = dal_bios_parser_get_faked_edid_buf( -+ as->bios_parser, -+ buf, -+ len); -+ return result == BP_RESULT_OK; -+ -+} -+ -+/* -+ * dal_adapter_service_is_fusion -+ * -+ * Is this Fusion ASIC -+ */ -+bool dal_adapter_service_is_fusion(struct adapter_service *as) -+{ -+ return as->asic_cap->caps.IS_FUSION; -+} -+ -+/* -+ * dal_adapter_service_is_dfsbyass_dynamic -+ * -+ * -+ **/ -+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as) -+{ -+ return as->asic_cap->caps.DFSBYPASS_DYNAMIC_SUPPORT; -+} -+ -+/* -+ * dal_adapter_service_should_optimize -+ * -+ * @brief Reports whether driver settings allow requested optimization -+ * -+ * @param -+ * as: adapter service handler -+ * feature: for which optimization is validated -+ * -+ * @return -+ * true if requested feature can be optimized -+ */ -+bool dal_adapter_service_should_optimize( -+ struct adapter_service *as, enum optimization_feature feature) -+{ -+ uint32_t supported_optimization = 0; -+ struct dal_asic_runtime_flags flags; -+ -+ if (!dal_adapter_service_get_feature_value(FEATURE_OPTIMIZATION, -+ &supported_optimization, sizeof(uint32_t))) -+ return false; -+ -+ /* Retrieve ASIC runtime flags */ -+ flags = dal_adapter_service_get_asic_runtime_flags(as); -+ -+ /* Check runtime flags against different optimization features */ -+ switch (feature) { -+ case OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY: -+ if (!flags.flags.bits.OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT) -+ return false; -+ break; -+ -+ case OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME: -+ if (as->integrated_info == NULL || -+ !flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME) -+ return false; -+ break; -+ case OF_SKIP_POWER_DOWN_INACTIVE_ENCODER: -+ if (!dal_adapter_service_get_asic_runtime_flags(as).flags.bits. -+ SKIP_POWER_DOWN_ON_RESUME) -+ return false; -+ break; -+ default: -+ break; -+ } -+ -+ return (supported_optimization & feature) != 0; -+} -+ -+/* -+ * dal_adapter_service_is_in_accelerated_mode -+ * -+ * @brief Determine if driver is in accelerated mode -+ * -+ * @param -+ * as: Adapter Service handler -+ * -+ * @out -+ * True if driver is in accelerated mode, false otherwise. -+ */ -+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as) -+{ -+ return dal_bios_parser_is_accelerated_mode(as->bios_parser); -+} -+ -+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info( -+ struct adapter_service *as, -+ struct graphics_object_i2c_info *info) -+{ -+ struct gpio_ddc_hw_info hw_info = { -+ info->i2c_hw_assist, -+ info->i2c_line }; -+ return dal_gpio_service_create_ddc(as->gpio_service, -+ info->gpio_info.clk_a_register_index, -+ (1 << info->gpio_info.clk_a_shift), &hw_info); -+} -+ -+struct bdf_info dal_adapter_service_get_adapter_info(struct adapter_service *as) -+{ -+ return as->bdf_info; -+} -+ -+/* -+ * dal_adapter_service_should_psr_skip_wait_for_pll_lock -+ * -+ * @brief Determine if this ASIC needs to wait on PLL lock bit -+ * -+ * @param -+ * as: Adapter Service handle -+ * -+ * @out -+ * True if ASIC does not need to wait for PLL lock bit, i.e. skip the wait. -+ */ -+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->caps.SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT; -+} -+ -+bool dal_adapter_service_is_lid_open(struct adapter_service *as) -+{ -+ bool is_lid_open = false; -+ struct platform_info_params params; -+ -+ params.data = &is_lid_open; -+ params.method = PM_GET_LID_STATE; -+ -+ if ((PM_GET_LID_STATE & as->platform_methods_mask) && -+ dal_get_platform_info(as->ctx, ¶ms)) -+ return is_lid_open; -+ -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ return dal_bios_parser_is_lid_open(as->bios_parser); -+#else -+ return false; -+#endif -+} -+ -+bool dal_adapter_service_get_panel_backlight_default_levels( -+ struct adapter_service *as, -+ struct panel_backlight_levels *levels) -+{ -+ if (!as->backlight_caps_initialized) -+ return false; -+ -+ levels->ac_level_percentage = as->ac_level_percentage; -+ levels->dc_level_percentage = as->dc_level_percentage; -+ return true; -+} -+ -+bool dal_adapter_service_get_panel_backlight_boundaries( -+ struct adapter_service *as, -+ struct panel_backlight_boundaries *boundaries) -+{ -+ if (!as->backlight_caps_initialized) -+ return false; -+ if (boundaries != NULL) { -+ boundaries->min_signal_level = as->backlight_8bit_lut[0]; -+ boundaries->max_signal_level = -+ as->backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT - 1]; -+ return true; -+ } -+ return false; -+} -+ -+ -+uint32_t dal_adapter_service_get_view_port_pixel_granularity( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY]; -+} -+ -+/** -+ * Get number of paths per DP 1.2 connector from the runtime parameter if it -+ * exists. -+ * A check to see if MST is supported for the generation of ASIC is done -+ * -+ * \return -+ * Number of paths per DP 1.2 connector is exists in runtime parameters -+ * or ASIC cap -+ */ -+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector( -+ struct adapter_service *as) -+{ -+ if (as->asic_cap->caps.DP_MST_SUPPORTED == 0) { -+ /* ASIC doesn't support DP MST at all */ -+ return 0; -+ } -+ -+ return as->asic_cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR]; -+} -+ -+uint32_t dal_adapter_service_get_num_of_underlays( -+ struct adapter_service *as) -+{ -+ return as->asic_cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES]; -+} -+ -+bool dal_adapter_service_get_encoder_cap_info( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ struct graphics_object_encoder_cap_info *info) -+{ -+ struct bp_encoder_cap_info bp_cap_info = {0}; -+ enum bp_result result; -+ -+ if (NULL == info) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ /* -+ * Retrieve Encoder Capability Information from VBIOS and store the -+ * call result (success or fail) -+ * Info from VBIOS about HBR2 has two fields: -+ * -+ * - dpHbr2Cap: indicates supported/not supported by HW Encoder -+ * - dpHbr2En : indicates DP spec compliant/not compliant -+ */ -+ result = dal_bios_parser_get_encoder_cap_info( -+ as->bios_parser, -+ id, -+ &bp_cap_info); -+ -+ /* Set dp_hbr2_validated flag (it's equal to Enable) */ -+ info->dp_hbr2_validated = bp_cap_info.DP_HBR2_EN; -+ -+ if (result == BP_RESULT_OK) { -+ info->dp_hbr2_cap = bp_cap_info.DP_HBR2_CAP; -+ return true; -+ } -+ -+ return false; -+} -+ -+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as) -+{ -+ return as->asic_cap->caps.NEED_MC_TUNING ? true : false; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h -new file mode 100644 -index 0000000..25ac648 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.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_ADAPTER_SERVICE_H__ -+#define __DAL_ADAPTER_SERVICE_H__ -+ -+/* Include */ -+#include "include/adapter_service_interface.h" -+#include "wireless_data_source.h" -+ -+/* -+ * Forward declaration -+ */ -+struct gpio_service; -+struct asic_cap; -+ -+/* Adapter service */ -+struct adapter_service { -+ struct dc_context *ctx; -+ struct asic_capability *asic_cap; -+ struct bios_parser *bios_parser; -+ struct gpio_service *gpio_service; -+ struct i2caux *i2caux; -+ struct wireless_data wireless_data; -+ struct hw_ctx_adapter_service *hw_ctx; -+ struct integrated_info *integrated_info; -+ struct bdf_info bdf_info; -+ uint32_t platform_methods_mask; -+ uint32_t ac_level_percentage; -+ uint32_t dc_level_percentage; -+ uint32_t backlight_caps_initialized; -+ uint32_t backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT]; -+}; -+ -+/* Type of feature with its runtime parameter and default value */ -+struct feature_source_entry { -+ enum adapter_feature_id feature_id; -+ uint32_t default_value; -+ bool is_boolean_type; -+}; -+ -+/* Stores entire ASIC features by sets */ -+extern uint32_t adapter_feature_set[]; -+ -+#endif /* __DAL_ADAPTER_SERVICE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c -new file mode 100644 -index 0000000..31c2aab ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.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 "dal_services.h" -+#include "../hw_ctx_adapter_service.h" -+ -+#include "hw_ctx_adapter_service_dce110.h" -+ -+#include "include/logger_interface.h" -+#include "include/grph_object_id.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#ifndef mmCC_DC_HDMI_STRAPS -+#define mmCC_DC_HDMI_STRAPS 0x4819 -+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -+#endif -+ -+static const struct graphics_object_id invalid_go = { -+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN, 0 -+}; -+ -+/* Macro */ -+#define AUDIO_STRAPS_HDMI_ENABLE 0x2 -+ -+#define FROM_HW_CTX(ptr) \ -+ container_of((ptr), struct hw_ctx_adapter_service_dce110, base) -+ -+static const uint32_t audio_index_reg_offset[] = { -+ /*CZ has 3 DIGs but 4 audio endpoints*/ -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX -+}; -+ -+static const uint32_t audio_data_reg_offset[] = { -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA, -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA, -+}; -+ -+enum { -+ MAX_NUMBER_OF_AUDIO_PINS = 4 -+}; -+ -+static void destruct( -+ struct hw_ctx_adapter_service_dce110 *hw_ctx) -+{ -+ /* There is nothing to destruct at the moment */ -+ dal_adapter_service_destruct_hw_ctx(&hw_ctx->base); -+} -+ -+static void destroy( -+ struct hw_ctx_adapter_service *ptr) -+{ -+ struct hw_ctx_adapter_service_dce110 *hw_ctx = -+ FROM_HW_CTX(ptr); -+ -+ destruct(hw_ctx); -+ -+ dc_service_free(ptr->ctx, hw_ctx); -+} -+ -+/* -+ * enum_audio_object -+ * -+ * @brief enumerate audio object -+ * -+ * @param -+ * const struct hw_ctx_adapter_service *hw_ctx - [in] provides num of endpoints -+ * uint32_t index - [in] audio index -+ * -+ * @return -+ * grphic object id -+ */ -+static struct graphics_object_id enum_audio_object( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ uint32_t number_of_connected_audio_endpoints = -+ FROM_HW_CTX(hw_ctx)->number_of_connected_audio_endpoints; -+ -+ if (index >= number_of_connected_audio_endpoints || -+ number_of_connected_audio_endpoints == 0) -+ return invalid_go; -+ else -+ return dal_graphics_object_id_init( -+ AUDIO_ID_INTERNAL_AZALIA, -+ (enum object_enum_id)(index + 1), -+ OBJECT_TYPE_AUDIO); -+} -+ -+static uint32_t get_number_of_connected_audio_endpoints_multistream( -+ struct dc_context *ctx) -+{ -+ uint32_t num_connected_audio_endpoints = 0; -+ uint32_t i; -+ uint32_t default_config = -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT; -+ -+ /* find the total number of streams available via the -+ * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT -+ * registers (one for each pin) starting from pin 1 -+ * up to the max number of audio pins. -+ * We stop on the first pin where -+ * PORT_CONNECTIVITY == 1 (as instructed by HW team). -+ */ -+ for (i = 0; i < MAX_NUMBER_OF_AUDIO_PINS; i++) { -+ uint32_t value = 0; -+ -+ set_reg_field_value(value, -+ default_config, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dal_write_reg(ctx, audio_index_reg_offset[i], value); -+ -+ value = 0; -+ value = dal_read_reg(ctx, audio_data_reg_offset[i]); -+ -+ /* 1 means not supported*/ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT, -+ PORT_CONNECTIVITY) == 1) -+ break; -+ -+ num_connected_audio_endpoints++; -+ } -+ -+ return num_connected_audio_endpoints; -+ -+} -+ -+/* -+ * get_number_of_connected_audio_endpoints -+ */ -+static uint32_t get_number_of_connected_audio_endpoints( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ uint32_t addr = mmCC_DC_HDMI_STRAPS; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED) -+ /* audio straps indicate no audio supported */ -+ return 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ field = get_reg_field_value( -+ value, CC_DC_HDMI_STRAPS, AUDIO_STREAM_NUMBER); -+ if (field == 1) -+ /* multi streams not supported */ -+ return 1; -+ else if (field == 0) -+ /* multi streams supported */ -+ return get_number_of_connected_audio_endpoints_multistream( -+ hw_ctx->ctx); -+ -+ /* unexpected value */ -+ ASSERT_CRITICAL(false); -+ return field; -+} -+ -+ -+/* -+ * power_up -+ * -+ * @brief -+ * Determine and cache audio support from register. -+ * -+ * @param -+ * struct hw_ctx_adapter_service *hw_ctx - [in] adapter service hw context -+ * -+ * @return -+ * true if succeed, false otherwise -+ */ -+static bool power_up( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ struct hw_ctx_adapter_service_dce110 *hw_ctx_dce11 = -+ FROM_HW_CTX(hw_ctx); -+ /* Allow DP audio all the time -+ * without additional pinstrap check on Fusion */ -+ -+ -+ { -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, mmCC_DC_HDMI_STRAPS); -+ field = get_reg_field_value( -+ value, CC_DC_HDMI_STRAPS, HDMI_DISABLE); -+ -+ if (field == 0) { -+ hw_ctx->cached_audio_straps = AUDIO_STRAPS_DP_HDMI_AUDIO; -+ } else { -+ value = dal_read_reg( -+ hw_ctx->ctx, mmDC_PINSTRAPS); -+ field = get_reg_field_value( -+ value, -+ DC_PINSTRAPS, -+ DC_PINSTRAPS_AUDIO); -+ -+ if (field & AUDIO_STRAPS_HDMI_ENABLE) -+ hw_ctx->cached_audio_straps = -+ AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE; -+ else -+ hw_ctx->cached_audio_straps = -+ AUDIO_STRAPS_DP_AUDIO_ALLOWED; -+ } -+ -+ } -+ -+ /* get the number of connected audio endpoints */ -+ hw_ctx_dce11->number_of_connected_audio_endpoints = -+ get_number_of_connected_audio_endpoints(hw_ctx); -+ -+ return true; -+} -+ -+static void update_audio_connectivity( -+ struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t number_of_audio_capable_display_path, -+ uint32_t number_of_controllers) -+{ -+ /* this one should be empty on DCE110 */ -+} -+ -+static const struct hw_ctx_adapter_service_funcs funcs = { -+ .destroy = destroy, -+ .power_up = power_up, -+ .enum_fake_path_resource = NULL, -+ .enum_stereo_sync_object = NULL, -+ .enum_sync_output_object = NULL, -+ .enum_audio_object = enum_audio_object, -+ .update_audio_connectivity = update_audio_connectivity -+}; -+ -+static bool construct( -+ struct hw_ctx_adapter_service_dce110 *hw_ctx, -+ struct dc_context *ctx) -+{ -+ if (!dal_adapter_service_construct_hw_ctx(&hw_ctx->base, ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ hw_ctx->base.funcs = &funcs; -+ hw_ctx->number_of_connected_audio_endpoints = 0; -+ -+ return true; -+} -+ -+struct hw_ctx_adapter_service * -+ dal_adapter_service_create_hw_ctx_dce110( -+ struct dc_context *ctx) -+{ -+ struct hw_ctx_adapter_service_dce110 *hw_ctx = -+ dc_service_alloc(ctx, sizeof(struct hw_ctx_adapter_service_dce110)); -+ -+ if (!hw_ctx) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(hw_ctx, ctx)) -+ return &hw_ctx->base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(ctx, hw_ctx); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h -new file mode 100644 -index 0000000..092b671 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h -@@ -0,0 +1,40 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ -+#define __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ -+ -+struct hw_ctx_adapter_service_dce110 { -+ struct hw_ctx_adapter_service base; -+ uint32_t number_of_connected_audio_endpoints; -+}; -+ -+struct hw_ctx_adapter_service * -+ dal_adapter_service_create_hw_ctx_dce110( -+ struct dc_context *ctx); -+ -+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ */ -+ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c -new file mode 100644 -index 0000000..5fa886f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c -@@ -0,0 +1,164 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/adapter_service_types.h" -+#include "include/grph_object_id.h" -+#include "hw_ctx_adapter_service.h" -+ -+static const struct graphics_object_id invalid_go = { -+ 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN -+}; -+ -+static void destroy( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ /* Attention! -+ * You must override impl method in derived class */ -+ BREAK_TO_DEBUGGER(); -+} -+ -+static bool power_up( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ /* Attention! -+ * You must override impl method in derived class */ -+ BREAK_TO_DEBUGGER(); -+ -+ return false; -+} -+ -+static struct graphics_object_id enum_fake_path_resource( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ return invalid_go; -+} -+ -+static struct graphics_object_id enum_stereo_sync_object( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ return invalid_go; -+} -+ -+static struct graphics_object_id enum_sync_output_object( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ return invalid_go; -+} -+ -+static struct graphics_object_id enum_audio_object( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index) -+{ -+ /* by default, we only allow one audio */ -+ -+ if (index > 0) -+ return invalid_go; -+ else if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED) -+ return invalid_go; -+ else -+ return dal_graphics_object_id_init( -+ AUDIO_ID_INTERNAL_AZALIA, -+ ENUM_ID_1, -+ OBJECT_TYPE_AUDIO); -+} -+ -+static void update_audio_connectivity( -+ struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t number_of_audio_capable_display_path, -+ uint32_t number_of_controllers) -+{ -+ /* Attention! -+ * You must override impl method in derived class */ -+ BREAK_TO_DEBUGGER(); -+} -+ -+static const struct hw_ctx_adapter_service_funcs funcs = { -+ destroy, -+ power_up, -+ enum_fake_path_resource, -+ enum_stereo_sync_object, -+ enum_sync_output_object, -+ enum_audio_object, -+ update_audio_connectivity -+}; -+ -+bool dal_adapter_service_construct_hw_ctx( -+ struct hw_ctx_adapter_service *hw_ctx, -+ struct dc_context *ctx) -+{ -+ -+ hw_ctx->ctx = ctx; -+ hw_ctx->funcs = &funcs; -+ hw_ctx->cached_audio_straps = AUDIO_STRAPS_NOT_ALLOWED; -+ -+ return true; -+} -+ -+union audio_support dal_adapter_service_hw_ctx_get_audio_support( -+ const struct hw_ctx_adapter_service *hw_ctx) -+{ -+ union audio_support result; -+ -+ result.raw = 0; -+ -+ switch (hw_ctx->cached_audio_straps) { -+ case AUDIO_STRAPS_DP_HDMI_AUDIO: -+ result.bits.HDMI_AUDIO_NATIVE = true; -+ /* do not break ! */ -+ case AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE: -+ result.bits.HDMI_AUDIO_ON_DONGLE = true; -+ /* do not break ! */ -+ case AUDIO_STRAPS_DP_AUDIO_ALLOWED: -+ result.bits.DP_AUDIO = true; -+ break; -+ default: -+ break; -+ } -+ -+ return result; -+} -+ -+void dal_adapter_service_destruct_hw_ctx( -+ struct hw_ctx_adapter_service *hw_ctx) -+{ -+ /* There is nothing to destruct at the moment */ -+} -+ -+void dal_adapter_service_destroy_hw_ctx( -+ struct hw_ctx_adapter_service **ptr) -+{ -+ if (!ptr || !*ptr) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ (*ptr)->funcs->destroy(*ptr); -+ -+ *ptr = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h -new file mode 100644 -index 0000000..f98c2d4 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h -@@ -0,0 +1,86 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_H__ -+#define __DAL_HW_CTX_ADAPTER_SERVICE_H__ -+ -+enum audio_straps { -+ AUDIO_STRAPS_NOT_ALLOWED = 0, -+ AUDIO_STRAPS_DP_AUDIO_ALLOWED, -+ AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE, -+ AUDIO_STRAPS_DP_HDMI_AUDIO -+}; -+ -+struct hw_ctx_adapter_service; -+ -+struct hw_ctx_adapter_service_funcs { -+ void (*destroy)( -+ struct hw_ctx_adapter_service *hw_ctx); -+ /* Initializes relevant HW registers -+ * and caches relevant data from HW registers */ -+ bool (*power_up)( -+ struct hw_ctx_adapter_service *hw_ctx); -+ /* Enumerate fake path resources */ -+ struct graphics_object_id (*enum_fake_path_resource)( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index); -+ /* Enumerate stereo sync objects */ -+ struct graphics_object_id (*enum_stereo_sync_object)( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index); -+ /* Enumerate (H/V) sync output objects */ -+ struct graphics_object_id (*enum_sync_output_object)( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index); -+ /* Enumerate audio objects */ -+ struct graphics_object_id (*enum_audio_object)( -+ const struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t index); -+ void (*update_audio_connectivity)( -+ struct hw_ctx_adapter_service *hw_ctx, -+ uint32_t number_of_audio_capable_display_path, -+ uint32_t number_of_controllers); -+}; -+ -+struct hw_ctx_adapter_service { -+ struct dc_context *ctx; -+ const struct hw_ctx_adapter_service_funcs *funcs; -+ enum audio_straps cached_audio_straps; -+}; -+ -+bool dal_adapter_service_construct_hw_ctx( -+ struct hw_ctx_adapter_service *hw_ctx, -+ struct dc_context *ctx); -+ -+union audio_support dal_adapter_service_hw_ctx_get_audio_support( -+ const struct hw_ctx_adapter_service *hw_ctx); -+ -+void dal_adapter_service_destruct_hw_ctx( -+ struct hw_ctx_adapter_service *hw_ctx); -+ -+void dal_adapter_service_destroy_hw_ctx( -+ struct hw_ctx_adapter_service **ptr); -+ -+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c -new file mode 100644 -index 0000000..dcb885d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c -@@ -0,0 +1,209 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+ -+#include "dal_services.h" -+#include "adapter_service.h" -+#include "wireless_data_source.h" -+ -+#include "atom.h" -+ -+/*construct wireless data*/ -+bool wireless_data_init(struct wireless_data *data, -+ struct bios_parser *bp, -+ struct wireless_init_data *init_data) -+{ -+ struct firmware_info info; -+ -+ if (data == NULL || bp == NULL || init_data == NULL) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ data->miracast_connector_enable = false; -+ data->wireless_disp_path_enable = false; -+ data->wireless_enable = false; -+ -+ /* Wireless it not supported if VCE is not supported */ -+ if (!init_data->vce_supported) -+ return true; -+ -+ if (init_data->miracast_target_required) -+ data->miracast_connector_enable = true; -+ -+ /* -+ * If override is in place for platform support, we will both -+ * enable wireless display as a feature (i.e. CCC aspect) and -+ * enable the wireless display path without any further checks. -+ */ -+ if (init_data->platform_override) { -+ data->wireless_enable = true; -+ data->wireless_disp_path_enable = true; -+ } else { -+ /* -+ * Check if SBIOS sets remote display enable, exposed -+ * through VBIOS. This is only valid for APU, not dGPU -+ */ -+ dal_bios_parser_get_firmware_info(bp, &info); -+ -+ if ((REMOTE_DISPLAY_ENABLE == -+ info.remote_display_config) && -+ init_data->fusion) { -+ data->wireless_enable = true; -+ data->wireless_disp_path_enable = true; -+ } -+ } -+ -+ /* -+ * If remote display path override is enabled, we enable just the -+ * remote display path. This is mainly used for testing purposes -+ */ -+ if (init_data->remote_disp_path_override) -+ data->wireless_disp_path_enable = true; -+ -+ return true; -+} -+ -+uint8_t wireless_get_clocks_num( -+ struct adapter_service *as) -+{ -+ if (as->wireless_data.wireless_enable || -+ as->wireless_data.wireless_disp_path_enable) -+ return 1; -+ else -+ return 0; -+} -+ -+static uint8_t wireless_get_encoders_num( -+ struct adapter_service *as) -+{ -+ if (as->wireless_data.wireless_enable || -+ as->wireless_data.wireless_disp_path_enable) -+ return 1; -+ else -+ return 0; -+} -+ -+uint8_t wireless_get_connectors_num( -+ struct adapter_service *as) -+{ -+ uint8_t wireless_connectors_num = 0; -+ -+ if (as->wireless_data.wireless_enable && -+ as->wireless_data.miracast_connector_enable) -+ wireless_connectors_num++; -+ -+ if (as->wireless_data.wireless_disp_path_enable) -+ wireless_connectors_num++; -+ -+ return wireless_connectors_num; -+} -+ -+struct graphics_object_id wireless_get_connector_id( -+ struct adapter_service *as, -+ uint8_t index) -+{ -+ struct graphics_object_id unknown_object_id = -+ dal_graphics_object_id_init( -+ 0, -+ ENUM_ID_UNKNOWN, -+ OBJECT_TYPE_UNKNOWN); -+ -+ if (!as->wireless_data.wireless_enable && -+ !as->wireless_data.wireless_disp_path_enable) -+ return unknown_object_id; -+ -+ else if (!as->wireless_data.miracast_connector_enable) -+ return dal_graphics_object_id_init( -+ CONNECTOR_ID_WIRELESS, -+ ENUM_ID_1, -+ OBJECT_TYPE_CONNECTOR); -+ -+ switch (index) { -+ case 0: -+ return dal_graphics_object_id_init( -+ CONNECTOR_ID_WIRELESS, -+ ENUM_ID_1, -+ OBJECT_TYPE_CONNECTOR); -+ break; -+ case 1: -+ return dal_graphics_object_id_init( -+ CONNECTOR_ID_MIRACAST, -+ ENUM_ID_1, -+ OBJECT_TYPE_CONNECTOR); -+ break; -+ default: -+ return unknown_object_id; -+ } -+} -+ -+uint8_t wireless_get_srcs_num( -+ struct adapter_service *as, -+ struct graphics_object_id id) -+{ -+ switch (id.type) { -+ case OBJECT_TYPE_CONNECTOR: -+ return wireless_get_encoders_num(as); -+ case OBJECT_TYPE_ENCODER: -+ return 1; -+ -+ default: -+ ASSERT_CRITICAL(false); -+ break; -+ } -+ -+ return 0; -+} -+ -+struct graphics_object_id wireless_get_src_obj_id( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ uint8_t index) -+{ -+ if (index < wireless_get_srcs_num(as, id)) { -+ switch (id.type) { -+ case OBJECT_TYPE_CONNECTOR: -+ return dal_graphics_object_id_init( -+ ENCODER_ID_INTERNAL_WIRELESS, -+ ENUM_ID_1, -+ OBJECT_TYPE_ENCODER); -+ break; -+ case OBJECT_TYPE_ENCODER: -+ return dal_graphics_object_id_init( -+ 0, -+ ENUM_ID_1, -+ OBJECT_TYPE_GPU); -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ break; -+ } -+ } -+ -+ return dal_graphics_object_id_init( -+ 0, -+ ENUM_ID_UNKNOWN, -+ OBJECT_TYPE_UNKNOWN); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h -new file mode 100644 -index 0000000..54b140a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h -@@ -0,0 +1,80 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_WIRELESS_DATA_SOURCE_H__ -+#define __DAL_WIRELESS_DATA_SOURCE_H__ -+ -+/* Include */ -+#include "include/grph_object_id.h" -+ -+/* -+ * Forward declaration -+ */ -+struct adapter_service; -+struct bios_parser; -+ -+/* Wireless data init structure */ -+struct wireless_init_data { -+ bool fusion; /* Fusion flag */ -+ bool platform_override; /* Override for platform BIOS option */ -+ bool remote_disp_path_override; /* Override enabling wireless path */ -+ bool vce_supported; /* Existence of VCE block on this DCE */ -+ bool miracast_target_required; /* OS requires Miracast target */ -+}; -+ -+/* Wireless data */ -+struct wireless_data { -+ bool wireless_enable; -+ bool wireless_disp_path_enable; -+ bool miracast_connector_enable; -+}; -+ -+ -+/*construct wireless data*/ -+bool wireless_data_init( -+ struct wireless_data *data, -+ struct bios_parser *bp, -+ struct wireless_init_data *init_data); -+ -+uint8_t wireless_get_clocks_num( -+ struct adapter_service *as); -+ -+uint8_t wireless_get_connectors_num( -+ struct adapter_service *as); -+ -+struct graphics_object_id wireless_get_connector_id( -+ struct adapter_service *as, -+ uint8_t connector_index); -+ -+uint8_t wireless_get_srcs_num( -+ struct adapter_service *as, -+ struct graphics_object_id id); -+ -+struct graphics_object_id wireless_get_src_obj_id( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ uint8_t index); -+ -+#endif /* __DAL_WIRELESS_DATA_SOURCE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile -new file mode 100644 -index 0000000..5e01a86 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile -@@ -0,0 +1,23 @@ -+# -+# Makefile for the 'asic_capability' sub-component of DAL. -+# -+ -+ASIC_CAPABILITY = asic_capability.o -+ -+AMD_DAL_ASIC_CAPABILITY = \ -+ $(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY)) -+ -+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+ASIC_CAPABILITY_DCE11 = carrizo_asic_capability.o -+ -+AMD_DAL_ASIC_CAPABILITY_DCE11 = \ -+ $(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE11)) -+ -+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE11) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c -new file mode 100644 -index 0000000..a532e2f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c -@@ -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 -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/logger_interface.h" -+ -+#include "include/asic_capability_interface.h" -+#include "include/asic_capability_types.h" -+#include "include/dal_types.h" -+#include "include/dal_asic_id.h" -+ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "carrizo_asic_capability.h" -+#endif -+ -+/* -+ * Initializes asic_capability instance. -+ */ -+static bool construct( -+ struct asic_capability *cap, -+ struct hw_asic_id *init, -+ struct dc_context *ctx) -+{ -+ bool asic_supported = false; -+ -+ cap->ctx = ctx; -+ dc_service_memset(cap->data, 0, sizeof(cap->data)); -+ -+ /* ASIC data */ -+ cap->data[ASIC_DATA_VRAM_TYPE] = init->vram_type; -+ cap->data[ASIC_DATA_VRAM_BITWIDTH] = init->vram_width; -+ cap->data[ASIC_DATA_FEATURE_FLAGS] = init->feature_flags; -+ cap->runtime_flags = init->runtime_flags; -+ cap->data[ASIC_DATA_REVISION_ID] = init->hw_internal_rev; -+ cap->data[ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE] = 10; -+ cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 4; -+ cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 1; -+ cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 0; -+ cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 25; -+ -+ /* ASIC basic capability */ -+ cap->caps.UNDERSCAN_FOR_HDMI_ONLY = true; -+ cap->caps.SUPPORT_CEA861E_FINAL = true; -+ cap->caps.MIRABILIS_SUPPORTED = false; -+ cap->caps.MIRABILIS_ENABLED_BY_DEFAULT = false; -+ cap->caps.WIRELESS_LIMIT_TO_720P = false; -+ cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT = false; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = true; -+ cap->caps.WIRELESS_COMPRESSED_AUDIO = false; -+ cap->caps.VCE_SUPPORTED = false; -+ cap->caps.HPD_CHECK_FOR_EDID = false; -+ cap->caps.NO_VCC_OFF_HPD_POLLING = false; -+ cap->caps.NEED_MC_TUNING = false; -+ cap->caps.SUPPORT_8BPP = true; -+ -+ /* ASIC stereo 3D capability */ -+ cap->stereo_3d_caps.SUPPORTED = true; -+ -+ switch (init->chip_family) { -+ case FAMILY_CI: -+ break; -+ -+ case FAMILY_KV: -+ if (ASIC_REV_IS_KALINDI(init->hw_internal_rev) || -+ ASIC_REV_IS_BHAVANI(init->hw_internal_rev)) { -+ } else { -+ } -+ break; -+ -+ case FAMILY_CZ: -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ carrizo_asic_capability_create(cap, init); -+ asic_supported = true; -+#endif -+ break; -+ -+ default: -+ /* unsupported "chip_family" */ -+ break; -+ } -+ -+ if (false == asic_supported) { -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_MASK_ALL, -+ "%s: ASIC not supported!\n", __func__); -+ } -+ -+ return asic_supported; -+} -+ -+static void destruct( -+ struct asic_capability *cap) -+{ -+ /* nothing to do (yet?) */ -+} -+ -+/* -+ * dal_asic_capability_create -+ * -+ * Creates asic capability based on DCE version. -+ */ -+struct asic_capability *dal_asic_capability_create( -+ struct hw_asic_id *init, -+ struct dc_context *ctx) -+{ -+ struct asic_capability *cap; -+ -+ if (!init) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ cap = dc_service_alloc(ctx, sizeof(struct asic_capability)); -+ -+ if (!cap) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (construct(cap, init, ctx)) -+ return cap; -+ -+ BREAK_TO_DEBUGGER(); -+ -+ dc_service_free(ctx, cap); -+ -+ return NULL; -+} -+ -+/* -+ * dal_asic_capability_destroy -+ * -+ * Destroy allocated memory. -+ */ -+void dal_asic_capability_destroy( -+ struct asic_capability **cap) -+{ -+ if (!cap) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ if (!*cap) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ destruct(*cap); -+ -+ dc_service_free((*cap)->ctx, *cap); -+ -+ *cap = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c -new file mode 100644 -index 0000000..f57d3f7 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c -@@ -0,0 +1,146 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/asic_capability_interface.h" -+#include "include/asic_capability_types.h" -+ -+#include "carrizo_asic_capability.h" -+ -+#include "atom.h" -+#include "dce/dce_11_0_d.h" -+#include "smu/smu_8_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "dal_asic_id.h" -+ -+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074 -+ -+/* -+ * carrizo_asic_capability_create -+ * -+ * Create and initiate Carrizo capability. -+ */ -+void carrizo_asic_capability_create(struct asic_capability *cap, -+ struct hw_asic_id *init) -+{ -+ uint32_t e_fuse_setting; -+ /* ASIC data */ -+ cap->data[ASIC_DATA_CONTROLLERS_NUM] = 3; -+ cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 3; -+ cap->data[ASIC_DATA_LINEBUFFER_NUM] = 3; -+ cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4; -+ cap->data[ASIC_DATA_DCE_VERSION] = 0x110; /* DCE 11 */ -+ cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 1712 * 144; -+ cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 45; -+ cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 2; -+ cap->data[ASIC_DATA_MC_LATENCY] = 5000; -+ cap->data[ASIC_DATA_STUTTERMODE] = 0x200A; -+ cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2; -+ cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 2; -+ cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 2; -+ cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 100; -+ cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 1; -+ cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 3; -+ -+ /* ASIC basic capability */ -+ cap->caps.IS_FUSION = true; -+ cap->caps.DP_MST_SUPPORTED = true; -+ cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true; -+ cap->caps.MIRABILIS_SUPPORTED = true; -+ cap->caps.NO_VCC_OFF_HPD_POLLING = true; -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.HPD_CHECK_FOR_EDID = true; -+ cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true; -+ cap->caps.SUPPORT_8BPP = false; -+ -+ /* ASIC stereo 3d capability */ -+ cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true; -+ cap->stereo_3d_caps.HDMI_FRAME_PACK = true; -+ cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true; -+ cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true; -+ cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true; -+ cap->stereo_3d_caps.INTERLEAVE = true; -+ -+ e_fuse_setting = dal_read_index_reg(cap->ctx,CGS_IND_REG__SMC,ixVCE_HARVEST_FUSE_MACRO__ADDRESS); -+ -+ /* Bits [28:27]*/ -+ switch ((e_fuse_setting >> 27) & 0x3) { -+ case 0: -+ /*both VCE engine are working*/ -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = false; -+ /*TODO: -+ cap->caps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance0Enabled = true; -+ m_AsicCaps.vceInstance1Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 1: -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = true; -+ /*TODO: -+ m_AsicCaps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance1Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 2: -+ cap->caps.VCE_SUPPORTED = true; -+ cap->caps.WIRELESS_TIMING_ADJUSTMENT = true; -+ /*TODO: -+ m_AsicCaps.wirelessLowVCEPerformance = false; -+ m_AsicCaps.vceInstance0Enabled = true;*/ -+ cap->caps.NEED_MC_TUNING = true; -+ break; -+ -+ case 3: -+ /* VCE_DISABLE = 0x3 - both VCE -+ * instances are in harvesting, -+ * no VCE supported any more. -+ */ -+ cap->caps.VCE_SUPPORTED = false; -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (ASIC_REV_IS_STONEY(init->hw_internal_rev)) -+ { -+ /* Stoney is the same DCE11, but only two pipes, three digs. -+ * and HW added 64bit back for non SG */ -+ cap->data[ASIC_DATA_CONTROLLERS_NUM] = 2; -+ cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 2; -+ cap->data[ASIC_DATA_LINEBUFFER_NUM] = 2; -+ /*3 DP MST per connector, limited by number of pipe and number -+ * of Dig.*/ -+ cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 2; -+ -+ } -+ -+ -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h -new file mode 100644 -index 0000000..d1e9b83 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_CARRIZO_ASIC_CAPABILITY_H__ -+#define __DAL_CARRIZO_ASIC_CAPABILITY_H__ -+ -+/* Forward declaration */ -+struct asic_capability; -+ -+/* Create and initialize Carrizo data */ -+void carrizo_asic_capability_create(struct asic_capability *cap, -+ struct hw_asic_id *init); -+ -+#endif /* __DAL_CARRIZO_ASIC_CAPABILITY_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/Makefile b/drivers/gpu/drm/amd/dal/dc/audio/Makefile -new file mode 100644 -index 0000000..0999372 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/Makefile -@@ -0,0 +1,22 @@ -+# -+# Makefile for the 'audio' sub-component of DAL. -+# It provides the control and status of HW adapter resources, -+# that are global for the ASIC and sharable between pipes. -+ -+AUDIO = audio_base.o hw_ctx_audio.o -+ -+AMD_DAL_AUDIO = $(addprefix $(AMDDALPATH)/dc/audio/,$(AUDIO)) -+ -+AMD_DAL_FILES += $(AMD_DAL_AUDIO) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+AUDIO_DCE11 = audio_dce110.o hw_ctx_audio_dce110.o -+ -+AMD_DAL_AUDIO_DCE11 = $(addprefix $(AMDDALPATH)/dc/audio/dce110/,$(AUDIO_DCE11)) -+ -+AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE11) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio.h b/drivers/gpu/drm/amd/dal/dc/audio/audio.h -new file mode 100644 -index 0000000..ad2dc18 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio.h -@@ -0,0 +1,195 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_AUDIO_H__ -+#define __DAL_AUDIO_H__ -+ -+#include "include/audio_interface.h" -+#include "hw_ctx_audio.h" -+#include "include/link_service_types.h" -+ -+/***** only for hook functions *****/ -+/** -+ *which will be overwritten by derived audio object. -+ *audio hw context object is independent object -+ */ -+ -+struct audio; -+ -+struct audio_funcs { -+ /* -+ *get_object_id -+ *get_object_type -+ *enumerate_input_signals -+ *enumerate_output_signals -+ *is_input_signal_supported -+ *is_output_signal_supported -+ *set_object_properties -+ *get_object_properties -+ */ -+ -+ void (*destroy)(struct audio **audio); -+ /*power_up -+ *power_down -+ *release_hw_base -+ */ -+ -+ /* setup audio */ -+ enum audio_result (*setup)( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info); -+ -+ enum audio_result (*enable_output)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+ enum audio_result (*disable_output)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+ /*enable_azalia_audio_jack_presence -+ * disable_azalia_audio_jack_presence -+ */ -+ -+ enum audio_result (*unmute)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+ enum audio_result (*mute)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+ /* SW initialization that cannot be done in constructor. This will -+ * be done is audio_power_up but is not in audio_interface. It is only -+ * called by power_up -+ */ -+ enum audio_result (*initialize)( -+ struct audio *audio); -+ -+ /* enable channel splitting mapping */ -+ void (*enable_channel_splitting_mapping)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable); -+ -+ /* get current multi channel split. */ -+ enum audio_result (*get_channel_splitting_mapping)( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping); -+ -+ /* set payload value for the unsolicited response */ -+ void (*set_unsolicited_response_payload)( -+ struct audio *audio, -+ enum audio_payload payload); -+ -+ /* Update audio wall clock source */ -+ void (*setup_audio_wall_dto)( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info); -+ -+ /* options and features supported by Audio */ -+ struct audio_feature_support (*get_supported_features)( -+ struct audio *audio); -+ -+ /* -+ *check_audio_bandwidth -+ *write_reg -+ *read_reg -+ *enable_gtc_embedding_with_group -+ *disable_gtc_embedding -+ *register_interrupt -+ *unregister_interrupt -+ *process_interrupt -+ *create_hw_ctx -+ *getHwCtx -+ *setHwCtx -+ *handle_interrupt -+ */ -+}; -+ -+struct audio { -+ /* hook functions. they will be overwritten by specific ASIC */ -+ const struct audio_funcs *funcs; -+ /* TODO: static struct audio_funcs funcs;*/ -+ -+ /*external structures - get service from external*/ -+ struct graphics_object_id id; -+ struct adapter_service *adapter_service; -+ /* audio HW context */ -+ struct hw_ctx_audio *hw_ctx; -+ struct dc_context *ctx; -+ /* audio supports input and output signals */ -+ uint32_t input_signals; -+ uint32_t output_signals; -+}; -+ -+/* - functions defined by audio.h will be used by audio component only. -+ * but audio.c also implements some function defined by dal\include -+ */ -+ -+/* graphics_object_base implemention -+ * 1.input_signals and output_signals are moved -+ * into audio object. -+ * -+ * 2.Get the Graphics Object ID -+ * -+ * Outside audio: -+ * use dal_graphics_object_id_get_audio_id -+ * Within audio: -+ * use audio->go_base.id -+ * -+ * 3. Get the Graphics Object Type -+ * -+ * use object_id.type -+ * not function implemented. -+ * 4. Common Graphics Object Properties -+ * use object id ->go_properties.multi_path -+ * not function implemented. -+ */ -+ -+bool dal_audio_construct_base( -+ struct audio *audio, -+ const struct audio_init_data *init_data); -+ -+void dal_audio_destruct_base( -+ struct audio *audio); -+ -+void dal_audio_release_hw_base( -+ struct audio *audio); -+ -+#endif /* __DAL_AUDIO__ */ -+ -+ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c -new file mode 100644 -index 0000000..6bac3ed ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c -@@ -0,0 +1,463 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/logger_interface.h" -+ -+#include "audio.h" -+#include "hw_ctx_audio.h" -+ -+#include "dce110/audio_dce110.h" -+ -+/***** static function : only used within audio.c *****/ -+ -+/* stub for hook functions */ -+static void destroy( -+ struct audio **audio) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+static enum audio_result setup( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static enum audio_result enable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static enum audio_result disable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static enum audio_result unmute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static enum audio_result mute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static enum audio_result initialize( -+ struct audio *audio) -+{ -+ /*DCE specific, must be implemented in derived. Implemeentaion of -+ *initialize will create audio hw context. create_hw_ctx -+ */ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+static void enable_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* get current multi channel split. */ -+static enum audio_result get_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return AUDIO_RESULT_OK; -+} -+ -+/* set payload value for the unsolicited response */ -+static void set_unsolicited_response_payload( -+ struct audio *audio, -+ enum audio_payload payload) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* update audio wall clock source */ -+static void setup_audio_wall_dto( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+static struct audio_feature_support get_supported_features(struct audio *audio) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ struct audio_feature_support features; -+ -+ dc_service_memset(&features, 0, sizeof(features)); -+ -+ features.ENGINE_DIGA = 1; -+ features.ENGINE_DIGB = 1; -+ -+ return features; -+} -+ -+static const struct audio_funcs audio_funcs = { -+ .destroy = destroy, -+ .setup = setup, -+ .enable_output = enable_output, -+ .disable_output = disable_output, -+ .unmute = unmute, -+ .mute = mute, -+ .initialize = initialize, -+ .enable_channel_splitting_mapping = -+ enable_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .setup_audio_wall_dto = setup_audio_wall_dto, -+ .get_supported_features = get_supported_features, -+}; -+ -+/***** SCOPE : declare in audio.h. use within dal-audio. *****/ -+ -+bool dal_audio_construct_base( -+ struct audio *audio, -+ const struct audio_init_data *init_data) -+{ -+ enum signal_type signals = SIGNAL_TYPE_HDMI_TYPE_A; -+ -+ ASSERT(init_data->as != NULL); -+ -+ /* base hook functions */ -+ audio->funcs = &audio_funcs; -+ -+ /*setup pointers to get service from dal service compoenents*/ -+ audio->adapter_service = init_data->as; -+ -+ audio->ctx = init_data->ctx; -+ -+ /* save audio endpoint number to identify object creating */ -+ audio->id = init_data->audio_stream_id; -+ -+ /* Fill supported signals. !!! be aware that android definition is -+ * already shift to vector. -+ */ -+ signals |= SIGNAL_TYPE_DISPLAY_PORT; -+ signals |= SIGNAL_TYPE_DISPLAY_PORT_MST; -+ signals |= SIGNAL_TYPE_EDP; -+ signals |= SIGNAL_TYPE_DISPLAY_PORT; -+ signals |= SIGNAL_TYPE_WIRELESS; -+ -+ /* Audio supports same set for input and output signals */ -+ audio->input_signals = signals; -+ audio->output_signals = signals; -+ -+ return true; -+} -+ -+/* except hw_ctx, no other hw need reset. so do nothing */ -+void dal_audio_destruct_base( -+ struct audio *audio) -+{ -+} -+ -+/* Enumerate Graphics Object supported Input/Output Signal Types */ -+uint32_t dal_audio_enumerate_input_signals( -+ struct audio *audio) -+{ -+ return audio->input_signals; -+} -+ -+uint32_t dal_audio_enumerate_output_signals( -+ struct audio *audio) -+{ -+ return audio->output_signals; -+} -+ -+/* Check if signal supported by GraphicsObject */ -+bool dal_audio_is_input_signal_supported( -+ struct audio *audio, -+ enum signal_type signal) -+{ -+ return (signal & audio->output_signals) != 0; -+} -+ -+bool dal_audio_is_output_signal_supported( -+ struct audio *audio, -+ enum signal_type signal) -+{ -+ return (signal & audio->input_signals) != 0; -+} -+ -+/***** SCOPE : declare in dal\include *****/ -+ -+/* audio object creator triage. memory allocate and release will be -+ * done within dal_audio_create_dcexx -+ */ -+struct audio *dal_audio_create( -+ const struct audio_init_data *init_data) -+{ -+ struct adapter_service *as; -+ -+ if (init_data->as == NULL) -+ return NULL; -+ -+ as = init_data->as; -+ switch (dal_adapter_service_get_dce_version(as)) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ return dal_audio_create_dce110(init_data); -+#endif -+ default: -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ return NULL; -+} -+ -+/* audio object creator triage. -+ * memory for "struct audio dal_audio_create_dce8x" allocate -+ * will happens within dal_audio_dce8x. memory allocate is done -+ * with dal_audio_create_dce8x. memory release is initiated by -+ * dal_audio_destroy. It will call hook function which will finially -+ * used destroy() of dal_audio_dce8x. therefore, no memroy allocate -+ *and release happen physcially at audio base object. -+ */ -+void dal_audio_destroy( -+ struct audio **audio) -+{ -+ if (!audio || !*audio) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ (*audio)->funcs->destroy(audio); -+ -+ *audio = NULL; -+} -+ -+const struct graphics_object_id dal_audio_get_graphics_object_id( -+ const struct audio *audio) -+{ -+ return audio->id; -+} -+ -+/* enable azalia audio endpoint. This function call hw_ctx directly -+ *not overwitten at audio level. -+ */ -+enum audio_result dal_audio_enable_azalia_audio_jack_presence( -+ struct audio *audio, -+ enum engine_id engine_id) -+{ -+ audio->hw_ctx->funcs->enable_azalia_audio(audio->hw_ctx, engine_id); -+ return AUDIO_RESULT_OK; -+} -+ -+/* disable azalia audio endpoint. This function call hw_ctx directly -+ *not overwitten at audio level. -+ */ -+enum audio_result dal_audio_disable_azalia_audio_jack_presence( -+ struct audio *audio, -+ enum engine_id engine_id) -+{ -+ audio->hw_ctx->funcs->disable_azalia_audio(audio->hw_ctx, engine_id); -+ return AUDIO_RESULT_OK; -+} -+ -+/* get audio bandwidth information. This function call hw_ctx directly -+ *not overwitten at audio level. -+ */ -+void dal_audio_check_audio_bandwidth( -+ struct audio *audio, -+ const struct audio_crtc_info *info, -+ uint32_t channel_count, -+ enum signal_type signal, -+ union audio_sample_rates *sample_rates) -+{ -+ dal_hw_ctx_audio_check_audio_bandwidth( -+ audio->hw_ctx, info, channel_count, signal, sample_rates); -+} -+ -+/* DP Audio register write access. This function call hw_ctx directly -+ * not overwitten at audio level. -+ */ -+ -+/*assign GTC group and enable GTC value embedding*/ -+void dal_audio_enable_gtc_embedding_with_group( -+ struct audio *audio, -+ uint32_t group_num, -+ uint32_t audio_latency) -+{ -+ audio->hw_ctx->funcs->enable_gtc_embedding_with_group( -+ audio->hw_ctx, group_num, audio_latency); -+} -+ -+/* disable GTC value embedding */ -+void dal_audio_disable_gtc_embedding( -+ struct audio *audio) -+{ -+ audio->hw_ctx->funcs->disable_gtc_embedding(audio->hw_ctx); -+} -+ -+/* perform power up sequence (boot up, resume, recovery) */ -+enum audio_result dal_audio_power_up( -+ struct audio *audio) -+{ -+ return audio->funcs->initialize(audio); -+} -+ -+/* perform power down (shut down, stand by) */ -+enum audio_result dal_audio_power_down( -+ struct audio *audio) -+{ -+ return AUDIO_RESULT_OK; -+} -+ -+/* setup audio */ -+enum audio_result dal_audio_setup( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info) -+{ -+ return audio->funcs->setup(audio, output, info); -+} -+ -+/* enable audio */ -+enum audio_result dal_audio_enable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ return audio->funcs->enable_output(audio, engine_id, signal); -+} -+ -+/* disable audio */ -+enum audio_result dal_audio_disable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ return audio->funcs->disable_output(audio, engine_id, signal); -+} -+ -+/* unmute audio */ -+enum audio_result dal_audio_unmute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ return audio->funcs->unmute(audio, engine_id, signal); -+} -+ -+/* mute audio */ -+enum audio_result dal_audio_mute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ return audio->funcs->mute(audio, engine_id, signal); -+} -+ -+/* Enable multi channel split */ -+void dal_audio_enable_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ audio->funcs->enable_channel_splitting_mapping( -+ audio, engine_id, signal, audio_mapping, enable); -+} -+ -+/* get current multi channel split. */ -+enum audio_result dal_audio_get_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ return audio->funcs->get_channel_splitting_mapping( -+ audio, engine_id, audio_mapping); -+} -+ -+/* set payload value for the unsolicited response */ -+void dal_audio_set_unsolicited_response_payload( -+ struct audio *audio, -+ enum audio_payload payload) -+{ -+ audio->funcs->set_unsolicited_response_payload(audio, payload); -+} -+ -+/* update audio wall clock source */ -+void dal_audio_setup_audio_wall_dto( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ audio->funcs->setup_audio_wall_dto(audio, signal, crtc_info, pll_info); -+} -+ -+struct audio_feature_support dal_audio_get_supported_features( -+ struct audio *audio) -+{ -+ return audio->funcs->get_supported_features(audio); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c -new file mode 100644 -index 0000000..f284870 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c -@@ -0,0 +1,452 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/logger_interface.h" -+ -+#include "audio_dce110.h" -+ -+/***** static functions *****/ -+ -+static void destruct(struct audio_dce110 *audio) -+{ -+ /*release memory allocated for hw_ctx -- allocated is initiated -+ *by audio_dce110 power_up -+ *audio->base->hw_ctx = NULL is done within hw-ctx->destroy -+ */ -+ if (audio->base.hw_ctx) -+ audio->base.hw_ctx->funcs->destroy(&(audio->base.hw_ctx)); -+ -+ /* reset base_audio_block */ -+ dal_audio_destruct_base(&audio->base); -+} -+ -+static void destroy(struct audio **ptr) -+{ -+ struct audio_dce110 *audio = NULL; -+ -+ audio = container_of(*ptr, struct audio_dce110, base); -+ -+ destruct(audio); -+ -+ /* release memory allocated for audio_dce110*/ -+ dc_service_free((*ptr)->ctx, audio); -+ *ptr = NULL; -+} -+ -+ -+/* The inital call of hook function comes from audio object level. -+ *The passing object handle "struct audio *audio" point to base object -+ *already.There is not need to get base object from audio_dce110. -+ */ -+ -+/** -+* setup -+* -+* @brief -+* setup Audio HW block, to be called by dal_audio_setup -+* -+*/ -+static enum audio_result setup( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info) -+{ -+ switch (output->signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ /*setup HDMI audio engine*/ -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, -+ output->engine_id, -+ true); -+ audio->hw_ctx->funcs->setup_hdmi_audio( -+ audio->hw_ctx, output->engine_id, &output->crtc_info); -+ -+ audio->hw_ctx->funcs->setup_azalia( -+ audio->hw_ctx, -+ output->engine_id, -+ output->signal, -+ &output->crtc_info, -+ &output->pll_info, -+ info); -+ break; -+ -+ case SIGNAL_TYPE_WIRELESS: -+ /* setup Azalia block for Wireless Display - This -+ is different than for wired -+ displays because there is no -+ DIG to program.*/ -+ /*TODO: -+ audio->hw_ctx->funcs->setup_azalia_for_vce( -+ audio->hw_ctx, -+ audio->signal, -+ audio->crtc_info, -+ info); -+ */ -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* setup DP audio engine will be done at enable output */ -+ -+ /* setup Azalia block*/ -+ audio->hw_ctx->funcs->setup_azalia( -+ audio->hw_ctx, -+ output->engine_id, -+ output->signal, -+ &output->crtc_info, -+ &output->pll_info, -+ info); -+ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* enable_output -+* -+* @brief -+* enable Audio HW block, to be called by dal_audio_enable_output -+*/ -+static enum audio_result enable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ /* enable audio output */ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: { -+ /* enable AFMT clock before enable audio*/ -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, true); -+ /* setup DP audio engine */ -+ audio->hw_ctx->funcs->setup_dp_audio( -+ audio->hw_ctx, engine_id); -+ /* enabl DP audio packets will be done at unblank */ -+ audio->hw_ctx->funcs->enable_dp_audio( -+ audio->hw_ctx, engine_id); -+ } -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /* route audio to VCE block */ -+ audio->hw_ctx->funcs->setup_vce_audio(audio->hw_ctx); -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* disable_output -+* -+* @brief -+* disable Audio HW block, to be called by dal_audio_disable_output -+* -+*/ -+static enum audio_result disable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_WIRELESS: -+ /* disable HDMI audio */ -+ audio->hw_ctx-> -+ funcs->disable_azalia_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx-> -+ funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, -+ false); -+ -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: { -+ /* disable DP audio */ -+ audio->hw_ctx->funcs->disable_dp_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx->funcs->disable_azalia_audio( -+ audio->hw_ctx, engine_id); -+ audio->hw_ctx->funcs->enable_afmt_clock( -+ audio->hw_ctx, engine_id, false); -+ } -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* unmute -+* -+* @brief -+* unmute audio, to be called by dal_audio_unmute -+* -+*/ -+static enum audio_result unmute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* unmute Azalia audio */ -+ audio->hw_ctx->funcs->unmute_azalia_audio( -+ audio->hw_ctx, engine_id); -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /*Do nothing for wireless display*/ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* mute -+* -+* @brief -+* mute audio, to be called by dal_audio_nmute -+* -+*/ -+static enum audio_result mute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* mute Azalia audio */ -+ audio->hw_ctx->funcs->mute_azalia_audio( -+ audio->hw_ctx, engine_id); -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ /*Do nothing for wireless display*/ -+ break; -+ default: -+ return AUDIO_RESULT_ERROR; -+ } -+ return AUDIO_RESULT_OK; -+} -+ -+/** -+* initialize -+* -+* @brief -+* Perform SW initialization - create audio hw context. Then do HW -+* initialization. this function is called at dal_audio_power_up. -+* -+*/ -+static enum audio_result initialize( -+ struct audio *audio) -+{ -+ uint8_t audio_endpoint_enum_id = 0; -+ -+ audio_endpoint_enum_id = audio->id.enum_id; -+ -+ /* HW CTX already create*/ -+ if (audio->hw_ctx != NULL) -+ return AUDIO_RESULT_OK; -+ -+ audio->hw_ctx = dal_hw_ctx_audio_dce110_create( -+ audio->ctx, -+ audio_endpoint_enum_id); -+ -+ if (audio->hw_ctx == NULL) -+ return AUDIO_RESULT_ERROR; -+ -+ /* override HW default settings */ -+ audio->hw_ctx->funcs->hw_initialize(audio->hw_ctx); -+ -+ return AUDIO_RESULT_OK; -+} -+ -+/* enable multi channel split */ -+static void enable_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ audio->hw_ctx->funcs->setup_channel_splitting_mapping( -+ audio->hw_ctx, -+ engine_id, -+ signal, -+ audio_mapping, enable); -+} -+ -+/* get current multi channel split. */ -+static enum audio_result get_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ if (audio->hw_ctx->funcs->get_channel_splitting_mapping( -+ audio->hw_ctx, engine_id, audio_mapping)) { -+ return AUDIO_RESULT_OK; -+ } else { -+ return AUDIO_RESULT_ERROR; -+ } -+} -+ -+/** -+* set_unsolicited_response_payload -+* -+* @brief -+* Set payload value for the unsolicited response -+*/ -+static void set_unsolicited_response_payload( -+ struct audio *audio, -+ enum audio_payload payload) -+{ -+ audio->hw_ctx->funcs->set_unsolicited_response_payload( -+ audio->hw_ctx, payload); -+} -+ -+/** -+* setup_audio_wall_dto -+* -+* @brief -+* Update audio source clock from hardware context. -+* -+*/ -+static void setup_audio_wall_dto( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ audio->hw_ctx->funcs->setup_audio_wall_dto( -+ audio->hw_ctx, signal, crtc_info, pll_info); -+} -+ -+/** -+* get_supported_features -+* -+* @brief -+* options and features supported by Audio -+* returns supported engines, signals. -+* features are reported for HW audio/Azalia block rather then Audio object -+* itself the difference for DCE6.x is that MultiStream Audio is now supported -+* -+*/ -+static struct audio_feature_support get_supported_features(struct audio *audio) -+{ -+ struct audio_feature_support afs = {0}; -+ -+ afs.ENGINE_DIGA = 1; -+ afs.ENGINE_DIGB = 1; -+ afs.ENGINE_DIGC = 1; -+ afs.MULTISTREAM_AUDIO = 1; -+ -+ return afs; -+} -+ -+static const struct audio_funcs funcs = { -+ .destroy = destroy, -+ .setup = setup, -+ .enable_output = enable_output, -+ .disable_output = disable_output, -+ .unmute = unmute, -+ .mute = mute, -+ .initialize = initialize, -+ .enable_channel_splitting_mapping = -+ enable_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .setup_audio_wall_dto = setup_audio_wall_dto, -+ .get_supported_features = get_supported_features, -+}; -+ -+static bool construct( -+ struct audio_dce110 *audio, -+ const struct audio_init_data *init_data) -+{ -+ struct audio *base = &audio->base; -+ -+ /* base audio construct*/ -+ if (!dal_audio_construct_base(base, init_data)) -+ return false; -+ -+ /*vtable methods*/ -+ base->funcs = &funcs; -+ return true; -+} -+ -+ -+/* --- audio scope functions --- */ -+ -+struct audio *dal_audio_create_dce110( -+ const struct audio_init_data *init_data) -+{ -+ /*allocate memory for audio_dce110 */ -+ struct audio_dce110 *audio = dc_service_alloc(init_data->ctx, sizeof(*audio)); -+ -+ if (audio == NULL) { -+ ASSERT_CRITICAL(audio); -+ return NULL; -+ } -+ /*pointer to base_audio_block of audio_dce110 ==> audio base object */ -+ if (construct(audio, init_data)) -+ return &audio->base; -+ -+ dal_logger_write( -+ init_data->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Failed to create audio object for DCE11\n"); -+ -+ /*release memory allocated if fail */ -+ dc_service_free(init_data->ctx, audio); -+ return NULL; -+} -+ -+/* Do not need expose construct_dce110 and destruct_dce110 becuase there is -+ *derived object after dce110 -+ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h -new file mode 100644 -index 0000000..e5ff823 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h -@@ -0,0 +1,42 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_AUDIO_DCE_110_H__ -+#define __DAL_AUDIO_DCE_110_H__ -+ -+#include "audio/audio.h" -+#include "audio/hw_ctx_audio.h" -+#include "audio/dce110/hw_ctx_audio_dce110.h" -+ -+ -+ -+struct audio_dce110 { -+ struct audio base; -+ /* dce-specific members are following */ -+ /* none */ -+}; -+ -+struct audio *dal_audio_create_dce110(const struct audio_init_data *init_data); -+ -+#endif /*__DAL_AUDIO_DCE_110_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c -new file mode 100644 -index 0000000..a13b2ab ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c -@@ -0,0 +1,1929 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/logger_interface.h" -+#include "../hw_ctx_audio.h" -+#include "hw_ctx_audio_dce110.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#define FROM_BASE(ptr) \ -+ container_of((ptr), struct hw_ctx_audio_dce110, base) -+ -+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -+#define DP_AUDIO_DTO_MODULE_WITHOUT_SS 360 -+#define DP_AUDIO_DTO_PHASE_WITHOUT_SS 24 -+ -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUDIO_FRONT_END 0 -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 -+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__REGISTER_PROGRAMMABLE 2 -+ -+#define FIRST_AUDIO_STREAM_ID 1 -+ -+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_AUDIO, \ -+ "Audio:%s()\n", __func__) -+ -+static const uint32_t engine_offset[] = { -+ 0, -+ mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG3_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL -+}; -+ -+static void destruct( -+ struct hw_ctx_audio_dce110 *hw_ctx_dce110) -+{ -+ dal_audio_destruct_hw_ctx_audio(&hw_ctx_dce110->base); -+} -+ -+static void destroy( -+ struct hw_ctx_audio **ptr) -+{ -+ struct hw_ctx_audio_dce110 *hw_ctx_dce110; -+ -+ hw_ctx_dce110 = container_of( -+ *ptr, struct hw_ctx_audio_dce110, base); -+ -+ destruct(hw_ctx_dce110); -+ /* release memory allocated for struct hw_ctx_audio_dce110 */ -+ dc_service_free((*ptr)->ctx, hw_ctx_dce110); -+ -+ *ptr = NULL; -+} -+ -+/* --- helpers --- */ -+static void write_indirect_azalia_reg( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t reg_index, -+ uint32_t reg_data) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index; -+ -+ set_reg_field_value(value, reg_index, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data; -+ -+ value = 0; -+ set_reg_field_value(value, reg_data, -+ AZALIA_F0_CODEC_ENDPOINT_DATA, -+ AZALIA_ENDPOINT_REG_DATA); -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_AUDIO, -+ "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n", -+ reg_index, reg_data); -+} -+ -+static uint32_t read_indirect_azalia_reg( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t reg_index) -+{ -+ uint32_t ret_val = 0; -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index; -+ -+ set_reg_field_value(value, reg_index, -+ AZALIA_F0_CODEC_ENDPOINT_INDEX, -+ AZALIA_ENDPOINT_REG_INDEX); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ -+ { -+ addr = -+ FROM_BASE(hw_ctx)->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ ret_val = value; -+ } -+ -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_AUDIO, -+ "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n", -+ reg_index, ret_val); -+ -+ return ret_val; -+} -+ -+/* expose/not expose HBR capability to Audio driver */ -+static void set_high_bit_rate_capable( -+ const struct hw_ctx_audio *hw_ctx, -+ bool capable) -+{ -+ uint32_t value = 0; -+ -+ /* set high bit rate audio capable*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR); -+ -+ set_reg_field_value(value, capable, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, -+ HBR_CAPABLE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, -+ value); -+} -+ -+/* set HBR channnel count * -+static void set_hbr_channel_count( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t hbr_channel_count) -+{ -+ uint32_t value = 0; -+ -+ if (hbr_channel_count > 7) -+ return; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL); -+ -+ set_reg_field_value(value, hbr_channel_count, -+ AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ HBR_CHANNEL_COUNT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, value); -+ -+} -+ -+*set compressed audio channel count * -+static void set_compressed_audio_channel_count( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t compressed_audio_ch_count) -+{ -+ uint32_t value = 0; -+ if (compressed_audio_ch_count > 7) -+ return; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL); -+ -+ set_reg_field_value(value, compressed_audio_ch_count, -+ AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ COMPRESSED_CHANNEL_COUNT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, -+ value); -+ -+} -+*/ -+/* set video latency in in ms/2+1 */ -+static void set_video_latency( -+ const struct hw_ctx_audio *hw_ctx, -+ int latency_in_ms) -+{ -+ uint32_t value = 0; -+ -+ if ((latency_in_ms < 0) || (latency_in_ms > 255)) -+ return; -+ -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); -+ -+ set_reg_field_value(value, latency_in_ms, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ VIDEO_LIPSYNC); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ value); -+ -+} -+ -+/* set audio latency in in ms/2+1 */ -+static void set_audio_latency( -+ const struct hw_ctx_audio *hw_ctx, -+ int latency_in_ms) -+{ -+ uint32_t value = 0; -+ -+ if (latency_in_ms < 0) -+ latency_in_ms = 0; -+ -+ if (latency_in_ms > 255) -+ latency_in_ms = 255; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); -+ -+ set_reg_field_value(value, latency_in_ms, -+ AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ AUDIO_LIPSYNC); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, -+ value); -+ -+} -+ -+/* enable HW/SW Sync */ -+/*static void enable_hw_sw_sync( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ union AZALIA_CYCLIC_BUFFER_SYNC value; -+ -+ value = dal_read_reg(mmAZALIA_CYCLIC_BUFFER_SYNC); -+ value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 1; -+ dal_write_reg(mmAZALIA_CYCLIC_BUFFER_SYNC, value); -+}*/ -+ -+/* disable HW/SW Sync */ -+/*static void disable_hw_sw_sync( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ union AZALIA_CYCLIC_BUFFER_SYNC value; -+ -+ value = dal_read_reg( -+ mmAZALIA_CYCLIC_BUFFER_SYNC); -+ value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 0; -+ dal_write_reg( -+ mmAZALIA_CYCLIC_BUFFER_SYNC, value); -+}*/ -+ -+/* update hardware with software's current position in cyclic buffer */ -+/*static void update_sw_write_ptr( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t offset) -+{ -+ union AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER value; -+ -+ value = dal_read_reg( -+ mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER); -+ value.bits.APPLICATION_POSITION_IN_CYCLIC_BUFFER = offset; -+ dal_write_reg( -+ mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER, -+ value); -+}*/ -+ -+/* update Audio/Video association */ -+/*static void update_av_association( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ uint32_t displayId) -+{ -+ -+}*/ -+ -+/* --- hook functions --- */ -+static bool get_azalia_clock_info_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info); -+ -+static bool get_azalia_clock_info_dp( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info); -+ -+static void setup_audio_wall_dto( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ struct azalia_clock_info clock_info = { 0 }; -+ -+ uint32_t value = dal_read_reg(hw_ctx->ctx, mmDCCG_AUDIO_DTO_SOURCE); -+ -+ /* TODO: GraphicsObject\inc\GraphicsObjectDefs.hpp(131): -+ *inline bool isHdmiSignal(SignalType signal) -+ *if (Signals::isHdmiSignal(signal)) -+ */ -+ if (dc_is_hdmi_signal(signal)) { -+ /*DTO0 Programming goal: -+ -generate 24MHz, 128*Fs from 24MHz -+ -use DTO0 when an active HDMI port is connected -+ (optionally a DP is connected) */ -+ -+ /* calculate DTO settings */ -+ get_azalia_clock_info_hdmi( -+ hw_ctx, -+ crtc_info->requested_pixel_clock, -+ crtc_info->calculated_pixel_clock, -+ &clock_info); -+ -+ /* On TN/SI, Program DTO source select and DTO select before -+ programming DTO modulo and DTO phase. These bits must be -+ programmed first, otherwise there will be no HDMI audio at boot -+ up. This is a HW sequence change (different from old ASICs). -+ Caution when changing this programming sequence. -+ -+ HDMI enabled, using DTO0 -+ program master CRTC for DTO0 */ -+ { -+ set_reg_field_value(value, -+ pll_info->dto_source - DTO_SOURCE_ID0, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO0_SOURCE_SEL); -+ -+ set_reg_field_value(value, -+ 0, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO_SEL); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO_SOURCE, value); -+ } -+ -+ /* module */ -+ { -+ value = dal_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_MODULE); -+ set_reg_field_value(value, -+ clock_info.audio_dto_module, -+ DCCG_AUDIO_DTO0_MODULE, -+ DCCG_AUDIO_DTO0_MODULE); -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_MODULE, value); -+ } -+ -+ /* phase */ -+ { -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_PHASE); -+ set_reg_field_value(value, -+ clock_info.audio_dto_phase, -+ DCCG_AUDIO_DTO0_PHASE, -+ DCCG_AUDIO_DTO0_PHASE); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO0_PHASE, value); -+ } -+ -+ } else { -+ /*DTO1 Programming goal: -+ -generate 24MHz, 512*Fs, 128*Fs from 24MHz -+ -default is to used DTO1, and switch to DTO0 when an audio -+ master HDMI port is connected -+ -use as default for DP -+ -+ calculate DTO settings */ -+ get_azalia_clock_info_dp( -+ hw_ctx, -+ crtc_info->requested_pixel_clock, -+ pll_info, -+ &clock_info); -+ -+ /* Program DTO select before programming DTO modulo and DTO -+ phase. default to use DTO1 */ -+ -+ { -+ set_reg_field_value(value, 1, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO_SEL); -+ /*dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value)*/ -+ -+ /* Select 512fs for DP TODO: web register definition -+ does not match register header file -+ set_reg_field_value(value, 1, -+ DCCG_AUDIO_DTO_SOURCE, -+ DCCG_AUDIO_DTO2_USE_512FBR_DTO); -+ */ -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO_SOURCE, value); -+ } -+ -+ /* module */ -+ { -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_MODULE); -+ -+ set_reg_field_value(value, -+ clock_info.audio_dto_module, -+ DCCG_AUDIO_DTO1_MODULE, -+ DCCG_AUDIO_DTO1_MODULE); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_MODULE, value); -+ } -+ -+ /* phase */ -+ { -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_PHASE); -+ -+ set_reg_field_value(value, -+ clock_info.audio_dto_phase, -+ DCCG_AUDIO_DTO1_PHASE, -+ DCCG_AUDIO_DTO1_PHASE); -+ -+ dal_write_reg(hw_ctx->ctx, -+ mmDCCG_AUDIO_DTO1_PHASE, value); -+ } -+ -+ /* DAL2 code separate DCCG_AUDIO_DTO_SEL and -+ DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different -+ location. merge together should not hurt */ -+ /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; -+ dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ -+ } -+} -+ -+/* setup HDMI audio */ -+static void setup_hdmi_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ const struct audio_crtc_info *crtc_info) -+{ -+ struct audio_clock_info audio_clock_info = {0}; -+ uint32_t max_packets_per_line; -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* For now still do calculation, although this field is ignored when -+ above HDMI_PACKET_GEN_VERSION set to 1 */ -+ max_packets_per_line = -+ dal_audio_hw_ctx_calc_max_audio_packets_per_line( -+ hw_ctx, -+ crtc_info); -+ -+ /* HDMI_AUDIO_PACKET_CONTROL */ -+ { -+ addr = -+ mmHDMI_AUDIO_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, max_packets_per_line, -+ HDMI_AUDIO_PACKET_CONTROL, -+ HDMI_AUDIO_PACKETS_PER_LINE); -+ /* still apply RS600's default setting which is 1. */ -+ set_reg_field_value(value, 1, -+ HDMI_AUDIO_PACKET_CONTROL, -+ HDMI_AUDIO_DELAY_EN); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AFMT_AUDIO_PACKET_CONTROL, -+ AFMT_60958_CS_UPDATE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL2 */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_LAYOUT_OVRD); -+ -+ /*Register field changed.*/ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_60958_OSF_OVRD); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_PACKET_CONTROL */ -+ { -+ addr = mmHDMI_ACR_PACKET_CONTROL + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_AUTO_SEND); -+ -+ /* Set HDMI_ACR_SOURCE to 0, to use hardwre -+ * computed CTS values.*/ -+ set_reg_field_value(value, 0, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_SOURCE); -+ -+ /* For now clear HDMI_ACR_AUDIO_PRIORITY =>ACR packet has -+ higher priority over Audio Sample */ -+ set_reg_field_value(value, 0, -+ HDMI_ACR_PACKET_CONTROL, -+ HDMI_ACR_AUDIO_PRIORITY); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Program audio clock sample/regeneration parameters */ -+ if (dal_audio_hw_ctx_get_audio_clock_info( -+ hw_ctx, -+ crtc_info->color_depth, -+ crtc_info->requested_pixel_clock, -+ crtc_info->calculated_pixel_clock, -+ &audio_clock_info)) { -+ -+ /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ -+ { -+ addr = mmHDMI_ACR_32_0 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, audio_clock_info.cts_32khz, -+ HDMI_ACR_32_0, -+ HDMI_ACR_CTS_32); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ -+ { -+ addr = mmHDMI_ACR_32_1 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_32khz, -+ HDMI_ACR_32_1, -+ HDMI_ACR_N_32); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ -+ { -+ addr = mmHDMI_ACR_44_0 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.cts_44khz, -+ HDMI_ACR_44_0, -+ HDMI_ACR_CTS_44); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ -+ { -+ addr = mmHDMI_ACR_44_1 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_44khz, -+ HDMI_ACR_44_1, -+ HDMI_ACR_N_44); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ -+ { -+ addr = mmHDMI_ACR_48_0 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.cts_48khz, -+ HDMI_ACR_48_0, -+ HDMI_ACR_CTS_48); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ -+ { -+ addr = mmHDMI_ACR_48_1 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, audio_clock_info.n_48khz, -+ HDMI_ACR_48_1, -+ HDMI_ACR_N_48); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Video driver cannot know in advance which sample rate will -+ be used by HD Audio driver -+ HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is -+ programmed below in interruppt callback */ -+ } /* if */ -+ -+ /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & -+ AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -+ { -+ addr = mmAFMT_60958_0 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ AFMT_60958_0, -+ AFMT_60958_CS_CHANNEL_NUMBER_L); -+ -+ /*HW default */ -+ set_reg_field_value(value, 0, -+ AFMT_60958_0, -+ AFMT_60958_CS_CLOCK_ACCURACY); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ -+ { -+ addr = mmAFMT_60958_1 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 2, -+ AFMT_60958_1, -+ AFMT_60958_CS_CHANNEL_NUMBER_R); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /*AFMT_60958_2 now keep this settings until -+ * Programming guide comes out*/ -+ { -+ addr = mmAFMT_60958_2 + engine_offset[engine_id]; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 3, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_2); -+ -+ set_reg_field_value(value, 4, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_3); -+ -+ set_reg_field_value(value, 5, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_4); -+ -+ set_reg_field_value(value, 6, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_5); -+ -+ set_reg_field_value(value, 7, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_6); -+ -+ set_reg_field_value(value, 8, -+ AFMT_60958_2, -+ AFMT_60958_CS_CHANNEL_NUMBER_7); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+ /* setup DP audio */ -+static void setup_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /* --- DP Audio packet configurations --- */ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* ATP Configuration */ -+ { -+ addr = mmDP_SEC_AUD_N + engine_offset[engine_id]; -+ -+ set_reg_field_value(value, -+ DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT, -+ DP_SEC_AUD_N, -+ DP_SEC_AUD_N); -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Async/auto-calc timestamp mode */ -+ { -+ addr = mmDP_SEC_TIMESTAMP + -+ engine_offset[engine_id]; -+ -+ value = 0; -+ -+ set_reg_field_value(value, -+ DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC, -+ DP_SEC_TIMESTAMP, -+ DP_SEC_TIMESTAMP_MODE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* --- The following are the registers -+ * copied from the SetupHDMI --- */ -+ -+ -+ /* AFMT_AUDIO_PACKET_CONTROL */ -+ { -+ addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 1, -+ AFMT_AUDIO_PACKET_CONTROL, -+ AFMT_60958_CS_UPDATE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_AUDIO_PACKET_CONTROL2 */ -+ { -+ addr = -+ mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_LAYOUT_OVRD); -+ -+ set_reg_field_value(value, -+ 0, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_60958_OSF_OVRD); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_INFOFRAME_CONTROL0 */ -+ { -+ addr = -+ mmAFMT_INFOFRAME_CONTROL0 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, -+ 1, -+ AFMT_INFOFRAME_CONTROL0, -+ AFMT_AUDIO_INFO_UPDATE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -+ { -+ addr = mmAFMT_60958_0 + engine_offset[engine_id]; -+ -+ value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, -+ 0, -+ AFMT_60958_0, -+ AFMT_60958_CS_CLOCK_ACCURACY); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+ /* setup VCE audio */ -+static void setup_vce_audio( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ struct dc_context *ctx = hw_ctx->ctx; -+ -+ NOT_IMPLEMENTED(); -+ -+ /*TODO: -+ const uint32_t addr = mmDOUT_DCE_VCE_CONTROL; -+ uint32_t value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, -+ addr); -+ -+ set_reg_field_value(value, -+ FROM_BASE(hw_ctx)->azalia_stream_id - 1, -+ DOUT_DCE_VCE_CONTROL, -+ DC_VCE_AUDIO_STREAM_SELECT); -+ -+ dal_write_reg(hw_ctx->ctx, -+ addr, value);*/ -+} -+ -+static void enable_afmt_clock( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ bool enable_flag) -+{ -+ uint32_t engine_offs = engine_offset[engine_id]; -+ uint32_t value; -+ uint32_t count = 0; -+ uint32_t enable = enable_flag ? 1:0; -+ -+ /* Enable Audio packets*/ -+ value = dal_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs); -+ -+ /*enable AFMT clock*/ -+ set_reg_field_value(value, enable, -+ AFMT_CNTL, AFMT_AUDIO_CLOCK_EN); -+ dal_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value); -+ -+ /*wait for AFMT clock to turn on, -+ * the expectation is that this -+ * should complete in 1-2 reads) -+ */ -+ do { -+ /* Wait for 1us between subsequent register reads.*/ -+ dc_service_delay_in_microseconds(hw_ctx->ctx, 1); -+ value = dal_read_reg(hw_ctx->ctx, -+ mmAFMT_CNTL + engine_offs); -+ } while (get_reg_field_value(value, -+ AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) != -+ enable && count++ < 10); -+} -+ -+/* enable Azalia audio */ -+static void enable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ uint32_t value; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); -+ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED) != 1) -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ value); -+} -+ -+/* disable Azalia audio */ -+static void disable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ uint32_t value; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ AUDIO_ENABLED); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, -+ value); -+} -+ -+/* enable DP audio */ -+static void enable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id]; -+ -+ uint32_t value; -+ -+ /* Enable Audio packets */ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_ASP_ENABLE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ -+ /* Program the ATP and AIP next */ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_ATP_ENABLE); -+ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_AIP_ENABLE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ -+ /* Program STREAM_ENABLE after all the other enables. */ -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* disable DP audio */ -+static void disable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id]; -+ -+ uint32_t value; -+ -+ /* Disable Audio packets */ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ASP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ATP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_AIP_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_ACM_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ /* This register shared with encoder info frame. Therefore we need to -+ keep master enabled if at least on of the fields is not 0 */ -+ if (value != 0) -+ set_reg_field_value(value, 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+static void configure_azalia( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_info *audio_info) -+{ -+ uint32_t speakers = audio_info->flags.info.ALLSPEAKERS; -+ uint32_t value; -+ uint32_t field = 0; -+ enum audio_format_code audio_format_code; -+ uint32_t format_index; -+ uint32_t index; -+ bool is_ac3_supported = false; -+ bool is_audio_format_supported = false; -+ union audio_sample_rates sample_rate; -+ uint32_t strlen = 0; -+ -+ /* Speaker Allocation */ -+ /* -+ uint32_t value; -+ uint32_t field = 0;*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); -+ -+ set_reg_field_value(value, -+ speakers, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ SPEAKER_ALLOCATION); -+ -+ /* LFE_PLAYBACK_LEVEL = LFEPBL -+ * LFEPBL = 0 : Unknown or refer to other information -+ * LFEPBL = 1 : 0dB playback -+ * LFEPBL = 2 : +10dB playback -+ * LFE_BL = 3 : Reserved -+ */ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ LFE_PLAYBACK_LEVEL); -+ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ set_reg_field_value(value, -+ 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ DP_CONNECTION); -+ -+ field = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ field &= ~0x1; -+ -+ set_reg_field_value(value, -+ field, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ /* set audio for output signal */ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ break; -+ case SIGNAL_TYPE_WIRELESS: { -+ /*LSB used for "is wireless" flag */ -+ field = 0; -+ field = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ field |= 0x1; -+ set_reg_field_value(value, -+ field, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ EXTRA_CONNECTION_INFO); -+ -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ HDMI_CONNECTION); -+ -+ } -+ break; -+ case SIGNAL_TYPE_EDP: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ set_reg_field_value(value, -+ 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ DP_CONNECTION); -+ -+ break; -+ default: -+ break; -+ } -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, -+ value); -+ -+ /* Wireless Display identification */ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION); -+ -+ set_reg_field_value(value, -+ signal == SIGNAL_TYPE_WIRELESS ? 1 : 0, -+ AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, -+ WIRELESS_DISPLAY_IDENTIFICATION); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, -+ value); -+ -+ /* Audio Descriptors */ -+ /* pass through all formats */ -+ for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT; -+ format_index++) { -+ audio_format_code = -+ (AUDIO_FORMAT_CODE_FIRST + format_index); -+ -+ /* those are unsupported, skip programming */ -+ if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO || -+ audio_format_code == AUDIO_FORMAT_CODE_DST) -+ continue; -+ -+ value = 0; -+ -+ /* check if supported */ -+ is_audio_format_supported = -+ dal_audio_hw_ctx_is_audio_format_supported( -+ hw_ctx, -+ audio_info, -+ audio_format_code, &index); -+ -+ if (is_audio_format_supported) { -+ const struct audio_mode *audio_mode = -+ &audio_info->modes[index]; -+ union audio_sample_rates sample_rates = -+ audio_mode->sample_rates; -+ uint8_t byte2 = audio_mode->max_bit_rate; -+ -+ /* adjust specific properties */ -+ switch (audio_format_code) { -+ case AUDIO_FORMAT_CODE_LINEARPCM: { -+ dal_hw_ctx_audio_check_audio_bandwidth( -+ hw_ctx, -+ crtc_info, -+ audio_mode->channel_count, -+ signal, -+ &sample_rates); -+ -+ byte2 = audio_mode->sample_size; -+ -+ set_reg_field_value(value, -+ sample_rates.all, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ SUPPORTED_FREQUENCIES_STEREO); -+ -+ } -+ break; -+ case AUDIO_FORMAT_CODE_AC3: -+ is_ac3_supported = true; -+ break; -+ case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS: -+ case AUDIO_FORMAT_CODE_DTS_HD: -+ case AUDIO_FORMAT_CODE_MAT_MLP: -+ case AUDIO_FORMAT_CODE_DST: -+ case AUDIO_FORMAT_CODE_WMAPRO: -+ byte2 = audio_mode->vendor_specific; -+ break; -+ default: -+ break; -+ } -+ -+ /* fill audio format data */ -+ set_reg_field_value(value, -+ audio_mode->channel_count - 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ MAX_CHANNELS); -+ -+ set_reg_field_value(value, -+ sample_rates.all, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ SUPPORTED_FREQUENCIES); -+ -+ set_reg_field_value(value, -+ byte2, -+ AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, -+ DESCRIPTOR_BYTE_2); -+ -+ } /* if */ -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + -+ format_index, -+ value); -+ } /* for */ -+ -+ if (is_ac3_supported) -+ dal_write_reg(hw_ctx->ctx, -+ mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, -+ 0x05); -+ -+ /* check for 192khz/8-Ch support for HBR requirements */ -+ sample_rate.all = 0; -+ sample_rate.rate.RATE_192 = 1; -+ dal_hw_ctx_audio_check_audio_bandwidth( -+ hw_ctx, -+ crtc_info, -+ 8, -+ signal, -+ &sample_rate); -+ -+ set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192); -+ -+ /* Audio and Video Lipsync */ -+ set_video_latency(hw_ctx, audio_info->video_latency); -+ set_audio_latency(hw_ctx, audio_info->audio_latency); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->manufacture_id, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ MANUFACTURER_ID); -+ -+ set_reg_field_value(value, audio_info->product_id, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ PRODUCT_ID); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, -+ value); -+ -+ -+ value = 0; -+ -+ /*get display name string length */ -+ while (audio_info->display_name[strlen++] != '\0') { -+ if (strlen >= -+ MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS) -+ break; -+ } -+ set_reg_field_value(value, strlen, -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, -+ SINK_DESCRIPTION_LEN); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, -+ value); -+ -+ -+ /* -+ *write the port ID: -+ *PORT_ID0 = display index -+ *PORT_ID1 = 16bit BDF -+ *(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function) -+ */ -+ -+ value = 0; -+ -+ set_reg_field_value(value, audio_info->port_id[0], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, -+ PORT_ID0); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->port_id[1], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, -+ PORT_ID1); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, -+ value); -+ -+ /*write the 18 char monitor string */ -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[0], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION0); -+ -+ set_reg_field_value(value, audio_info->display_name[1], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION1); -+ -+ set_reg_field_value(value, audio_info->display_name[2], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION2); -+ -+ set_reg_field_value(value, audio_info->display_name[3], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ DESCRIPTION3); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, -+ value); -+ -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[4], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION4); -+ -+ set_reg_field_value(value, audio_info->display_name[5], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION5); -+ -+ set_reg_field_value(value, audio_info->display_name[6], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION6); -+ -+ set_reg_field_value(value, audio_info->display_name[7], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ DESCRIPTION7); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[8], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION8); -+ -+ set_reg_field_value(value, audio_info->display_name[9], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION9); -+ -+ set_reg_field_value(value, audio_info->display_name[10], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION10); -+ -+ set_reg_field_value(value, audio_info->display_name[11], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ DESCRIPTION11); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[12], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION12); -+ -+ set_reg_field_value(value, audio_info->display_name[13], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION13); -+ -+ set_reg_field_value(value, audio_info->display_name[14], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION14); -+ -+ set_reg_field_value(value, audio_info->display_name[15], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ DESCRIPTION15); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, -+ value); -+ -+ -+ value = 0; -+ set_reg_field_value(value, audio_info->display_name[16], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ DESCRIPTION16); -+ -+ set_reg_field_value(value, audio_info->display_name[17], -+ AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ DESCRIPTION17); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, -+ value); -+ -+} -+ -+/* setup Azalia HW block */ -+static void setup_azalia( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info, -+ const struct audio_info *audio_info) -+{ -+ uint32_t speakers = 0; -+ uint32_t channels = 0; -+ -+ if (audio_info == NULL) -+ /* This should not happen.it does so we don't get BSOD*/ -+ return; -+ -+ speakers = audio_info->flags.info.ALLSPEAKERS; -+ channels = dal_audio_hw_ctx_speakers_to_channels( -+ hw_ctx, -+ audio_info->flags.speaker_flags).all; -+ -+ /* setup the audio stream source select (audio -> dig mapping) */ -+ { -+ const uint32_t addr = -+ mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ /*convert one-based index to zero-based */ -+ set_reg_field_value(value, -+ FROM_BASE(hw_ctx)->azalia_stream_id - 1, -+ AFMT_AUDIO_SRC_CONTROL, -+ AFMT_AUDIO_SRC_SELECT); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /* Channel allocation */ -+ { -+ const uint32_t addr = -+ mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; -+ uint32_t value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, -+ channels, -+ AFMT_AUDIO_PACKET_CONTROL2, -+ AFMT_AUDIO_CHANNEL_ENABLE); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ configure_azalia(hw_ctx, signal, crtc_info, audio_info); -+} -+ -+/* unmute audio */ -+static void unmute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* mute audio */ -+static void mute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL + -+ engine_offset[engine_id]; -+ -+ uint32_t value = 0; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+} -+ -+/* enable channel splitting mapping */ -+static void setup_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ uint32_t value = 0; -+ -+ if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable) -+ return; -+ -+ -+ value = audio_mapping->u32all; -+ -+ if (enable == false) -+ /*0xFFFFFFFF;*/ -+ value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO; -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO, -+ value); -+} -+ -+/* get current channel spliting */ -+static bool get_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ uint32_t value = 0; -+ -+ if (audio_mapping == NULL) -+ return false; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO); -+ -+ /*0xFFFFFFFF*/ -+ if (get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO, -+ ASSOCIATION_INFO) != -+ MULTI_CHANNEL_SPLIT_NO_ASSO_INFO) { -+ uint32_t multi_channel01_enable = 0; -+ uint32_t multi_channel23_enable = 0; -+ uint32_t multi_channel45_enable = 0; -+ uint32_t multi_channel67_enable = 0; -+ /* get the one we set.*/ -+ audio_mapping->u32all = value; -+ -+ /* check each enable status*/ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE); -+ -+ multi_channel01_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL01_ENABLE); -+ -+ multi_channel23_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL23_ENABLE); -+ -+ multi_channel45_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL45_ENABLE); -+ -+ multi_channel67_enable = get_reg_field_value(value, -+ AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE, -+ MULTICHANNEL67_ENABLE); -+ -+ if (multi_channel01_enable == 0 && -+ multi_channel23_enable == 0 && -+ multi_channel45_enable == 0 && -+ multi_channel67_enable == 0) -+ dal_logger_write(hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Audio driver did not enable multi-channel\n"); -+ -+ return true; -+ } -+ -+ return false; -+} -+ -+/* set the payload value for the unsolicited response */ -+static void set_unsolicited_response_payload( -+ const struct hw_ctx_audio *hw_ctx, -+ enum audio_payload payload) -+{ -+ /* set the payload value for the unsolicited response -+ Jack presence is not required to be enabled */ -+ uint32_t value = 0; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE); -+ -+ set_reg_field_value(value, payload, -+ AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ UNSOLICITED_RESPONSE_PAYLOAD); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ UNSOLICITED_RESPONSE_FORCE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, -+ value); -+} -+ -+/* initialize HW state */ -+static void hw_initialize( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id; -+ uint32_t addr; -+ -+ /* we only need to program the following registers once, so we only do -+ it for the first audio stream.*/ -+ if (stream_id != FIRST_AUDIO_STREAM_ID) -+ return; -+ -+ /* Suport R5 - 32khz -+ * Suport R6 - 44.1khz -+ * Suport R7 - 48khz -+ */ -+ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES; -+ { -+ uint32_t value; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 0x70, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, -+ AUDIO_RATE_CAPABILITIES); -+ -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+ -+ /*Keep alive bit to verify HW block in BU. */ -+ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES; -+ { -+ uint32_t value; -+ -+ value = dal_read_reg(hw_ctx->ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, -+ CLKSTOP); -+ -+ set_reg_field_value(value, 1, -+ AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, -+ EPSS); -+ dal_write_reg(hw_ctx->ctx, addr, value); -+ } -+} -+ -+/* Assign GTC group and enable GTC value embedding */ -+static void enable_gtc_embedding_with_group( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t group_num, -+ uint32_t audio_latency) -+{ -+ /*need to replace the static number with variable */ -+ if (group_num <= 6) { -+ uint32_t value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); -+ -+ set_reg_field_value( -+ value, -+ group_num, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_GROUP); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_ENABLE); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ value); -+ -+ /*update audio latency to LIPSYNC*/ -+ set_audio_latency(hw_ctx, audio_latency); -+ } else { -+ dal_logger_write( -+ hw_ctx->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "GTC group number %d is too big", -+ group_num); -+ } -+} -+ -+ /* Disable GTC value embedding */ -+static void disable_gtc_embedding( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ uint32_t value = 0; -+ -+ value = read_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_ENABLE); -+ -+ set_reg_field_value(value, 0, -+ AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ PRESENTATION_TIME_EMBEDDING_GROUP); -+ -+ write_indirect_azalia_reg( -+ hw_ctx, -+ ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, -+ value); -+} -+ -+/* search pixel clock value for Azalia HDMI Audio */ -+static bool get_azalia_clock_info_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ if (azalia_clock_info == NULL) -+ return false; -+ -+ /* audio_dto_phase= 24 * 10,000; -+ * 24MHz in [100Hz] units */ -+ azalia_clock_info->audio_dto_phase = -+ 24 * 10000; -+ -+ /* audio_dto_module = PCLKFrequency * 10,000; -+ * [khz] -> [100Hz] */ -+ azalia_clock_info->audio_dto_module = -+ actual_pixel_clock_in_khz * 10; -+ -+ return true; -+} -+ -+/* search pixel clock value for Azalia DP Audio */ -+static bool get_azalia_clock_info_dp( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ if (pll_info == NULL || azalia_clock_info == NULL) -+ return false; -+ -+ /* Reported dpDtoSourceClockInkhz value for -+ * DCE8 already adjusted for SS, do not need any -+ * adjustment here anymore -+ */ -+ -+ /*audio_dto_phase = 24 * 10,000; -+ * 24MHz in [100Hz] units */ -+ azalia_clock_info->audio_dto_phase = 24 * 10000; -+ -+ /*audio_dto_module = dpDtoSourceClockInkhz * 10,000; -+ * [khz] ->[100Hz] */ -+ azalia_clock_info->audio_dto_module = -+ pll_info->dp_dto_source_clock_in_khz * 10; -+ -+ return true; -+} -+ -+static const struct hw_ctx_audio_funcs funcs = { -+ .destroy = destroy, -+ .setup_audio_wall_dto = -+ setup_audio_wall_dto, -+ .setup_hdmi_audio = -+ setup_hdmi_audio, -+ .setup_dp_audio = setup_dp_audio, -+ .setup_vce_audio = setup_vce_audio, -+ .enable_azalia_audio = -+ enable_azalia_audio, -+ .disable_azalia_audio = -+ disable_azalia_audio, -+ .enable_dp_audio = -+ enable_dp_audio, -+ .disable_dp_audio = -+ disable_dp_audio, -+ .setup_azalia = -+ setup_azalia, -+ .disable_az_clock_gating = NULL, -+ .unmute_azalia_audio = -+ unmute_azalia_audio, -+ .mute_azalia_audio = -+ mute_azalia_audio, -+ .setup_channel_splitting_mapping = -+ setup_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .hw_initialize = -+ hw_initialize, -+ .enable_gtc_embedding_with_group = -+ enable_gtc_embedding_with_group, -+ .disable_gtc_embedding = -+ disable_gtc_embedding, -+ .get_azalia_clock_info_hdmi = -+ get_azalia_clock_info_hdmi, -+ .get_azalia_clock_info_dp = -+ get_azalia_clock_info_dp, -+ .enable_afmt_clock = enable_afmt_clock -+}; -+ -+static bool construct( -+ struct hw_ctx_audio_dce110 *hw_ctx, -+ uint8_t azalia_stream_id, -+ struct dc_context *ctx) -+{ -+ struct hw_ctx_audio *base = &hw_ctx->base; -+ -+ if (!dal_audio_construct_hw_ctx_audio(base)) -+ return false; -+ -+ base->funcs = &funcs; -+ -+ /* save audio endpoint or dig front for current dce110 audio object */ -+ hw_ctx->azalia_stream_id = azalia_stream_id; -+ hw_ctx->base.ctx = ctx; -+ -+ /* azalia audio endpoints register offsets. azalia is associated with -+ DIG front. save AUDIO register offset */ -+ switch (azalia_stream_id) { -+ case 1: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 2: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 3: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ case 4: { -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_index = -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX; -+ hw_ctx->az_mm_reg_offsets. -+ azf0endpointx_azalia_f0_codec_endpoint_data = -+ mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA; -+ } -+ break; -+ default: -+ dal_logger_write( -+ hw_ctx->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Invalid Azalia stream ID!"); -+ break; -+ } -+ -+ return true; -+} -+ -+/* audio_dce110 is derived from audio directly, not via dce80 */ -+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create( -+ struct dc_context *ctx, -+ uint32_t azalia_stream_id) -+{ -+ /* allocate memory for struc hw_ctx_audio_dce110 */ -+ struct hw_ctx_audio_dce110 *hw_ctx_dce110 = -+ dc_service_alloc(ctx, sizeof(struct hw_ctx_audio_dce110)); -+ -+ if (!hw_ctx_dce110) { -+ ASSERT_CRITICAL(hw_ctx_dce110); -+ return NULL; -+ } -+ -+ /*return pointer to hw_ctx_audio back to caller -- audio object */ -+ if (construct( -+ hw_ctx_dce110, azalia_stream_id, ctx)) -+ return &hw_ctx_dce110->base; -+ -+ dal_logger_write( -+ ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_AUDIO, -+ "Failed to create hw_ctx_audio for DCE11\n"); -+ -+ -+ dc_service_free(ctx, hw_ctx_dce110); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h -new file mode 100644 -index 0000000..1ad3826 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_CTX_AUDIO_DCE110_H__ -+#define __DAL_HW_CTX_AUDIO_DCE110_H__ -+ -+#include "audio/hw_ctx_audio.h" -+ -+struct hw_ctx_audio_dce110 { -+ struct hw_ctx_audio base; -+ -+ /* azalia stream id 1 based indexing, corresponding to audio GO enumId*/ -+ uint32_t azalia_stream_id; -+ -+ /* azalia stream endpoint register offsets */ -+ struct azalia_reg_offsets az_mm_reg_offsets; -+ -+ /* audio encoder block MM register offset -- associate with DIG FRONT */ -+}; -+ -+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create( -+ struct dc_context *ctx, -+ uint32_t azalia_stream_id); -+ -+#endif /* __DAL_HW_CTX_AUDIO_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c -new file mode 100644 -index 0000000..f1f1298 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c -@@ -0,0 +1,771 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "hw_ctx_audio.h" -+ -+/* 25.2MHz/1.001*/ -+/* 25.2MHz/1.001*/ -+/* 25.2MHz*/ -+/* 27MHz */ -+/* 27MHz*1.001*/ -+/* 27MHz*1.001*/ -+/* 54MHz*/ -+/* 54MHz*1.001*/ -+/* 74.25MHz/1.001*/ -+/* 74.25MHz*/ -+/* 148.5MHz/1.001*/ -+/* 148.5MHz*/ -+ -+static const struct audio_clock_info audio_clock_info_table[12] = { -+ {2517, 4576, 28125, 7007, 31250, 6864, 28125}, -+ {2518, 4576, 28125, 7007, 31250, 6864, 28125}, -+ {2520, 4096, 25200, 6272, 28000, 6144, 25200}, -+ {2700, 4096, 27000, 6272, 30000, 6144, 27000}, -+ {2702, 4096, 27027, 6272, 30030, 6144, 27027}, -+ {2703, 4096, 27027, 6272, 30030, 6144, 27027}, -+ {5400, 4096, 54000, 6272, 60000, 6144, 54000}, -+ {5405, 4096, 54054, 6272, 60060, 6144, 54054}, -+ {7417, 11648, 210937, 17836, 234375, 11648, 140625}, -+ {7425, 4096, 74250, 6272, 82500, 6144, 74250}, -+ {14835, 11648, 421875, 8918, 234375, 5824, 140625}, -+ {14850, 4096, 148500, 6272, 165000, 6144, 148500} -+}; -+ -+static const struct audio_clock_info audio_clock_info_table_36bpc[12] = { -+ {2517, 9152, 84375, 7007, 48875, 9152, 56250}, -+ {2518, 9152, 84375, 7007, 48875, 9152, 56250}, -+ {2520, 4096, 37800, 6272, 42000, 6144, 37800}, -+ {2700, 4096, 40500, 6272, 45000, 6144, 40500}, -+ {2702, 8192, 81081, 6272, 45045, 8192, 54054}, -+ {2703, 8192, 81081, 6272, 45045, 8192, 54054}, -+ {5400, 4096, 81000, 6272, 90000, 6144, 81000}, -+ {5405, 4096, 81081, 6272, 90090, 6144, 81081}, -+ {7417, 11648, 316406, 17836, 351562, 11648, 210937}, -+ {7425, 4096, 111375, 6272, 123750, 6144, 111375}, -+ {14835, 11648, 632812, 17836, 703125, 11648, 421875}, -+ {14850, 4096, 222750, 6272, 247500, 6144, 222750} -+}; -+ -+static const struct audio_clock_info audio_clock_info_table_48bpc[12] = { -+ {2517, 4576, 56250, 7007, 62500, 6864, 56250}, -+ {2518, 4576, 56250, 7007, 62500, 6864, 56250}, -+ {2520, 4096, 50400, 6272, 56000, 6144, 50400}, -+ {2700, 4096, 54000, 6272, 60000, 6144, 54000}, -+ {2702, 4096, 54054, 6267, 60060, 8192, 54054}, -+ {2703, 4096, 54054, 6272, 60060, 8192, 54054}, -+ {5400, 4096, 108000, 6272, 120000, 6144, 108000}, -+ {5405, 4096, 108108, 6272, 120120, 6144, 108108}, -+ {7417, 11648, 421875, 17836, 468750, 11648, 281250}, -+ {7425, 4096, 148500, 6272, 165000, 6144, 148500}, -+ {14835, 11648, 843750, 8918, 468750, 11648, 281250}, -+ {14850, 4096, 297000, 6272, 330000, 6144, 297000} -+}; -+ -+ -+/***** static function *****/ -+ -+/* -+ * except of HW context create function, caller will access other functions of -+ * hw ctx via handle hw_ctx. Memory allocation for struct hw_ctx_audio_dce8x -+ * will happen in hw_ctx_audio_dce8x. Memory allocation is done with -+ * dal_audio_create_hw_ctx_audio_dce8x. Memory release is done by caller -+ * via hw_ctx->functions.destroy(). It will finally use destroy() of -+ * hw_ctx_audio_dce8x. Therefore, no memory allocate and release happen -+ * physically at hw ctx base object. -+ */ -+static void destroy( -+ struct hw_ctx_audio **ptr) -+{ -+ /* Attention! -+ * You must override this method in derived class */ -+} -+ -+static void setup_audio_wall_dto( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* setup HDMI audio */ -+static void setup_hdmi_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ const struct audio_crtc_info *crtc_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+ /* setup DP audio */ -+static void setup_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+ /* setup VCE audio */ -+static void setup_vce_audio( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* enable Azalia audio */ -+static void enable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* disable Azalia audio */ -+static void disable_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* enable DP audio */ -+static void enable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* disable DP audio */ -+static void disable_dp_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* setup Azalia HW block */ -+static void setup_azalia( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info, -+ const struct audio_info *audio_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* unmute audio */ -+static void unmute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* mute audio */ -+static void mute_azalia_audio( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* enable channel splitting mapping */ -+static void setup_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* get current channel spliting */ -+static bool get_channel_splitting_mapping( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return false; -+} -+ -+/* set the payload value for the unsolicited response */ -+static void set_unsolicited_response_payload( -+ const struct hw_ctx_audio *hw_ctx, -+ enum audio_payload payload) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* initialize HW state */ -+static void hw_initialize( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* Assign GTC group and enable GTC value embedding */ -+static void enable_gtc_embedding_with_group( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t groupNum, -+ uint32_t audioLatency) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* Disable GTC value embedding */ -+static void disable_gtc_embedding( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* Disable Azalia Clock Gating Feature */ -+static void disable_az_clock_gating( -+ const struct hw_ctx_audio *hw_ctx) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+} -+ -+/* search pixel clock value for Azalia HDMI Audio */ -+static bool get_azalia_clock_info_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return false; -+} -+ -+/* search pixel clock value for Azalia DP Audio */ -+static bool get_azalia_clock_info_dp( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info) -+{ -+ /*DCE specific, must be implemented in derived*/ -+ BREAK_TO_DEBUGGER(); -+ return false; -+} -+ -+ -+ -+ -+ -+ -+ -+ -+ -+/*****SCOPE : within audio hw context dal-audio-hw-ctx *****/ -+ -+ -+/* check whether specified sample rates can fit into a given timing */ -+void dal_hw_ctx_audio_check_audio_bandwidth( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ enum signal_type signal, -+ union audio_sample_rates *sample_rates) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ dal_audio_hw_ctx_check_audio_bandwidth_hdmi( -+ hw_ctx, crtc_info, channel_count, sample_rates); -+ break; -+ case SIGNAL_TYPE_EDP: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ dal_audio_hw_ctx_check_audio_bandwidth_dpsst( -+ hw_ctx, crtc_info, channel_count, sample_rates); -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ dal_audio_hw_ctx_check_audio_bandwidth_dpmst( -+ hw_ctx, crtc_info, channel_count, sample_rates); -+ break; -+ default: -+ break; -+ } -+} -+ -+/*For HDMI, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates) -+{ -+ uint32_t samples; -+ uint32_t h_blank; -+ bool limit_freq_to_48_khz = false; -+ bool limit_freq_to_88_2_khz = false; -+ bool limit_freq_to_96_khz = false; -+ bool limit_freq_to_174_4_khz = false; -+ -+ /* For two channels supported return whatever sink support,unmodified*/ -+ if (channel_count > 2) { -+ -+ /* Based on HDMI spec 1.3 Table 7.5 */ -+ if ((crtc_info->requested_pixel_clock <= 27000) && -+ (crtc_info->v_active <= 576) && -+ !(crtc_info->interlaced) && -+ !(crtc_info->pixel_repetition == 2 || -+ crtc_info->pixel_repetition == 4)) { -+ limit_freq_to_48_khz = true; -+ -+ } else if ((crtc_info->requested_pixel_clock <= 27000) && -+ (crtc_info->v_active <= 576) && -+ (crtc_info->interlaced) && -+ (crtc_info->pixel_repetition == 2)) { -+ limit_freq_to_88_2_khz = true; -+ -+ } else if ((crtc_info->requested_pixel_clock <= 54000) && -+ (crtc_info->v_active <= 576) && -+ !(crtc_info->interlaced)) { -+ limit_freq_to_174_4_khz = true; -+ } -+ } -+ -+ /* Also do some calculation for the available Audio Bandwidth for the -+ * 8 ch (i.e. for the Layout 1 => ch > 2) -+ */ -+ h_blank = crtc_info->h_total - crtc_info->h_active; -+ -+ if (crtc_info->pixel_repetition) -+ h_blank *= crtc_info->pixel_repetition; -+ -+ /*based on HDMI spec 1.3 Table 7.5 */ -+ h_blank -= 58; -+ /*for Control Period */ -+ h_blank -= 16; -+ -+ samples = h_blank * 10; -+ /* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number -+ * of Audio samples per line multiplied by 10 - Layout 1) -+ */ -+ samples /= 32; -+ samples *= crtc_info->v_active; -+ /*Number of samples multiplied by 10, per second */ -+ samples *= crtc_info->refresh_rate; -+ /*Number of Audio samples per second */ -+ samples /= 10; -+ -+ /* @todo do it after deep color is implemented -+ * 8xx - deep color bandwidth scaling -+ * Extra bandwidth is avaliable in deep color b/c link runs faster than -+ * pixel rate. This has the effect of allowing more tmds characters to -+ * be transmitted during blank -+ */ -+ -+ switch (crtc_info->color_depth) { -+ case COLOR_DEPTH_888: -+ samples *= 4; -+ break; -+ case COLOR_DEPTH_101010: -+ samples *= 5; -+ break; -+ case COLOR_DEPTH_121212: -+ samples *= 6; -+ break; -+ default: -+ samples *= 4; -+ break; -+ } -+ -+ samples /= 4; -+ -+ /*check limitation*/ -+ if (samples < 88200) -+ limit_freq_to_48_khz = true; -+ else if (samples < 96000) -+ limit_freq_to_88_2_khz = true; -+ else if (samples < 176400) -+ limit_freq_to_96_khz = true; -+ else if (samples < 192000) -+ limit_freq_to_174_4_khz = true; -+ -+ if (sample_rates != NULL) { -+ /* limit frequencies */ -+ if (limit_freq_to_174_4_khz) -+ sample_rates->rate.RATE_192 = 0; -+ -+ if (limit_freq_to_96_khz) { -+ sample_rates->rate.RATE_192 = 0; -+ sample_rates->rate.RATE_176_4 = 0; -+ } -+ if (limit_freq_to_88_2_khz) { -+ sample_rates->rate.RATE_192 = 0; -+ sample_rates->rate.RATE_176_4 = 0; -+ sample_rates->rate.RATE_96 = 0; -+ } -+ if (limit_freq_to_48_khz) { -+ sample_rates->rate.RATE_192 = 0; -+ sample_rates->rate.RATE_176_4 = 0; -+ sample_rates->rate.RATE_96 = 0; -+ sample_rates->rate.RATE_88_2 = 0; -+ } -+ } -+} -+ -+/*For DP SST, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates) -+{ -+ /* do nothing */ -+} -+ -+/*For DP MST, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates) -+{ -+ /* do nothing */ -+} -+ -+/* calculate max number of Audio packets per line */ -+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info) -+{ -+ uint32_t max_packets_per_line; -+ -+ max_packets_per_line = -+ crtc_info->h_total - crtc_info->h_active; -+ -+ if (crtc_info->pixel_repetition) -+ max_packets_per_line *= crtc_info->pixel_repetition; -+ -+ /* for other hdmi features */ -+ max_packets_per_line -= 58; -+ /* for Control Period */ -+ max_packets_per_line -= 16; -+ /* Number of Audio Packets per Line */ -+ max_packets_per_line /= 32; -+ -+ return max_packets_per_line; -+} -+ -+/** -+* speakersToChannels -+* -+* @brief -+* translate speakers to channels -+* -+* FL - Front Left -+* FR - Front Right -+* RL - Rear Left -+* RR - Rear Right -+* RC - Rear Center -+* FC - Front Center -+* FLC - Front Left Center -+* FRC - Front Right Center -+* RLC - Rear Left Center -+* RRC - Rear Right Center -+* LFE - Low Freq Effect -+* -+* FC -+* FLC FRC -+* FL FR -+* -+* LFE -+* () -+* -+* -+* RL RR -+* RLC RRC -+* RC -+* -+* ch 8 7 6 5 4 3 2 1 -+* 0b00000011 - - - - - - FR FL -+* 0b00000111 - - - - - LFE FR FL -+* 0b00001011 - - - - FC - FR FL -+* 0b00001111 - - - - FC LFE FR FL -+* 0b00010011 - - - RC - - FR FL -+* 0b00010111 - - - RC - LFE FR FL -+* 0b00011011 - - - RC FC - FR FL -+* 0b00011111 - - - RC FC LFE FR FL -+* 0b00110011 - - RR RL - - FR FL -+* 0b00110111 - - RR RL - LFE FR FL -+* 0b00111011 - - RR RL FC - FR FL -+* 0b00111111 - - RR RL FC LFE FR FL -+* 0b01110011 - RC RR RL - - FR FL -+* 0b01110111 - RC RR RL - LFE FR FL -+* 0b01111011 - RC RR RL FC - FR FL -+* 0b01111111 - RC RR RL FC LFE FR FL -+* 0b11110011 RRC RLC RR RL - - FR FL -+* 0b11110111 RRC RLC RR RL - LFE FR FL -+* 0b11111011 RRC RLC RR RL FC - FR FL -+* 0b11111111 RRC RLC RR RL FC LFE FR FL -+* 0b11000011 FRC FLC - - - - FR FL -+* 0b11000111 FRC FLC - - - LFE FR FL -+* 0b11001011 FRC FLC - - FC - FR FL -+* 0b11001111 FRC FLC - - FC LFE FR FL -+* 0b11010011 FRC FLC - RC - - FR FL -+* 0b11010111 FRC FLC - RC - LFE FR FL -+* 0b11011011 FRC FLC - RC FC - FR FL -+* 0b11011111 FRC FLC - RC FC LFE FR FL -+* 0b11110011 FRC FLC RR RL - - FR FL -+* 0b11110111 FRC FLC RR RL - LFE FR FL -+* 0b11111011 FRC FLC RR RL FC - FR FL -+* 0b11111111 FRC FLC RR RL FC LFE FR FL -+* -+* @param -+* speakers - speaker information as it comes from CEA audio block -+*/ -+/* translate speakers to channels */ -+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels( -+ const struct hw_ctx_audio *hw_ctx, -+ struct audio_speaker_flags speaker_flags) -+{ -+ union audio_cea_channels cea_channels = {0}; -+ -+ /* these are one to one */ -+ cea_channels.channels.FL = speaker_flags.FL_FR; -+ cea_channels.channels.FR = speaker_flags.FL_FR; -+ cea_channels.channels.LFE = speaker_flags.LFE; -+ cea_channels.channels.FC = speaker_flags.FC; -+ -+ /* if Rear Left and Right exist move RC speaker to channel 7 -+ * otherwise to channel 5 -+ */ -+ if (speaker_flags.RL_RR) { -+ cea_channels.channels.RL_RC = speaker_flags.RL_RR; -+ cea_channels.channels.RR = speaker_flags.RL_RR; -+ cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; -+ } else { -+ cea_channels.channels.RL_RC = speaker_flags.RC; -+ } -+ -+ /* FRONT Left Right Center and REAR Left Right Center are exclusive */ -+ if (speaker_flags.FLC_FRC) { -+ cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; -+ cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; -+ } else { -+ cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; -+ cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; -+ } -+ -+ return cea_channels; -+} -+ -+/* check whether specified audio format supported */ -+bool dal_audio_hw_ctx_is_audio_format_supported( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_info *audio_info, -+ enum audio_format_code audio_format_code, -+ uint32_t *format_index) -+{ -+ uint32_t index; -+ uint32_t max_channe_index = 0; -+ bool found = false; -+ -+ if (audio_info == NULL) -+ return found; -+ -+ /* pass through whole array */ -+ for (index = 0; index < audio_info->mode_count; index++) { -+ if (audio_info->modes[index].format_code == audio_format_code) { -+ if (found) { -+ /* format has multiply entries, choose one with -+ * highst number of channels */ -+ if (audio_info->modes[index].channel_count > -+ audio_info->modes[max_channe_index].channel_count) { -+ max_channe_index = index; -+ } -+ } else { -+ /* format found, save it's index */ -+ found = true; -+ max_channe_index = index; -+ } -+ } -+ } -+ -+ /* return index */ -+ if (found && format_index != NULL) -+ *format_index = max_channe_index; -+ -+ return found; -+} -+ -+/* search pixel clock value for HDMI */ -+bool dal_audio_hw_ctx_get_audio_clock_info( -+ const struct hw_ctx_audio *hw_ctx, -+ enum dc_color_depth color_depth, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct audio_clock_info *audio_clock_info) -+{ -+ const struct audio_clock_info *clock_info; -+ uint32_t index; -+ uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; -+ uint32_t audio_array_size; -+ -+ if (audio_clock_info == NULL) -+ return false; /* should not happen */ -+ -+ switch (color_depth) { -+ case COLOR_DEPTH_161616: -+ clock_info = audio_clock_info_table_48bpc; -+ audio_array_size = ARRAY_SIZE( -+ audio_clock_info_table_48bpc); -+ break; -+ case COLOR_DEPTH_121212: -+ clock_info = audio_clock_info_table_36bpc; -+ audio_array_size = ARRAY_SIZE( -+ audio_clock_info_table_36bpc); -+ break; -+ default: -+ clock_info = audio_clock_info_table; -+ audio_array_size = ARRAY_SIZE( -+ audio_clock_info_table); -+ break; -+ } -+ -+ if (clock_info != NULL) { -+ /* search for exact pixel clock in table */ -+ for (index = 0; index < audio_array_size; index++) { -+ if (clock_info[index].pixel_clock_in_10khz > -+ crtc_pixel_clock_in_10khz) -+ break; /* not match */ -+ else if (clock_info[index].pixel_clock_in_10khz == -+ crtc_pixel_clock_in_10khz) { -+ /* match found */ -+ if (audio_clock_info != NULL) { -+ *audio_clock_info = clock_info[index]; -+ return true; -+ } -+ } -+ } -+ } -+ -+ -+ /* not found */ -+ if (actual_pixel_clock_in_khz == 0) -+ actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz; -+ -+ /* See HDMI spec the table entry under -+ * pixel clock of "Other". */ -+ audio_clock_info->pixel_clock_in_10khz = -+ actual_pixel_clock_in_khz / 10; -+ audio_clock_info->cts_32khz = actual_pixel_clock_in_khz; -+ audio_clock_info->cts_44khz = actual_pixel_clock_in_khz; -+ audio_clock_info->cts_48khz = actual_pixel_clock_in_khz; -+ -+ audio_clock_info->n_32khz = 4096; -+ audio_clock_info->n_44khz = 6272; -+ audio_clock_info->n_48khz = 6144; -+ -+ return true; -+} -+ -+static const struct hw_ctx_audio_funcs funcs = { -+ .destroy = destroy, -+ .setup_audio_wall_dto = -+ setup_audio_wall_dto, -+ .setup_hdmi_audio = -+ setup_hdmi_audio, -+ .setup_dp_audio = setup_dp_audio, -+ .setup_vce_audio = setup_vce_audio, -+ .enable_azalia_audio = -+ enable_azalia_audio, -+ .disable_azalia_audio = -+ disable_azalia_audio, -+ .enable_dp_audio = -+ enable_dp_audio, -+ .disable_dp_audio = -+ disable_dp_audio, -+ .setup_azalia = -+ setup_azalia, -+ .disable_az_clock_gating = -+ disable_az_clock_gating, -+ .unmute_azalia_audio = -+ unmute_azalia_audio, -+ .mute_azalia_audio = -+ mute_azalia_audio, -+ .setup_channel_splitting_mapping = -+ setup_channel_splitting_mapping, -+ .get_channel_splitting_mapping = -+ get_channel_splitting_mapping, -+ .set_unsolicited_response_payload = -+ set_unsolicited_response_payload, -+ .hw_initialize = -+ hw_initialize, -+ .enable_gtc_embedding_with_group = -+ enable_gtc_embedding_with_group, -+ .disable_gtc_embedding = -+ disable_gtc_embedding, -+ .get_azalia_clock_info_hdmi = -+ get_azalia_clock_info_hdmi, -+ .get_azalia_clock_info_dp = -+ get_azalia_clock_info_dp, -+}; -+/* --- object creator, destroy, construct, destruct --- */ -+ -+bool dal_audio_construct_hw_ctx_audio( -+ struct hw_ctx_audio *ctx) -+{ -+ ctx->funcs = &funcs; -+ -+ /* internal variables */ -+ -+ return true; -+} -+ -+void dal_audio_destruct_hw_ctx_audio( -+ struct hw_ctx_audio *ctx) -+{ -+ /* nothing to do */ -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h -new file mode 100644 -index 0000000..8ab2e58 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h -@@ -0,0 +1,285 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_CTX_AUDIO_H__ -+#define __DAL_HW_CTX_AUDIO_H__ -+ -+#include "include/audio_interface.h" -+#include "include/link_service_types.h" -+ -+struct hw_ctx_audio; -+ -+ -+struct azalia_reg_offsets { -+ uint32_t azf0endpointx_azalia_f0_codec_endpoint_index; -+ uint32_t azf0endpointx_azalia_f0_codec_endpoint_data; -+}; -+ -+/***** hook functions *****/ -+ -+struct hw_ctx_audio_funcs { -+ -+ /* functions for hw_ctx creation */ -+ void (*destroy)( -+ struct hw_ctx_audio **ptr); -+ -+ /***** from dal2 hwcontextaudio.hpp *****/ -+ -+ void (*setup_audio_wall_dto)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info); -+ -+ /* MM register access read_register write_register */ -+ -+ /***** from dal2 hwcontextaudio_hal.hpp *****/ -+ -+ /* setup HDMI audio */ -+ void (*setup_hdmi_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ const struct audio_crtc_info *crtc_info); -+ -+ /* setup DP audio */ -+ void (*setup_dp_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* setup VCE audio */ -+ void (*setup_vce_audio)( -+ const struct hw_ctx_audio *hw_ctx); -+ -+ /* enable Azalia audio */ -+ void (*enable_azalia_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* disable Azalia audio */ -+ void (*disable_azalia_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* enable DP audio */ -+ void (*enable_dp_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* disable DP audio */ -+ void (*disable_dp_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* setup Azalia HW block */ -+ void (*setup_azalia)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info, -+ const struct audio_info *audio_info); -+ -+ /* unmute audio */ -+ void (*unmute_azalia_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* mute audio */ -+ void (*mute_azalia_audio)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id); -+ -+ /* enable channel splitting mapping */ -+ void (*setup_channel_splitting_mapping)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable); -+ -+ /* get current channel spliting */ -+ bool (*get_channel_splitting_mapping)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping); -+ -+ /* set the payload value for the unsolicited response */ -+ void (*set_unsolicited_response_payload)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum audio_payload payload); -+ -+ /* initialize HW state */ -+ void (*hw_initialize)( -+ const struct hw_ctx_audio *hw_ctx); -+ -+ /* check_audio_bandwidth */ -+ -+ /* Assign GTC group and enable GTC value embedding */ -+ void (*enable_gtc_embedding_with_group)( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t groupNum, -+ uint32_t audioLatency); -+ -+ /* Disable GTC value embedding */ -+ void (*disable_gtc_embedding)( -+ const struct hw_ctx_audio *hw_ctx); -+ -+ /* Disable Azalia Clock Gating Feature */ -+ void (*disable_az_clock_gating)( -+ const struct hw_ctx_audio *hw_ctx); -+ -+ /* ~~~~ protected: ~~~~*/ -+ -+ /* calc_max_audio_packets_per_line */ -+ /* speakers_to_channels */ -+ /* is_audio_format_supported */ -+ /* get_audio_clock_info */ -+ -+ /* search pixel clock value for Azalia HDMI Audio */ -+ bool (*get_azalia_clock_info_hdmi)( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct azalia_clock_info *azalia_clock_info); -+ -+ /* search pixel clock value for Azalia DP Audio */ -+ bool (*get_azalia_clock_info_dp)( -+ const struct hw_ctx_audio *hw_ctx, -+ uint32_t requested_pixel_clock_in_khz, -+ const struct audio_pll_info *pll_info, -+ struct azalia_clock_info *azalia_clock_info); -+ -+ void (*enable_afmt_clock)( -+ const struct hw_ctx_audio *hw_ctx, -+ enum engine_id engine_id, -+ bool enable); -+ -+ /* @@@@ private: @@@@ */ -+ -+ /* check_audio_bandwidth_hdmi */ -+ /* check_audio_bandwidth_dpsst */ -+ /* check_audio_bandwidth_dpmst */ -+ -+}; -+ -+ -+struct hw_ctx_audio { -+ const struct hw_ctx_audio_funcs *funcs; -+ struct dc_context *ctx; -+ -+ /*audio_clock_infoTable[12]; -+ *audio_clock_infoTable_36bpc[12]; -+ *audio_clock_infoTable_48bpc[12]; -+ *used by hw_ctx_audio.c file only. Will declare as static array -+ *azaliaclockinfoTable[12] -- not used -+ *BusNumberMask; BusNumberShift; DeviceNumberMask; -+ *not used by dce6 and after -+ */ -+}; -+ -+ -+ -+/* --- object construct, destruct --- */ -+ -+/* -+ *called by derived audio object for specific ASIC. In case no derived object, -+ *these two functions do not need exposed. -+ */ -+bool dal_audio_construct_hw_ctx_audio( -+ struct hw_ctx_audio *hw_ctx); -+ -+void dal_audio_destruct_hw_ctx_audio( -+ struct hw_ctx_audio *hw_ctx); -+ -+/* -+ *creator of audio HW context will be implemented by specific ASIC object only. -+ *Top base or interface object does not have implementation of creator. -+ */ -+ -+ -+/* --- functions called by audio hw context itself --- */ -+ -+/* MM register access */ -+/*read_register - dal_read_reg */ -+/*write_register - dal_write_reg*/ -+ -+ -+/*check whether specified sample rates can fit into a given timing */ -+void dal_hw_ctx_audio_check_audio_bandwidth( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ enum signal_type signal, -+ union audio_sample_rates *sample_rates); -+ -+/*For HDMI, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates); -+ -+/*For DPSST, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates); -+ -+/*For DPMST, calculate if specified sample rates can fit into a given timing */ -+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info, -+ uint32_t channel_count, -+ union audio_sample_rates *sample_rates); -+ -+/* calculate max number of Audio packets per line */ -+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_crtc_info *crtc_info); -+ -+/* translate speakers to channels */ -+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels( -+ const struct hw_ctx_audio *hw_ctx, -+ struct audio_speaker_flags speaker_flags); -+ -+/* check whether specified audio format supported */ -+bool dal_audio_hw_ctx_is_audio_format_supported( -+ const struct hw_ctx_audio *hw_ctx, -+ const struct audio_info *audio_info, -+ enum audio_format_code audio_format_code, -+ uint32_t *format_index); -+ -+/* search pixel clock value for HDMI */ -+bool dal_audio_hw_ctx_get_audio_clock_info( -+ const struct hw_ctx_audio *hw_ctx, -+ enum dc_color_depth color_depth, -+ uint32_t crtc_pixel_clock_in_khz, -+ uint32_t actual_pixel_clock_in_khz, -+ struct audio_clock_info *audio_clock_info); -+ -+ -+#endif /* __DAL_HW_CTX_AUDIO_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile -new file mode 100644 -index 0000000..93e2371 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile -@@ -0,0 +1,10 @@ -+# -+# Makefile for the 'utils' sub-component of DAL. -+# It provides the general basic services required by other DAL -+# subcomponents. -+ -+BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o -+ -+AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) -+ -+AMD_DAL_FILES += $(AMD_DAL_BASICS) -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.c b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c -new file mode 100644 -index 0000000..8c38206 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/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 "dal_services.h" -+ -+#define DIVIDER 10000 -+ -+/* S2D13 value in [-3.00...0.9999] */ -+#define S2D13_MIN (-3 * DIVIDER) -+#define S2D13_MAX (3 * DIVIDER) -+ -+uint16_t fixed_point_to_int_frac( -+ struct fixed31_32 arg, -+ uint8_t integer_bits, -+ uint8_t fractional_bits) -+{ -+ int32_t numerator; -+ int32_t divisor = 1 << fractional_bits; -+ -+ uint16_t result; -+ -+ uint16_t d = (uint16_t)dal_fixed31_32_floor( -+ dal_fixed31_32_abs( -+ arg)); -+ -+ if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) -+ numerator = (uint16_t)dal_fixed31_32_floor( -+ dal_fixed31_32_mul_int( -+ arg, -+ divisor)); -+ else { -+ numerator = dal_fixed31_32_floor( -+ dal_fixed31_32_sub( -+ dal_fixed31_32_from_int( -+ 1LL << integer_bits), -+ dal_fixed31_32_recip( -+ dal_fixed31_32_from_int( -+ divisor)))); -+ } -+ -+ if (numerator >= 0) -+ result = (uint16_t)numerator; -+ else -+ result = (uint16_t)( -+ (1 << (integer_bits + fractional_bits + 1)) + numerator); -+ -+ if ((result != 0) && dal_fixed31_32_lt( -+ arg, dal_fixed31_32_zero)) -+ result |= 1 << (integer_bits + fractional_bits); -+ -+ return result; -+} -+/** -+* convert_float_matrix -+* This converts a double into HW register spec defined format S2D13. -+* @param : -+* @return None -+*/ -+void convert_float_matrix( -+ uint16_t *matrix, -+ struct fixed31_32 *flt, -+ uint32_t buffer_size) -+{ -+ const struct fixed31_32 min_2_13 = -+ dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); -+ const struct fixed31_32 max_2_13 = -+ dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); -+ uint32_t i; -+ -+ for (i = 0; i < buffer_size; ++i) { -+ uint32_t reg_value = -+ fixed_point_to_int_frac( -+ dal_fixed31_32_clamp( -+ flt[i], -+ min_2_13, -+ max_2_13), -+ 2, -+ 13); -+ -+ matrix[i] = (uint16_t)reg_value; -+ } -+} -+ -+static void calculate_adjustments_common( -+ const struct fixed31_32 *ideal_matrix, -+ const struct dc_csc_adjustments *adjustments, -+ struct fixed31_32 *matrix) -+{ -+ const struct fixed31_32 sin_hue = -+ dal_fixed31_32_sin(adjustments->hue); -+ const struct fixed31_32 cos_hue = -+ dal_fixed31_32_cos(adjustments->hue); -+ -+ const struct fixed31_32 multiplier = -+ dal_fixed31_32_mul( -+ adjustments->contrast, -+ adjustments->saturation); -+ -+ matrix[0] = dal_fixed31_32_mul( -+ ideal_matrix[0], -+ adjustments->contrast); -+ -+ matrix[1] = dal_fixed31_32_mul( -+ ideal_matrix[1], -+ adjustments->contrast); -+ -+ matrix[2] = dal_fixed31_32_mul( -+ ideal_matrix[2], -+ adjustments->contrast); -+ -+ matrix[4] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ ideal_matrix[8], -+ sin_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[4], -+ cos_hue))); -+ -+ matrix[5] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ ideal_matrix[9], -+ sin_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[5], -+ cos_hue))); -+ -+ matrix[6] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ ideal_matrix[10], -+ sin_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[6], -+ cos_hue))); -+ -+ matrix[7] = ideal_matrix[7]; -+ -+ matrix[8] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_sub( -+ dal_fixed31_32_mul( -+ ideal_matrix[8], -+ cos_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[4], -+ sin_hue))); -+ -+ matrix[9] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_sub( -+ dal_fixed31_32_mul( -+ ideal_matrix[9], -+ cos_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[5], -+ sin_hue))); -+ -+ matrix[10] = dal_fixed31_32_mul( -+ multiplier, -+ dal_fixed31_32_sub( -+ dal_fixed31_32_mul( -+ ideal_matrix[10], -+ cos_hue), -+ dal_fixed31_32_mul( -+ ideal_matrix[6], -+ sin_hue))); -+ -+ matrix[11] = ideal_matrix[11]; -+} -+ -+void calculate_adjustments( -+ const struct fixed31_32 *ideal_matrix, -+ const struct dc_csc_adjustments *adjustments, -+ struct fixed31_32 *matrix) -+{ -+ calculate_adjustments_common(ideal_matrix, adjustments, matrix); -+ -+ matrix[3] = dal_fixed31_32_add( -+ ideal_matrix[3], -+ dal_fixed31_32_mul( -+ adjustments->brightness, -+ dal_fixed31_32_from_fraction(86, 100))); -+} -+ -+void calculate_adjustments_y_only( -+ const struct fixed31_32 *ideal_matrix, -+ const struct dc_csc_adjustments *adjustments, -+ struct fixed31_32 *matrix) -+{ -+ calculate_adjustments_common(ideal_matrix, adjustments, matrix); -+ -+ matrix[3] = dal_fixed31_32_add( -+ ideal_matrix[3], -+ adjustments->brightness); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.h b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h -new file mode 100644 -index 0000000..24ff473 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h -@@ -0,0 +1,49 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_CONVERSION_H__ -+#define __DAL_CONVERSION_H__ -+ -+uint16_t fixed_point_to_int_frac( -+ struct fixed31_32 arg, -+ uint8_t integer_bits, -+ uint8_t fractional_bits); -+ -+void convert_float_matrix( -+ uint16_t *matrix, -+ struct fixed31_32 *flt, -+ uint32_t buffer_size); -+ -+void calculate_adjustments( -+ const struct fixed31_32 *ideal_matrix, -+ const struct dc_csc_adjustments *adjustments, -+ struct fixed31_32 *matrix); -+ -+void calculate_adjustments_y_only( -+ const struct fixed31_32 *ideal_matrix, -+ const struct dc_csc_adjustments *adjustments, -+ struct fixed31_32 *matrix); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c -new file mode 100644 -index 0000000..6ce75b3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c -@@ -0,0 +1,692 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/fixed31_32.h" -+ -+static inline uint64_t abs_i64( -+ int64_t arg) -+{ -+ if (arg > 0) -+ return (uint64_t)arg; -+ else -+ return (uint64_t)(-arg); -+} -+ -+/* -+ * @brief -+ * result = dividend / divisor -+ * *remainder = dividend % divisor -+ */ -+static inline uint64_t complete_integer_division_u64( -+ uint64_t dividend, -+ uint64_t divisor, -+ uint64_t *remainder) -+{ -+ uint64_t result; -+ -+ ASSERT(divisor); -+ -+ result = div64_u64_rem(dividend, divisor, remainder); -+ -+ return result; -+} -+ -+#define BITS_PER_FRACTIONAL_PART \ -+ 32 -+ -+#define FRACTIONAL_PART_MASK \ -+ ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) -+ -+#define GET_INTEGER_PART(x) \ -+ ((x) >> BITS_PER_FRACTIONAL_PART) -+ -+#define GET_FRACTIONAL_PART(x) \ -+ (FRACTIONAL_PART_MASK & (x)) -+ -+struct fixed31_32 dal_fixed31_32_from_fraction( -+ int64_t numerator, -+ int64_t denominator) -+{ -+ struct fixed31_32 res; -+ -+ bool arg1_negative = numerator < 0; -+ bool arg2_negative = denominator < 0; -+ -+ uint64_t arg1_value = arg1_negative ? -numerator : numerator; -+ uint64_t arg2_value = arg2_negative ? -denominator : denominator; -+ -+ uint64_t remainder; -+ -+ /* determine integer part */ -+ -+ uint64_t res_value = complete_integer_division_u64( -+ arg1_value, arg2_value, &remainder); -+ -+ ASSERT(res_value <= LONG_MAX); -+ -+ /* determine fractional part */ -+ { -+ uint32_t i = BITS_PER_FRACTIONAL_PART; -+ -+ do { -+ remainder <<= 1; -+ -+ res_value <<= 1; -+ -+ if (remainder >= arg2_value) { -+ res_value |= 1; -+ remainder -= arg2_value; -+ } -+ } while (--i != 0); -+ } -+ -+ /* round up LSB */ -+ { -+ uint64_t summand = (remainder << 1) >= arg2_value; -+ -+ ASSERT(res_value <= LLONG_MAX - summand); -+ -+ res_value += summand; -+ } -+ -+ res.value = (int64_t)res_value; -+ -+ if (arg1_negative ^ arg2_negative) -+ res.value = -res.value; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_from_int( -+ int64_t arg) -+{ -+ struct fixed31_32 res; -+ -+ ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX)); -+ -+ res.value = arg << BITS_PER_FRACTIONAL_PART; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_neg( -+ struct fixed31_32 arg) -+{ -+ struct fixed31_32 res; -+ -+ res.value = -arg.value; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_abs( -+ struct fixed31_32 arg) -+{ -+ if (arg.value < 0) -+ return dal_fixed31_32_neg(arg); -+ else -+ return arg; -+} -+ -+bool dal_fixed31_32_lt( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ return arg1.value < arg2.value; -+} -+ -+bool dal_fixed31_32_le( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ return arg1.value <= arg2.value; -+} -+ -+bool dal_fixed31_32_eq( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ return arg1.value == arg2.value; -+} -+ -+struct fixed31_32 dal_fixed31_32_min( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ if (arg1.value <= arg2.value) -+ return arg1; -+ else -+ return arg2; -+} -+ -+struct fixed31_32 dal_fixed31_32_max( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ if (arg1.value <= arg2.value) -+ return arg2; -+ else -+ return arg1; -+} -+ -+struct fixed31_32 dal_fixed31_32_clamp( -+ struct fixed31_32 arg, -+ struct fixed31_32 min_value, -+ struct fixed31_32 max_value) -+{ -+ if (dal_fixed31_32_le(arg, min_value)) -+ return min_value; -+ else if (dal_fixed31_32_le(max_value, arg)) -+ return max_value; -+ else -+ return arg; -+} -+ -+struct fixed31_32 dal_fixed31_32_shl( -+ struct fixed31_32 arg, -+ uint8_t shift) -+{ -+ struct fixed31_32 res; -+ -+ ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || -+ ((arg.value < 0) && (arg.value >= LLONG_MIN >> shift))); -+ -+ res.value = arg.value << shift; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_shr( -+ struct fixed31_32 arg, -+ uint8_t shift) -+{ -+ struct fixed31_32 res; -+ -+ ASSERT(shift < 64); -+ -+ res.value = arg.value >> shift; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_add( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ struct fixed31_32 res; -+ -+ ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) || -+ ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value))); -+ -+ res.value = arg1.value + arg2.value; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_sub_int( -+ struct fixed31_32 arg1, -+ int32_t arg2) -+{ -+ return dal_fixed31_32_sub( -+ arg1, -+ dal_fixed31_32_from_int(arg2)); -+} -+ -+struct fixed31_32 dal_fixed31_32_sub( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ struct fixed31_32 res; -+ -+ ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) || -+ ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value))); -+ -+ res.value = arg1.value - arg2.value; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_mul_int( -+ struct fixed31_32 arg1, -+ int32_t arg2) -+{ -+ return dal_fixed31_32_mul( -+ arg1, -+ dal_fixed31_32_from_int(arg2)); -+} -+ -+struct fixed31_32 dal_fixed31_32_mul( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ struct fixed31_32 res; -+ -+ bool arg1_negative = arg1.value < 0; -+ bool arg2_negative = arg2.value < 0; -+ -+ uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value; -+ uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value; -+ -+ uint64_t arg1_int = GET_INTEGER_PART(arg1_value); -+ uint64_t arg2_int = GET_INTEGER_PART(arg2_value); -+ -+ uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); -+ uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); -+ -+ uint64_t tmp; -+ -+ res.value = arg1_int * arg2_int; -+ -+ ASSERT(res.value <= LONG_MAX); -+ -+ res.value <<= BITS_PER_FRACTIONAL_PART; -+ -+ tmp = arg1_int * arg2_fra; -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ tmp = arg2_int * arg1_fra; -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ tmp = arg1_fra * arg2_fra; -+ -+ tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + -+ (tmp >= (uint64_t)dal_fixed31_32_half.value); -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ if (arg1_negative ^ arg2_negative) -+ res.value = -res.value; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_sqr( -+ struct fixed31_32 arg) -+{ -+ struct fixed31_32 res; -+ -+ uint64_t arg_value = abs_i64(arg.value); -+ -+ uint64_t arg_int = GET_INTEGER_PART(arg_value); -+ -+ uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value); -+ -+ uint64_t tmp; -+ -+ res.value = arg_int * arg_int; -+ -+ ASSERT(res.value <= LONG_MAX); -+ -+ res.value <<= BITS_PER_FRACTIONAL_PART; -+ -+ tmp = arg_int * arg_fra; -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ tmp = arg_fra * arg_fra; -+ -+ tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + -+ (tmp >= (uint64_t)dal_fixed31_32_half.value); -+ -+ ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); -+ -+ res.value += tmp; -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_div_int( -+ struct fixed31_32 arg1, -+ int64_t arg2) -+{ -+ return dal_fixed31_32_from_fraction( -+ arg1.value, -+ dal_fixed31_32_from_int(arg2).value); -+} -+ -+struct fixed31_32 dal_fixed31_32_div( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ return dal_fixed31_32_from_fraction( -+ arg1.value, -+ arg2.value); -+} -+ -+struct fixed31_32 dal_fixed31_32_recip( -+ struct fixed31_32 arg) -+{ -+ /* -+ * @note -+ * Good idea to use Newton's method -+ */ -+ -+ ASSERT(arg.value); -+ -+ return dal_fixed31_32_from_fraction( -+ dal_fixed31_32_one.value, -+ arg.value); -+} -+ -+struct fixed31_32 dal_fixed31_32_sinc( -+ struct fixed31_32 arg) -+{ -+ struct fixed31_32 square; -+ -+ struct fixed31_32 res = dal_fixed31_32_one; -+ -+ int32_t n = 27; -+ -+ struct fixed31_32 arg_norm = arg; -+ -+ if (dal_fixed31_32_le( -+ dal_fixed31_32_two_pi, -+ dal_fixed31_32_abs(arg))) { -+ arg_norm = dal_fixed31_32_sub( -+ arg_norm, -+ dal_fixed31_32_mul_int( -+ dal_fixed31_32_two_pi, -+ (int32_t)div64_s64( -+ arg_norm.value, -+ dal_fixed31_32_two_pi.value))); -+ } -+ -+ square = dal_fixed31_32_sqr(arg_norm); -+ -+ do { -+ res = dal_fixed31_32_sub( -+ dal_fixed31_32_one, -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_mul( -+ square, -+ res), -+ n * (n - 1))); -+ -+ n -= 2; -+ } while (n > 2); -+ -+ if (arg.value != arg_norm.value) -+ res = dal_fixed31_32_div( -+ dal_fixed31_32_mul(res, arg_norm), -+ arg); -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_sin( -+ struct fixed31_32 arg) -+{ -+ return dal_fixed31_32_mul( -+ arg, -+ dal_fixed31_32_sinc(arg)); -+} -+ -+struct fixed31_32 dal_fixed31_32_cos( -+ struct fixed31_32 arg) -+{ -+ /* TODO implement argument normalization */ -+ -+ const struct fixed31_32 square = dal_fixed31_32_sqr(arg); -+ -+ struct fixed31_32 res = dal_fixed31_32_one; -+ -+ int32_t n = 26; -+ -+ do { -+ res = dal_fixed31_32_sub( -+ dal_fixed31_32_one, -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_mul( -+ square, -+ res), -+ n * (n - 1))); -+ -+ n -= 2; -+ } while (n != 0); -+ -+ return res; -+} -+ -+/* -+ * @brief -+ * result = exp(arg), -+ * where abs(arg) < 1 -+ * -+ * Calculated as Taylor series. -+ */ -+static struct fixed31_32 fixed31_32_exp_from_taylor_series( -+ struct fixed31_32 arg) -+{ -+ uint32_t n = 9; -+ -+ struct fixed31_32 res = dal_fixed31_32_from_fraction( -+ n + 2, -+ n + 1); -+ /* TODO find correct res */ -+ -+ ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one)); -+ -+ do -+ res = dal_fixed31_32_add( -+ dal_fixed31_32_one, -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_mul( -+ arg, -+ res), -+ n)); -+ while (--n != 1); -+ -+ return dal_fixed31_32_add( -+ dal_fixed31_32_one, -+ dal_fixed31_32_mul( -+ arg, -+ res)); -+} -+ -+struct fixed31_32 dal_fixed31_32_exp( -+ struct fixed31_32 arg) -+{ -+ /* -+ * @brief -+ * Main equation is: -+ * exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r), -+ * where m = round(x / ln(2)), r = x - m * ln(2) -+ */ -+ -+ if (dal_fixed31_32_le( -+ dal_fixed31_32_ln2_div_2, -+ dal_fixed31_32_abs(arg))) { -+ int32_t m = dal_fixed31_32_round( -+ dal_fixed31_32_div( -+ arg, -+ dal_fixed31_32_ln2)); -+ -+ struct fixed31_32 r = dal_fixed31_32_sub( -+ arg, -+ dal_fixed31_32_mul_int( -+ dal_fixed31_32_ln2, -+ m)); -+ -+ ASSERT(m != 0); -+ -+ ASSERT(dal_fixed31_32_lt( -+ dal_fixed31_32_abs(r), -+ dal_fixed31_32_one)); -+ -+ if (m > 0) -+ return dal_fixed31_32_shl( -+ fixed31_32_exp_from_taylor_series(r), -+ (uint8_t)m); -+ else -+ return dal_fixed31_32_div_int( -+ fixed31_32_exp_from_taylor_series(r), -+ 1LL << -m); -+ } else if (arg.value != 0) -+ return fixed31_32_exp_from_taylor_series(arg); -+ else -+ return dal_fixed31_32_one; -+} -+ -+struct fixed31_32 dal_fixed31_32_log( -+ struct fixed31_32 arg) -+{ -+ struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one); -+ /* TODO improve 1st estimation */ -+ -+ struct fixed31_32 error; -+ -+ ASSERT(arg.value > 0); -+ /* TODO if arg is negative, return NaN */ -+ /* TODO if arg is zero, return -INF */ -+ -+ do { -+ struct fixed31_32 res1 = dal_fixed31_32_add( -+ dal_fixed31_32_sub( -+ res, -+ dal_fixed31_32_one), -+ dal_fixed31_32_div( -+ arg, -+ dal_fixed31_32_exp(res))); -+ -+ error = dal_fixed31_32_sub( -+ res, -+ res1); -+ -+ res = res1; -+ /* TODO determine max_allowed_error based on quality of exp() */ -+ } while (abs_i64(error.value) > 100ULL); -+ -+ return res; -+} -+ -+struct fixed31_32 dal_fixed31_32_pow( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2) -+{ -+ return dal_fixed31_32_exp( -+ dal_fixed31_32_mul( -+ dal_fixed31_32_log(arg1), -+ arg2)); -+} -+ -+int32_t dal_fixed31_32_floor( -+ struct fixed31_32 arg) -+{ -+ uint64_t arg_value = abs_i64(arg.value); -+ -+ if (arg.value >= 0) -+ return (int32_t)GET_INTEGER_PART(arg_value); -+ else -+ return -(int32_t)GET_INTEGER_PART(arg_value); -+} -+ -+int32_t dal_fixed31_32_round( -+ struct fixed31_32 arg) -+{ -+ uint64_t arg_value = abs_i64(arg.value); -+ -+ const int64_t summand = dal_fixed31_32_half.value; -+ -+ ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); -+ -+ arg_value += summand; -+ -+ if (arg.value >= 0) -+ return (int32_t)GET_INTEGER_PART(arg_value); -+ else -+ return -(int32_t)GET_INTEGER_PART(arg_value); -+} -+ -+int32_t dal_fixed31_32_ceil( -+ struct fixed31_32 arg) -+{ -+ uint64_t arg_value = abs_i64(arg.value); -+ -+ const int64_t summand = dal_fixed31_32_one.value - -+ dal_fixed31_32_epsilon.value; -+ -+ ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); -+ -+ arg_value += summand; -+ -+ if (arg.value >= 0) -+ return (int32_t)GET_INTEGER_PART(arg_value); -+ else -+ return -(int32_t)GET_INTEGER_PART(arg_value); -+} -+ -+/* this function is a generic helper to translate fixed point value to -+ * specified integer format that will consist of integer_bits integer part and -+ * fractional_bits fractional part. For example it is used in -+ * dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional -+ * part in 32 bits. It is used in hw programming (scaler) -+ */ -+ -+static inline uint32_t ux_dy( -+ int64_t value, -+ uint32_t integer_bits, -+ uint32_t fractional_bits) -+{ -+ /* 1. create mask of integer part */ -+ uint32_t result = -+ (1 << integer_bits) - 1; -+ /* 2. mask out fractional part */ -+ uint32_t fractional_part = FRACTIONAL_PART_MASK & value; -+ /* 3. shrink fixed point integer part to be of integer_bits width*/ -+ result &= GET_INTEGER_PART(value); -+ /* 4. make space for fractional part to be filled in after integer */ -+ result <<= fractional_bits; -+ /* 5. shrink fixed point fractional part to of fractional_bits width*/ -+ fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits; -+ /* 6. merge the result */ -+ return result | fractional_part; -+} -+ -+uint32_t dal_fixed31_32_u2d19( -+ struct fixed31_32 arg) -+{ -+ return ux_dy(arg.value, 2, 19); -+} -+ -+uint32_t dal_fixed31_32_u0d19( -+ struct fixed31_32 arg) -+{ -+ return ux_dy(arg.value, 0, 19); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c -new file mode 100644 -index 0000000..1140132 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c -@@ -0,0 +1,223 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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/dal/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c -new file mode 100644 -index 0000000..8276f9d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c -@@ -0,0 +1,135 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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)) { -+ dal_output_to_console( -+ "%s: Warning: comparing invalid object 'id1'!\n", __func__); -+ return false; -+ } -+ -+ if (false == dal_graphics_object_id_is_valid(id2)) { -+ dal_output_to_console( -+ "%s: Warning: comparing invalid object 'id2'!\n", __func__); -+ return false; -+ } -+ -+ if (id1.id == id2.id && id1.enum_id == id2.enum_id -+ && id1.type == id2.type) -+ return true; -+ -+ return false; -+} -+ -+/* Based on internal data members memory layout */ -+uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) -+{ -+ uint32_t object_id = 0; -+ -+ object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); -+ return object_id; -+} -+ -+/* -+ * ******* get specific ID - internal safe cast into specific type ******* -+ */ -+ -+enum controller_id dal_graphics_object_id_get_controller_id( -+ struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_CONTROLLER) -+ return id.id; -+ return CONTROLLER_ID_UNDEFINED; -+} -+ -+enum clock_source_id dal_graphics_object_id_get_clock_source_id( -+ struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_CLOCK_SOURCE) -+ return id.id; -+ return CLOCK_SOURCE_ID_UNDEFINED; -+} -+ -+enum encoder_id dal_graphics_object_id_get_encoder_id( -+ struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_ENCODER) -+ return id.id; -+ return ENCODER_ID_UNKNOWN; -+} -+ -+enum connector_id dal_graphics_object_id_get_connector_id( -+ struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_CONNECTOR) -+ return id.id; -+ return CONNECTOR_ID_UNKNOWN; -+} -+ -+enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_AUDIO) -+ return id.id; -+ return AUDIO_ID_UNKNOWN; -+} -+ -+enum engine_id dal_graphics_object_id_get_engine_id( -+ struct graphics_object_id id) -+{ -+ if (id.type == OBJECT_TYPE_ENGINE) -+ return id.id; -+ return ENGINE_ID_UNKNOWN; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.c b/drivers/gpu/drm/amd/dal/dc/basics/logger.c -new file mode 100644 -index 0000000..50db743 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.c -@@ -0,0 +1,947 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#include <stdarg.h> -+#include "dal_services.h" -+#include "include/dal_types.h" -+#include "include/logger_interface.h" -+#include "logger.h" -+ -+/* TODO: for now - empty, use DRM defines from dal services. -+ Need to define appropriate levels of prints, and implement -+ this component -+void dal_log(const char *format, ...) -+{ -+} -+*/ -+ -+/* ----------- Logging Major/Minor names ------------ */ -+ -+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) -+ -+static const struct log_minor_info component_minor_info_tbl[] = { -+ {LOG_MINOR_COMPONENT_LINK_SERVICE, "LS"}, -+ {LOG_MINOR_COMPONENT_DAL_INTERFACE, "DalIf"}, -+ {LOG_MINOR_COMPONENT_HWSS, "HWSS"}, -+ {LOG_MINOR_COMPONENT_ADAPTER_SERVICE, "AS"}, -+ {LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "DS"}, -+ {LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, "TM"}, -+ {LOG_MINOR_COMPONENT_ENCODER, "Encoder"}, -+ {LOG_MINOR_COMPONENT_I2C_AUX, "I2cAux"}, -+ {LOG_MINOR_COMPONENT_AUDIO, "Audio"}, -+ {LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, "Dcs"}, -+ {LOG_MINOR_COMPONENT_DMCU, "Dmcu"}, -+ {LOG_MINOR_COMPONENT_GPU, "GPU"}, -+ {LOG_MINOR_COMPONENT_CONTROLLER, "Cntrlr"}, -+ {LOG_MINOR_COMPONENT_ISR, "ISR"}, -+ {LOG_MINOR_COMPONENT_BIOS, "BIOS"}, -+ {LOG_MINOR_COMPONENT_DC, "DC"}, -+ {LOG_MINOR_COMPONENT_IRQ_SERVICE, "IRQ SERVICE"}, -+ -+}; -+ -+static const struct log_minor_info hw_trace_minor_info_tbl[] = { -+ {LOG_MINOR_HW_TRACE_MST, "Mst" }, -+ {LOG_MINOR_HW_TRACE_TRAVIS, "Travis" }, -+ {LOG_MINOR_HW_TRACE_HOTPLUG, "Hotplug" }, -+ {LOG_MINOR_HW_TRACE_LINK_TRAINING, "LinkTraining" }, -+ {LOG_MINOR_HW_TRACE_SET_MODE, "SetMode" }, -+ {LOG_MINOR_HW_TRACE_RESUME_S3, "ResumeS3" }, -+ {LOG_MINOR_HW_TRACE_RESUME_S4, "ResumeS4" }, -+ {LOG_MINOR_HW_TRACE_BOOTUP, "BootUp" }, -+ {LOG_MINOR_HW_TRACE_AUDIO, "Audio"}, -+ {LOG_MINOR_HW_TRACE_HPD_IRQ, "HpdIrq" }, -+ {LOG_MINOR_HW_TRACE_INTERRUPT, "Interrupt" }, -+ {LOG_MINOR_HW_TRACE_MPO, "Planes" }, -+}; -+ -+static const struct log_minor_info mst_minor_info_tbl[] = { -+ {LOG_MINOR_MST_IRQ_HPD_RX, "IrqHpdRx"}, -+ {LOG_MINOR_MST_IRQ_TIMER, "IrqTimer"}, -+ {LOG_MINOR_MST_NATIVE_AUX, "NativeAux"}, -+ {LOG_MINOR_MST_SIDEBAND_MSG, "SB"}, -+ {LOG_MINOR_MST_MSG_TRANSACTION, "MT"}, -+ {LOG_MINOR_MST_SIDEBAND_MSG_PARSED, "SB Parsed"}, -+ {LOG_MINOR_MST_MSG_TRANSACTION_PARSED, "MT Parsed"}, -+ {LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, "AuxMsgDpcdAccess"}, -+ {LOG_MINOR_MST_PROGRAMMING, "Programming"}, -+ {LOG_MINOR_MST_TOPOLOGY_DISCOVERY, "TopologyDiscovery"}, -+ {LOG_MINOR_MST_CONVERTER_CAPS, "ConverterCaps"}, -+}; -+ -+static const struct log_minor_info dcs_minor_info_tbl[] = { -+ {LOG_MINOR_DCS_EDID_EMULATOR, "EdidEmul"}, -+ {LOG_MINOR_DCS_DONGLE_DETECTION, "DongleDetect"}, -+}; -+ -+static const struct log_minor_info dcp_minor_info_tbl[] = { -+ { LOG_MINOR_DCP_GAMMA_GRPH, "GammaGrph"}, -+ { LOG_MINOR_DCP_GAMMA_OVL, "GammaOvl"}, -+ { LOG_MINOR_DCP_CSC_GRPH, "CscGrph"}, -+ { LOG_MINOR_DCP_CSC_OVL, "CscOvl"}, -+ { LOG_MINOR_DCP_SCALER, "Scaler"}, -+ { LOG_MINOR_DCP_SCALER_TABLES, "ScalerTables"}, -+}; -+ -+static const struct log_minor_info bios_minor_info_tbl[] = { -+ {LOG_MINOR_BIOS_CMD_TABLE, "CmdTbl"}, -+}; -+ -+static const struct log_minor_info reg_minor_info_tbl[] = { -+ {LOG_MINOR_REGISTER_INDEX, "Index"}, -+}; -+ -+static const struct log_minor_info info_packet_minor_info_tbl[] = { -+ {LOG_MINOR_INFO_PACKETS_HDMI, "Hdmi"}, -+}; -+ -+ -+static const struct log_minor_info dsat_minor_info_tbl[] = { -+ {LOG_MINOR_DSAT_LOGGER, "Logger"}, -+ {LOG_MINOR_DSAT_EDID_OVERRIDE, "EDID_Override"}, -+}; -+ -+static const struct log_minor_info ec_minor_info_tbl[] = { -+ {LOG_MINOR_EC_PPLIB_NOTIFY, "PPLib_Notify" }, /* PPLib notifies DAL */ -+ {LOG_MINOR_EC_PPLIB_QUERY, "PPLib_Query" } /* DAL requested info from -+ PPLib */ -+}; -+ -+static const struct log_minor_info bwm_minor_info_tbl[] = { -+ {LOG_MINOR_BWM_MODE_VALIDATION, "ModeValidation"}, -+ {LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, "Req_Bandw_Calcs"} -+}; -+ -+static const struct log_minor_info mode_enum_minor_info_tbl[] = { -+ {LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES, "BestviewCandidates"}, -+ {LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, "ViewSolution"}, -+ {LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, "TsListBuild"}, -+ {LOG_MINOR_MODE_ENUM_TS_LIST, "TsList"}, -+ {LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, "MasterViewList"}, -+ {LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, "MasterViewListUpdate"}, -+}; -+ -+static const struct log_minor_info i2caux_minor_info_tbl[] = { -+ {LOG_MINOR_I2C_AUX_LOG, "Log"}, -+ {LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, "Timestamp"}, -+ {LOG_MINOR_I2C_AUX_CFG, "Config"} -+}; -+ -+static const struct log_minor_info line_buffer_minor_info_tbl[] = { -+ {LOG_MINOR_LINE_BUFFER_POWERGATING, "PowerGating"} -+}; -+ -+static const struct log_minor_info hwss_minor_info_tbl[] = { -+ {LOG_MINOR_HWSS_TAPS_VALIDATION, "HWSS Taps"} -+}; -+ -+static const struct log_minor_info optimization_minor_info_tbl[] = { -+ {LOG_MINOR_OPTMZ_GENERAL, "General Optimizations"}, -+ {LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE, -+ "Skip Vcc Off During Set Mode"} -+}; -+ -+static const struct log_minor_info perf_measure_minor_info_tbl[] = { -+ {LOG_MINOR_PERF_MEASURE_GENERAL, "General Performance Measurement"}, -+ {LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, "Heap Memory Management"} -+}; -+ -+static const struct log_minor_info sync_minor_info_tbl[] = { -+ {LOG_MINOR_SYNC_HW_CLOCK_ADJUST, "Pixel Rate Tune-up"}, -+ {LOG_MINOR_SYNC_TIMING, "Timing"} -+}; -+ -+static const struct log_minor_info backlight_minor_info_tbl[] = { -+ {LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, "Caps"}, -+ {LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, "DMCU Delta LUT"}, -+ {LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, "Build DMCU Delta LUT"}, -+ {LOG_MINOR_BACKLIGHT_INTERFACE, "Interface"}, -+ {LOG_MINOR_BACKLIGHT_LID, "Lid Status"} -+}; -+ -+ -+static const struct log_minor_info override_feature_minor_info_tbl[] = { -+ {LOG_MINOR_FEATURE_OVERRIDE, "overriden feature"}, -+}; -+ -+static const struct log_minor_info detection_minor_info_tbl[] = { -+ {LOG_MINOR_DETECTION_EDID_PARSER, "EDID Parser"}, -+ {LOG_MINOR_DETECTION_DP_CAPS, "DP caps"}, -+}; -+ -+static const struct log_minor_info tm_minor_info_tbl[] = { -+ {LOG_MINOR_TM_INFO, "INFO"}, -+ {LOG_MINOR_TM_IFACE_TRACE, "IFACE_TRACE"}, -+ {LOG_MINOR_TM_RESOURCES, "RESOURCES"}, -+ {LOG_MINOR_TM_ENCODER_CTL, "ENCODER_CTL"}, -+ {LOG_MINOR_TM_ENG_ASN, "ENG_ASN"}, -+ {LOG_MINOR_TM_CONTROLLER_ASN, "CONTROLLER_ASN"}, -+ {LOG_MINOR_TM_PWR_GATING, "PWR_GATING"}, -+ {LOG_MINOR_TM_BUILD_DSP_PATH, "BUILD_PATH"}, -+ {LOG_MINOR_TM_DISPLAY_DETECT, "DISPLAY_DETECT"}, -+ {LOG_MINOR_TM_LINK_SRV, "LINK_SRV"}, -+ {LOG_MINOR_TM_NOT_IMPLEMENTED, "NOT_IMPL"}, -+ {LOG_MINOR_TM_COFUNC_PATH, "COFUNC_PATH"} -+}; -+ -+static const struct log_minor_info ds_minor_info_tbl[] = { -+ {LOG_MINOR_DS_MODE_SETTING, "Mode_Setting"}, -+}; -+ -+ -+struct log_major_mask_info { -+ struct log_major_info major_info; -+ uint32_t default_mask; -+ const struct log_minor_info *minor_tbl; -+ uint32_t tbl_element_cnt; -+}; -+ -+/* A mask for each Major. -+ * Use a mask or zero. */ -+#define LG_ERR_MSK 0xffffffff -+#define LG_WRN_MSK 0xffffffff -+#define LG_TM_MSK (1 << LOG_MINOR_TM_INFO) -+#define LG_FO_MSK (1 << LOG_MINOR_FEATURE_OVERRIDE) -+#define LG_EC_MSK ((1 << LOG_MINOR_EC_PPLIB_NOTIFY) | \ -+ (1 << LOG_MINOR_EC_PPLIB_QUERY)) -+#define LG_DSAT_MSK (1 << LOG_MINOR_DSAT_EDID_OVERRIDE) -+#define LG_DT_MSK (1 << LOG_MINOR_DETECTION_EDID_PARSER) -+ -+/* IFT - InterFaceTrace */ -+#define LG_IFT_MSK (1 << LOG_MINOR_COMPONENT_DC) -+ -+ -+#define LG_HW_TR_AUD_MSK (1 << LOG_MINOR_HW_TRACE_AUDIO) -+#define LG_HW_TR_INTERRUPT_MSK (1 << LOG_MINOR_HW_TRACE_INTERRUPT) | \ -+ (1 << LOG_MINOR_HW_TRACE_HPD_IRQ) -+#define LG_HW_TR_PLANES_MSK (1 << LOG_MINOR_HW_TRACE_MPO) -+#define LG_ALL_MSK 0xffffffff -+ -+#define LG_SYNC_MSK (1 << LOG_MINOR_SYNC_TIMING) -+ -+#define LG_BWM_MSK (1 << LOG_MINOR_BWM_MODE_VALIDATION) -+ -+ -+static const struct log_major_mask_info log_major_mask_info_tbl[] = { -+ /* LogMajor major name default MinorTble tblElementCnt */ -+ {{LOG_MAJOR_ERROR, "Error" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, -+ {{LOG_MAJOR_WARNING, "Warning" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, -+ {{LOG_MAJOR_INTERFACE_TRACE, "IfTrace" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, -+ {{LOG_MAJOR_HW_TRACE, "HwTrace" }, (LG_ALL_MSK & -+ ~((1 << LOG_MINOR_HW_TRACE_LINK_TRAINING) | -+ (1 << LOG_MINOR_HW_TRACE_AUDIO))), -+ hw_trace_minor_info_tbl, NUM_ELEMENTS(hw_trace_minor_info_tbl)}, -+ {{LOG_MAJOR_MST, "MST" }, LG_ALL_MSK, mst_minor_info_tbl, NUM_ELEMENTS(mst_minor_info_tbl)}, -+ {{LOG_MAJOR_DCS, "DCS" }, LG_ALL_MSK, dcs_minor_info_tbl, NUM_ELEMENTS(dcs_minor_info_tbl)}, -+ {{LOG_MAJOR_DCP, "DCP" }, LG_ALL_MSK, dcp_minor_info_tbl, NUM_ELEMENTS(dcp_minor_info_tbl)}, -+ {{LOG_MAJOR_BIOS, "Bios" }, LG_ALL_MSK, bios_minor_info_tbl, NUM_ELEMENTS(bios_minor_info_tbl)}, -+ {{LOG_MAJOR_REGISTER, "Register" }, LG_ALL_MSK, reg_minor_info_tbl, NUM_ELEMENTS(reg_minor_info_tbl)}, -+ {{LOG_MAJOR_INFO_PACKETS, "InfoPacket" }, LG_ALL_MSK, info_packet_minor_info_tbl, NUM_ELEMENTS(info_packet_minor_info_tbl)}, -+ {{LOG_MAJOR_DSAT, "DSAT" }, LG_ALL_MSK, dsat_minor_info_tbl, NUM_ELEMENTS(dsat_minor_info_tbl)}, -+ {{LOG_MAJOR_EC, "EC" }, LG_ALL_MSK, ec_minor_info_tbl, NUM_ELEMENTS(ec_minor_info_tbl)}, -+ {{LOG_MAJOR_BWM, "BWM" }, LG_BWM_MSK, bwm_minor_info_tbl, NUM_ELEMENTS(bwm_minor_info_tbl)}, -+ {{LOG_MAJOR_MODE_ENUM, "ModeEnum" }, LG_ALL_MSK, mode_enum_minor_info_tbl, NUM_ELEMENTS(mode_enum_minor_info_tbl)}, -+ {{LOG_MAJOR_I2C_AUX, "I2cAux" }, LG_ALL_MSK, i2caux_minor_info_tbl, NUM_ELEMENTS(i2caux_minor_info_tbl)}, -+ {{LOG_MAJOR_LINE_BUFFER, "LineBuffer" }, LG_ALL_MSK, line_buffer_minor_info_tbl, NUM_ELEMENTS(line_buffer_minor_info_tbl)}, -+ {{LOG_MAJOR_HWSS, "HWSS" }, LG_ALL_MSK, hwss_minor_info_tbl, NUM_ELEMENTS(hwss_minor_info_tbl)}, -+ {{LOG_MAJOR_OPTIMIZATION, "Optimization"}, LG_ALL_MSK, optimization_minor_info_tbl, NUM_ELEMENTS(optimization_minor_info_tbl)}, -+ {{LOG_MAJOR_PERF_MEASURE, "PerfMeasure" }, LG_ALL_MSK, perf_measure_minor_info_tbl, NUM_ELEMENTS(perf_measure_minor_info_tbl)}, -+ {{LOG_MAJOR_SYNC, "Sync" }, LG_SYNC_MSK,sync_minor_info_tbl, NUM_ELEMENTS(sync_minor_info_tbl)}, -+ {{LOG_MAJOR_BACKLIGHT, "Backlight" }, LG_ALL_MSK, backlight_minor_info_tbl, NUM_ELEMENTS(backlight_minor_info_tbl)}, -+ {{LOG_MAJOR_INTERRUPTS, "Interrupts" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, -+ {{LOG_MAJOR_TM, "TM" }, 0, tm_minor_info_tbl, NUM_ELEMENTS(tm_minor_info_tbl)}, -+ {{LOG_MAJOR_DISPLAY_SERVICE, "DS" }, LG_ALL_MSK, ds_minor_info_tbl, NUM_ELEMENTS(ds_minor_info_tbl)}, -+ {{LOG_MAJOR_FEATURE_OVERRIDE, "FeatureOverride" }, LG_ALL_MSK, override_feature_minor_info_tbl, NUM_ELEMENTS(override_feature_minor_info_tbl)}, -+ {{LOG_MAJOR_DETECTION, "Detection" }, LG_ALL_MSK, detection_minor_info_tbl, NUM_ELEMENTS(detection_minor_info_tbl)}, -+}; -+ -+/* ----------- Object init and destruction ----------- */ -+static bool construct(struct dc_context *ctx, struct dal_logger *logger) -+{ -+ uint32_t i; -+ /* malloc buffer and init offsets */ -+ -+ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; -+ logger->log_buffer = (char *)dc_service_alloc(ctx, -+ logger->log_buffer_size * -+ sizeof(char)); -+ -+ if (!logger->log_buffer) -+ return false; -+ -+ /* todo: Fill buffer with \0 if not done by dal_alloc */ -+ -+ /* Initialize both offsets to start of buffer (empty) */ -+ logger->buffer_read_offset = 0; -+ logger->buffer_write_offset = 0; -+ -+ logger->write_wrap_count = 0; -+ logger->read_wrap_count = 0; -+ logger->open_count = 0; -+ -+ logger->flags.bits.ENABLE_CONSOLE = 1; -+ logger->flags.bits.ENABLE_BUFFER = 0; -+ -+ logger->ctx = ctx; -+ -+ /* malloc and init minor mask array */ -+ logger->log_enable_mask_minors = -+ (uint32_t *)dc_service_alloc( -+ ctx, -+ NUM_ELEMENTS(log_major_mask_info_tbl) -+ * sizeof(uint32_t)); -+ if (!logger->log_enable_mask_minors) -+ return false; -+ -+ -+ /* Set default values for mask */ -+ for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { -+ -+ uint32_t dflt_mask = log_major_mask_info_tbl[i].default_mask; -+ -+ logger->log_enable_mask_minors[i] = dflt_mask; -+ } -+ -+ return true; -+} -+ -+static void destruct(struct dal_logger *logger) -+{ -+ if (logger->log_buffer) { -+ dc_service_free(logger->ctx, logger->log_buffer); -+ logger->log_buffer = NULL; -+ } -+ -+ if (logger->log_enable_mask_minors) { -+ dc_service_free(logger->ctx, logger->log_enable_mask_minors); -+ logger->log_enable_mask_minors = NULL; -+ } -+} -+ -+struct dal_logger *dal_logger_create(struct dc_context *ctx) -+{ -+ /* malloc struct */ -+ struct dal_logger *logger = dc_service_alloc(ctx, sizeof(struct dal_logger)); -+ -+ if (!logger) -+ return NULL; -+ if (!construct(ctx, logger)) { -+ dc_service_free(ctx, logger); -+ return NULL; -+ } -+ -+ return logger; -+} -+ -+uint32_t dal_logger_destroy(struct dal_logger **logger) -+{ -+ if (logger == NULL || *logger == NULL) -+ return 1; -+ destruct(*logger); -+ dc_service_free((*logger)->ctx, *logger); -+ *logger = NULL; -+ -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static void lock(struct dal_logger *logger) -+{ -+ /* Todo: lock mutex? */ -+} -+ -+static void unlock(struct dal_logger *logger) -+{ -+ /* Todo: unlock mutex */ -+} -+ -+bool dal_logger_should_log( -+ struct dal_logger *logger, -+ enum log_major major, -+ enum log_minor minor) -+{ -+ if (major < LOG_MAJOR_COUNT) { -+ -+ uint32_t minor_mask = logger->log_enable_mask_minors[major]; -+ -+ if ((minor_mask & (1 << minor)) != 0) -+ return true; -+ } -+ -+ return false; -+} -+ -+static void log_to_debug_console(struct log_entry *entry) -+{ -+ struct dal_logger *logger = entry->logger; -+ -+ if (logger->flags.bits.ENABLE_CONSOLE == 0) -+ return; -+ -+ switch (entry->major) { -+ case LOG_MAJOR_ERROR: -+ dal_error("%s", entry->buf); -+ break; -+ default: -+ dal_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]; -+ -+ dal_output_to_console( -+ "---------------- FLUSHING LOG BUFFER ----------------\n"); -+ while (i < logger->buffer_write_offset) { -+ -+ if (logger->log_buffer[i] == '\0') { -+ dal_output_to_console("%s", string_start); -+ string_start = (char *)logger->log_buffer + i + 1; -+ } -+ i++; -+ } -+ dal_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' -+ */ -+ dc_service_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; -+ -+ dc_service_memmove(logger->log_buffer + -+ logger->buffer_write_offset, -+ entry->buf, space_before_wrap); -+ dc_service_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 */ -+ dc_service_memmove(logger->log_buffer, entry->buf, size); -+ logger->buffer_write_offset = size; -+ logger->buffer_read_offset = 0; -+ } -+ -+ } -+ -+ unlock(logger); -+} -+ -+ -+static void log_timestamp(struct log_entry *entry) -+{ -+ dal_logger_append(entry, "00:00:00 "); -+} -+ -+static void log_major_minor(struct log_entry *entry) -+{ -+ uint32_t i; -+ enum log_major major = entry->major; -+ enum log_minor minor = entry->minor; -+ -+ for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { -+ -+ const struct log_major_mask_info *maj_mask_info = -+ &log_major_mask_info_tbl[i]; -+ -+ if (maj_mask_info->major_info.major == major) { -+ -+ dal_logger_append(entry, "[%s_", -+ maj_mask_info->major_info.major_name); -+ -+ if (maj_mask_info->minor_tbl != NULL) { -+ uint32_t j; -+ -+ for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) { -+ -+ const struct log_minor_info *min_info = &maj_mask_info->minor_tbl[j]; -+ -+ if (min_info->minor == minor) -+ dal_logger_append(entry, "%s]\t", min_info->minor_name); -+ } -+ } -+ -+ break; -+ } -+ } -+} -+ -+static void log_heading(struct log_entry *entry, -+ enum log_major major, -+ enum log_minor minor) -+{ -+ log_timestamp(entry); -+ log_major_minor(entry); -+} -+ -+ -+static void append_entry( -+ struct log_entry *entry, -+ char *buffer, -+ uint32_t buf_size) -+{ -+ if (!entry->buf || -+ entry->buf_offset + buf_size > entry->max_buf_bytes -+ ) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ /* Todo: check if off by 1 byte due to \0 anywhere */ -+ dc_service_memmove(entry->buf + entry->buf_offset, buffer, buf_size); -+ entry->buf_offset += buf_size; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Warning: Be careful that 'msg' is null terminated and the total size is -+ * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' -+ */ -+void dal_logger_write( -+ struct dal_logger *logger, -+ enum log_major major, -+ enum log_minor minor, -+ const char *msg, -+ ...) -+{ -+ -+ if (logger && dal_logger_should_log(logger, major, minor)) { -+ -+ uint32_t size; -+ va_list args; -+ char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE]; -+ struct log_entry entry; -+ -+ va_start(args, msg); -+ dal_logger_open(logger, &entry, major, minor); -+ -+ -+ size = dal_log_to_buffer( -+ buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args); -+ -+ if (size > 0 && size < -+ DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) { -+ -+ if (buffer[size] == '\0') -+ size++; /* Add one for null terminator */ -+ -+ /* Concatenate onto end of entry buffer */ -+ append_entry(&entry, buffer, size); -+ } else { -+ append_entry(&entry, "LOG_ERROR\n", 12); -+ } -+ -+ dal_logger_close(&entry); -+ va_end(args); -+ -+ } -+} -+ -+ -+/* Same as dal_logger_write, except without open() and close(), which must -+ * be done separately. -+ */ -+void dal_logger_append( -+ struct log_entry *entry, -+ const char *msg, -+ ...) -+{ -+ struct dal_logger *logger; -+ -+ if (!entry) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ logger = entry->logger; -+ -+ if (logger && logger->open_count > 0 && -+ dal_logger_should_log(logger, entry->major, entry->minor)) { -+ -+ uint32_t size; -+ va_list args; -+ char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE]; -+ -+ va_start(args, msg); -+ -+ size = dal_log_to_buffer( -+ buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args); -+ append_entry(entry, buffer, size); -+ -+ va_end(args); -+ } -+} -+ -+ -+uint32_t dal_logger_read( -+ struct dal_logger *logger, /* <[in] */ -+ uint32_t output_buffer_size, /* <[in] */ -+ char *output_buffer, /* >[out] */ -+ uint32_t *bytes_read, /* >[out] */ -+ bool single_line) -+{ -+ uint32_t bytes_remaining = 0; -+ uint32_t bytes_read_count = 0; -+ bool keep_reading = true; -+ -+ if (!logger || output_buffer == NULL || output_buffer_size == 0) { -+ BREAK_TO_DEBUGGER(); -+ *bytes_read = 0; -+ return 0; -+ } -+ -+ lock(logger); -+ -+ /* Read until null terminator (if single_line==true, -+ * max buffer size, or until we've read everything new -+ */ -+ -+ do { -+ char cur; -+ -+ /* Stop when we've read everything */ -+ if (logger->buffer_read_offset == -+ logger->buffer_write_offset) { -+ -+ break; -+ } -+ -+ cur = logger->log_buffer[logger->buffer_read_offset]; -+ logger->buffer_read_offset++; -+ -+ /* Wrap read pointer if at end */ -+ if (logger->buffer_read_offset == logger->log_buffer_size) { -+ -+ logger->buffer_read_offset = 0; -+ logger->read_wrap_count++; -+ } -+ -+ /* Don't send null terminators to buffer */ -+ if (cur != '\0') { -+ output_buffer[bytes_read_count] = cur; -+ bytes_read_count++; -+ } else if (single_line) { -+ keep_reading = false; -+ } -+ -+ } while (bytes_read_count <= output_buffer_size && keep_reading); -+ -+ /* We assume that reading can never be ahead of writing */ -+ if (logger->write_wrap_count > logger->read_wrap_count) { -+ bytes_remaining = logger->log_buffer_size - -+ logger->buffer_read_offset + -+ logger->buffer_write_offset; -+ } else { -+ bytes_remaining = logger->buffer_write_offset - -+ logger->buffer_read_offset; -+ } -+ -+ /* reset write/read wrap count to 0 if we've read everything */ -+ if (bytes_remaining == 0) { -+ -+ logger->write_wrap_count = 0; -+ logger->read_wrap_count = 0; -+ } -+ -+ *bytes_read = bytes_read_count; -+ unlock(logger); -+ -+ return bytes_remaining; -+} -+ -+void dal_logger_open( -+ struct dal_logger *logger, -+ struct log_entry *entry, /* out */ -+ enum log_major major, -+ enum log_minor minor) -+{ -+ if (!entry) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ entry->major = LOG_MAJOR_COUNT; -+ entry->minor = 0; -+ entry->logger = logger; -+ -+ entry->buf = dc_service_alloc( -+ logger->ctx, -+ DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE * sizeof(char)); -+ -+ entry->buf_offset = 0; -+ entry->max_buf_bytes = -+ DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE * sizeof(char); -+ -+ logger->open_count++; -+ entry->major = major; -+ entry->minor = minor; -+ -+ log_heading(entry, major, minor); -+} -+ -+void dal_logger_close(struct log_entry *entry) -+{ -+ struct dal_logger *logger = entry->logger; -+ -+ -+ if (logger && logger->open_count > 0) { -+ logger->open_count--; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ goto cleanup; -+ } -+ -+ /* --Flush log_entry buffer-- */ -+ /* print to kernel console */ -+ log_to_debug_console(entry); -+ /* log internally for dsat */ -+ log_to_internal_buffer(entry); -+ -+ /* TODO: Write end heading */ -+ -+cleanup: -+ if (entry->buf) { -+ dc_service_free(entry->logger->ctx, entry->buf); -+ entry->buf = NULL; -+ entry->buf_offset = 0; -+ entry->max_buf_bytes = 0; -+ } -+} -+ -+uint32_t dal_logger_get_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor) -+{ -+ uint32_t log_mask = 0; -+ -+ if (logger && lvl_major < LOG_MAJOR_COUNT) -+ log_mask = logger->log_enable_mask_minors[lvl_major]; -+ -+ log_mask &= 1 << lvl_minor; -+ return log_mask; -+} -+ -+uint32_t dal_logger_set_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor) -+{ -+ -+ if (logger && lvl_major < LOG_MAJOR_COUNT) { -+ if (lvl_minor == LOG_MINOR_MASK_ALL) { -+ logger->log_enable_mask_minors[lvl_major] = 0xFFFFFFFF; -+ } else { -+ logger->log_enable_mask_minors[lvl_major] |= -+ (1 << lvl_minor); -+ } -+ return 0; -+ } -+ return 1; -+} -+ -+uint32_t dal_logger_get_masks( -+ struct dal_logger *logger, -+ enum log_major lvl_major) -+{ -+ uint32_t log_mask = 0; -+ -+ if (logger && lvl_major < LOG_MAJOR_COUNT) -+ log_mask = logger->log_enable_mask_minors[lvl_major]; -+ -+ return log_mask; -+} -+ -+void dal_logger_set_masks( -+ struct dal_logger *logger, -+ enum log_major lvl_major, uint32_t log_mask) -+{ -+ if (logger && lvl_major < LOG_MAJOR_COUNT) -+ logger->log_enable_mask_minors[lvl_major] = log_mask; -+} -+ -+uint32_t dal_logger_unset_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor) -+{ -+ -+ if (lvl_major < LOG_MAJOR_COUNT) { -+ if (lvl_minor == LOG_MINOR_MASK_ALL) { -+ logger->log_enable_mask_minors[lvl_major] = 0; -+ } else { -+ logger->log_enable_mask_minors[lvl_major] &= -+ ~(1 << lvl_minor); -+ } -+ return 0; -+ } -+ return 1; -+} -+ -+uint32_t dal_logger_get_flags( -+ struct dal_logger *logger) -+{ -+ -+ return logger->flags.value; -+} -+ -+void dal_logger_set_flags( -+ struct dal_logger *logger, -+ union logger_flags flags) -+{ -+ -+ logger->flags = flags; -+} -+ -+ -+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger) -+{ -+ return DAL_LOGGER_BUFFER_MAX_SIZE; -+} -+ -+uint32_t dal_logger_set_buffer_size( -+ struct dal_logger *logger, -+ uint32_t new_size) -+{ -+ /* ToDo: implement dynamic size */ -+ -+ /* return new size */ -+ return DAL_LOGGER_BUFFER_MAX_SIZE; -+} -+ -+ -+const struct log_major_info *dal_logger_enum_log_major_info( -+ struct dal_logger *logger, -+ unsigned int enum_index) -+{ -+ const struct log_major_info *major_info; -+ -+ if (enum_index >= NUM_ELEMENTS(log_major_mask_info_tbl)) -+ return NULL; -+ -+ major_info = &log_major_mask_info_tbl[enum_index].major_info; -+ return major_info; -+} -+ -+const struct log_minor_info *dal_logger_enum_log_minor_info( -+ struct dal_logger *logger, -+ enum log_major major, -+ unsigned int enum_index) -+{ -+ const struct log_minor_info *minor_info = NULL; -+ uint32_t i; -+ -+ for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { -+ -+ const struct log_major_mask_info *maj_mask_info = -+ &log_major_mask_info_tbl[i]; -+ -+ if (maj_mask_info->major_info.major == major) { -+ -+ if (maj_mask_info->minor_tbl != NULL) { -+ uint32_t j; -+ -+ for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) { -+ -+ minor_info = &maj_mask_info->minor_tbl[j]; -+ -+ if (minor_info->minor == enum_index) -+ return minor_info; -+ } -+ } -+ -+ break; -+ } -+ } -+ return NULL; -+ -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.h b/drivers/gpu/drm/amd/dal/dc/basics/logger.h -new file mode 100644 -index 0000000..fba5ec3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.h -@@ -0,0 +1,64 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_LOGGER_H__ -+#define __DAL_LOGGER_H__ -+ -+/* Structure for keeping track of offsets, buffer, etc */ -+ -+#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 -+#define DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE 256 -+ -+ -+#include "include/logger_types.h" -+ -+struct dal_logger { -+ -+ /* How far into the circular buffer has been read by dsat -+ * Read offset should never cross write offset. Write \0's to -+ * read data just to be sure? -+ */ -+ uint32_t buffer_read_offset; -+ -+ /* How far into the circular buffer we have written -+ * Write offset should never cross read offset -+ */ -+ uint32_t buffer_write_offset; -+ -+ uint32_t write_wrap_count; -+ uint32_t read_wrap_count; -+ -+ uint32_t open_count; -+ -+ char *log_buffer; /* Pointer to malloc'ed buffer */ -+ uint32_t log_buffer_size; /* Size of circular buffer */ -+ -+ uint32_t *log_enable_mask_minors; /*array of masks for major elements*/ -+ -+ union logger_flags flags; -+ struct dc_context *ctx; -+}; -+ -+#endif /* __DAL_LOGGER_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c -new file mode 100644 -index 0000000..a3086a0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c -@@ -0,0 +1,197 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 -+ = ®_dump_stack.stack_locations[i]; -+ -+ if (stack_location->current_pid == dal_get_pid() -+ && stack_location->current_tgid == dal_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 */ -+ dal_output_to_console("[REG_DUMP]: %s: stack is full!\n", -+ __func__); -+ } else { -+ current_location = -+ ®_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 */ -+ dal_output_to_console("[REG_DUMP]: %s: stack is empty!\n", -+ __func__); -+ } else { -+ --reg_dump_stack.stack_pointer; -+ current_location = -+ ®_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; -+ -+ dc_service_memset(free_stack_location, 0, sizeof(*free_stack_location)); -+ -+ free_stack_location->current_caller_func = caller_func; -+ free_stack_location->current_pid = dal_get_pid(); -+ free_stack_location->current_tgid = dal_get_tgid(); -+ -+ dal_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) { -+ dal_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", -+ __func__); -+ return; -+ } -+ -+ dal_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, -+ dal_get_pid(), -+ dal_get_tgid()); -+ -+ dc_service_memset(top_stack_location, 0, sizeof(*top_stack_location)); -+} -+ -+void dal_reg_logger_rw_count_increment(void) -+{ -+ ++reg_dump_stack.total_rw_count; -+ -+ ++reg_dump_stack.stack_locations -+ [reg_dump_stack.stack_pointer - 1].rw_count; -+} -+ -+bool dal_reg_logger_should_dump_register(void) -+{ -+ if (true == dal_reg_dump_stack_is_empty()) -+ return false; -+ -+ if (false == is_reg_dump_process()) -+ return false; -+ -+ return true; -+} -+ -+/****************************************************************************** -+ * End of File. -+ *****************************************************************************/ -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c -new file mode 100644 -index 0000000..f589091 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c -@@ -0,0 +1,116 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dc_services.h" -+#include "include/signal_types.h" -+ -+bool dc_is_hdmi_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_HDMI_TYPE_A); -+} -+ -+bool dc_is_dp_sst_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DISPLAY_PORT || -+ signal == SIGNAL_TYPE_EDP); -+} -+ -+bool dc_is_dp_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DISPLAY_PORT || -+ signal == SIGNAL_TYPE_EDP || -+ signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -+} -+ -+bool dc_is_dp_external_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DISPLAY_PORT || -+ signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -+} -+ -+bool dc_is_analog_signal(enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_RGB: -+ return true; -+ break; -+ default: -+ return false; -+ } -+} -+ -+bool dc_is_embedded_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); -+} -+ -+bool dc_is_dvi_signal(enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ return true; -+ break; -+ default: -+ return false; -+ } -+} -+ -+bool dc_is_dvi_single_link_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); -+} -+ -+bool dc_is_dual_link_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); -+} -+ -+bool dc_is_audio_capable_signal(enum signal_type signal) -+{ -+ return (signal == SIGNAL_TYPE_DISPLAY_PORT || -+ signal == SIGNAL_TYPE_DISPLAY_PORT_MST || -+ dc_is_hdmi_signal(signal) || -+ signal == SIGNAL_TYPE_WIRELESS); -+} -+ -+/* -+ * @brief -+ * Returns whether the signal is compatible -+ * with other digital encoder signal types. -+ * This is true for DVI, LVDS, and HDMI signal types. -+ */ -+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) -+{ -+ switch (signal) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_LVDS: -+ return true; -+ default: -+ return false; -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/basics/vector.c b/drivers/gpu/drm/amd/dal/dc/basics/vector.c -new file mode 100644 -index 0000000..2f932c0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/basics/vector.c -@@ -0,0 +1,309 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 = dc_service_alloc(ctx, struct_size * capacity); -+ if (vector->container == NULL) -+ return false; -+ vector->capacity = capacity; -+ vector->struct_size = struct_size; -+ vector->count = 0; -+ vector->ctx = ctx; -+ return true; -+} -+ -+bool dal_vector_presized_costruct( -+ struct vector *vector, -+ struct dc_context *ctx, -+ uint32_t count, -+ void *initial_value, -+ uint32_t struct_size) -+{ -+ uint32_t i; -+ -+ vector->container = NULL; -+ -+ if (!struct_size || !count) { -+ /* Container must be non-zero size*/ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ vector->container = dc_service_alloc(ctx, struct_size * count); -+ -+ if (vector->container == NULL) -+ return false; -+ -+ /* If caller didn't supply initial value then the default -+ * of all zeros is expected, which is exactly what dal_alloc() -+ * initialises the memory to. */ -+ if (NULL != initial_value) { -+ for (i = 0; i < count; ++i) -+ dc_service_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 = dc_service_alloc(ctx, sizeof(struct vector)); -+ -+ if (vector == NULL) -+ return NULL; -+ -+ if (dal_vector_presized_costruct( -+ vector, ctx, size, initial_value, struct_size)) -+ return vector; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, vector); -+ return NULL; -+} -+ -+struct vector *dal_vector_create( -+ struct dc_context *ctx, -+ uint32_t capacity, -+ uint32_t struct_size) -+{ -+ struct vector *vector = dc_service_alloc(ctx, sizeof(struct vector)); -+ -+ if (vector == NULL) -+ return NULL; -+ -+ if (dal_vector_construct(vector, ctx, capacity, struct_size)) -+ return vector; -+ -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, vector); -+ return NULL; -+} -+ -+void dal_vector_destruct( -+ struct vector *vector) -+{ -+ if (vector->container != NULL) -+ dc_service_free(vector->ctx, vector->container); -+ vector->count = 0; -+ vector->capacity = 0; -+} -+ -+void dal_vector_destroy( -+ struct vector **vector) -+{ -+ if (vector == NULL || *vector == NULL) -+ return; -+ dal_vector_destruct(*vector); -+ dc_service_free((*vector)->ctx, *vector); -+ *vector = NULL; -+} -+ -+uint32_t dal_vector_get_count( -+ const struct vector *vector) -+{ -+ return vector->count; -+} -+ -+void *dal_vector_at_index( -+ const struct vector *vector, -+ uint32_t index) -+{ -+ if (vector->container == NULL || index >= vector->count) -+ return NULL; -+ return vector->container + (index * vector->struct_size); -+} -+ -+bool dal_vector_remove_at_index( -+ struct vector *vector, -+ uint32_t index) -+{ -+ if (index >= vector->count) -+ return false; -+ -+ if (index != vector->count - 1) -+ dc_service_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; -+ } -+ dc_service_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) -+ dc_service_memmove( -+ insert_address + vector->struct_size, -+ insert_address, -+ vector->struct_size * (vector->count - position)); -+ -+ dc_service_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 */ -+ dc_service_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 = dc_service_realloc(vector->ctx, vector->container, -+ capacity * vector->struct_size); -+ -+ if (new_container) { -+ vector->container = new_container; -+ vector->capacity = capacity; -+ return true; -+ } -+ -+ return false; -+} -+ -+void dal_vector_clear(struct vector *vector) -+{ -+ vector->count = 0; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/Makefile b/drivers/gpu/drm/amd/dal/dc/bios/Makefile -new file mode 100644 -index 0000000..75bb892 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/Makefile -@@ -0,0 +1,27 @@ -+# -+# Makefile for the 'bios' sub-component of DAL. -+# It provides the parsing and executing controls for atom bios image. -+ -+BIOS = bios_parser.o bios_parser_helper.o command_table.o command_table_helper.o -+ -+AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) -+ -+AMD_DAL_FILES += $(AMD_DAL_BIOS) -+ -+ifndef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+AMD_DAL_FILES := $(filter-out $(AMDDALPATH)/dc/bios/bios_parser_helper.o,$(AMD_DAL_FILES)) -+endif -+$(warning AMD_DAL_FILES=$(AMD_DAL_FILES)) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+ -+ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/bios_parser_helper_dce110.o -+endif -+ -+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c -new file mode 100644 -index 0000000..7a2b247 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c -@@ -0,0 +1,4758 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "atom.h" -+ -+#include "include/adapter_service_interface.h" -+#include "include/grph_object_ctrl_defs.h" -+#include "include/bios_parser_interface.h" -+#include "include/i2caux_interface.h" -+#include "include/logger_interface.h" -+ -+#include "command_table.h" -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+#include "bios_parser_helper.h" -+#endif -+#include "command_table_helper.h" -+#include "bios_parser.h" -+ -+#define THREE_PERCENT_OF_10000 300 -+ -+#define LAST_RECORD_TYPE 0xff -+ -+/* GUID to validate external display connection info table (aka OPM module) */ -+static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { -+ 0x91, 0x6E, 0x57, 0x09, -+ 0x3F, 0x6D, 0xD2, 0x11, -+ 0x39, 0x8E, 0x00, 0xA0, -+ 0xC9, 0x69, 0x72, 0x3B}; -+ -+#define GET_IMAGE(type, offset) ((type *) get_image(bp, offset, sizeof(type))) -+#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) -+ -+static uint8_t *get_image(struct bios_parser *bp, uint32_t offset, -+ uint32_t size); -+static uint32_t get_record_size(uint8_t *record); -+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid); -+static enum object_type object_type_from_bios_object_id( -+ uint32_t bios_object_id); -+static struct graphics_object_id object_id_from_bios_object_id( -+ uint32_t bios_object_id); -+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); -+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); -+static enum connector_id connector_id_from_bios_object_id( -+ uint32_t bios_object_id); -+static uint32_t id_from_bios_object_id(enum object_type type, -+ uint32_t bios_object_id); -+static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); -+static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); -+static void get_atom_data_table_revision( -+ ATOM_COMMON_TABLE_HEADER *atom_data_tbl, -+ struct atom_data_revision *tbl_revision); -+static uint32_t get_dst_number_from_object(struct bios_parser *bp, -+ ATOM_OBJECT *object); -+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, -+ uint16_t **id_list); -+static uint32_t get_dest_obj_list(struct bios_parser *bp, -+ ATOM_OBJECT *object, uint16_t **id_list); -+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, -+ struct graphics_object_id id); -+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, -+ ATOM_I2C_RECORD *record, -+ struct graphics_object_i2c_info *info); -+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, -+ ATOM_OBJECT *object); -+static struct device_id device_type_from_device_id(uint16_t device_id); -+static uint32_t signal_to_ss_id(enum as_signal_type signal); -+static uint32_t get_support_mask_for_device_id(struct device_id device_id); -+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( -+ struct bios_parser *bp, -+ ATOM_OBJECT *object); -+static void process_ext_display_connection_info(struct bios_parser *bp); -+ -+#define BIOS_IMAGE_SIZE_OFFSET 2 -+#define BIOS_IMAGE_SIZE_UNIT 512 -+ -+static bool bios_parser_construct( -+ struct bios_parser *bp, -+ struct bp_init_data *init, -+ struct adapter_service *as) -+{ -+ uint16_t *rom_header_offset = NULL; -+ ATOM_ROM_HEADER *rom_header = NULL; -+ ATOM_OBJECT_HEADER *object_info_tbl; -+ enum dce_version dce_version; -+ -+ if (!as) -+ return false; -+ -+ if (!init) -+ return false; -+ -+ if (!init->bios) -+ return false; -+ -+ dce_version = dal_adapter_service_get_dce_version(as); -+ bp->ctx = init->ctx; -+ bp->as = as; -+ bp->bios = init->bios; -+ bp->bios_size = bp->bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; -+ bp->bios_local_image = NULL; -+ bp->lcd_scale = LCD_SCALE_UNKNOWN; -+ -+ rom_header_offset = -+ GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); -+ -+ if (!rom_header_offset) -+ return false; -+ -+ rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); -+ -+ if (!rom_header) -+ return false; -+ -+ bp->master_data_tbl = -+ GET_IMAGE(ATOM_MASTER_DATA_TABLE, -+ rom_header->usMasterDataTableOffset); -+ -+ if (!bp->master_data_tbl) -+ return false; -+ -+ bp->object_info_tbl_offset = DATA_TABLES(Object_Header); -+ -+ if (!bp->object_info_tbl_offset) -+ return false; -+ -+ object_info_tbl = -+ GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); -+ -+ if (!object_info_tbl) -+ return false; -+ -+ get_atom_data_table_revision(&object_info_tbl->sHeader, -+ &bp->object_info_tbl.revision); -+ -+ if (bp->object_info_tbl.revision.major == 1 -+ && bp->object_info_tbl.revision.minor >= 3) { -+ ATOM_OBJECT_HEADER_V3 *tbl_v3; -+ -+ tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, -+ bp->object_info_tbl_offset); -+ if (!tbl_v3) -+ return false; -+ -+ bp->object_info_tbl.v1_3 = tbl_v3; -+ } else if (bp->object_info_tbl.revision.major == 1 -+ && bp->object_info_tbl.revision.minor >= 1) -+ bp->object_info_tbl.v1_1 = object_info_tbl; -+ else -+ return false; -+ -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ bp->vbios_helper_data.active = 0; -+ bp->vbios_helper_data.requested = 0; -+ dal_bios_parser_init_bios_helper(bp, dce_version); -+#endif -+ dal_bios_parser_init_cmd_tbl(bp); -+ dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); -+ -+ return true; -+} -+ -+struct bios_parser *dal_bios_parser_create( -+ struct bp_init_data *init, struct adapter_service *as) -+{ -+ struct bios_parser *bp = NULL; -+ -+ bp = dc_service_alloc(init->ctx, sizeof(struct bios_parser)); -+ if (!bp) -+ return NULL; -+ -+ if (bios_parser_construct(bp, init, as)) -+ return bp; -+ -+ dc_service_free(init->ctx, bp); -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+} -+ -+static void destruct(struct bios_parser *bp) -+{ -+ if (bp->bios_local_image) -+ dc_service_free(bp->ctx, bp->bios_local_image); -+} -+ -+void dal_bios_parser_destroy(struct bios_parser **bp) -+{ -+ if (!bp || !*bp) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ destruct(*bp); -+ -+ dc_service_free((*bp)->ctx, *bp); -+ *bp = NULL; -+} -+ -+void dal_bios_parser_power_down(struct bios_parser *bp) -+{ -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ dal_bios_parser_set_scratch_lcd_scale(bp, bp->lcd_scale); -+#endif -+} -+ -+void dal_bios_parser_power_up(struct bios_parser *bp) -+{ -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ if (bp->lcd_scale == LCD_SCALE_UNKNOWN) -+ bp->lcd_scale = dal_bios_parser_get_scratch_lcd_scale(bp); -+#endif -+} -+ -+static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) -+{ -+ ATOM_OBJECT_TABLE *table; -+ -+ uint32_t object_table_offset = bp->object_info_tbl_offset + offset; -+ -+ table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset); -+ -+ if (!table) -+ return 0; -+ else -+ return table->ucNumberOfObjects; -+} -+ -+uint8_t dal_bios_parser_get_encoders_number(struct bios_parser *bp) -+{ -+ return get_number_of_objects(bp, -+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset)); -+} -+ -+uint8_t dal_bios_parser_get_connectors_number(struct bios_parser *bp) -+{ -+ return get_number_of_objects(bp, -+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); -+} -+ -+uint32_t dal_bios_parser_get_oem_ddc_lines_number(struct bios_parser *bp) -+{ -+ uint32_t number = 0; -+ -+ if (DATA_TABLES(OemInfo) != 0) { -+ ATOM_OEM_INFO *info; -+ -+ info = GET_IMAGE(ATOM_OEM_INFO, -+ DATA_TABLES(OemInfo)); -+ -+ if (le16_to_cpu(info->sHeader.usStructureSize) -+ > sizeof(ATOM_COMMON_TABLE_HEADER)) { -+ -+ number = (le16_to_cpu(info->sHeader.usStructureSize) -+ - sizeof(ATOM_COMMON_TABLE_HEADER)) -+ / sizeof(ATOM_I2C_ID_CONFIG_ACCESS); -+ -+ } -+ } -+ -+ return number; -+} -+ -+struct graphics_object_id dal_bios_parser_get_encoder_id(struct bios_parser *bp, -+ uint32_t i) -+{ -+ 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; -+} -+ -+struct graphics_object_id dal_bios_parser_get_connector_id( -+ struct bios_parser *bp, -+ uint8_t i) -+{ -+ 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; -+} -+ -+uint32_t dal_bios_parser_get_src_number(struct bios_parser *bp, -+ struct graphics_object_id id) -+{ -+ uint32_t offset; -+ uint8_t *number; -+ ATOM_OBJECT *object; -+ -+ object = get_bios_object(bp, id); -+ -+ if (!object) { -+ BREAK_TO_DEBUGGER(); /* Invalid object id */ -+ return 0; -+ } -+ -+ offset = le16_to_cpu(object->usSrcDstTableOffset) -+ + bp->object_info_tbl_offset; -+ -+ number = GET_IMAGE(uint8_t, offset); -+ if (!number) -+ return 0; -+ -+ return *number; -+} -+ -+uint32_t dal_bios_parser_get_dst_number(struct bios_parser *bp, -+ struct graphics_object_id id) -+{ -+ ATOM_OBJECT *object = get_bios_object(bp, id); -+ -+ return get_dst_number_from_object(bp, object); -+} -+ -+enum bp_result dal_bios_parser_get_src_obj(struct bios_parser *bp, -+ 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; -+ -+ 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; -+} -+ -+enum bp_result dal_bios_parser_get_dst_obj(struct bios_parser *bp, -+ 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; -+ -+ 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; -+} -+ -+enum bp_result dal_bios_parser_get_oem_ddc_info(struct bios_parser *bp, -+ uint32_t index, -+ struct graphics_object_i2c_info *info) -+{ -+ -+ if (!info) -+ return BP_RESULT_BADINPUT; -+ -+ if (DATA_TABLES(OemInfo) != 0) { -+ ATOM_OEM_INFO *tbl; -+ -+ tbl = GET_IMAGE(ATOM_OEM_INFO, DATA_TABLES(OemInfo)); -+ -+ if (le16_to_cpu(tbl->sHeader.usStructureSize) -+ > sizeof(ATOM_COMMON_TABLE_HEADER)) { -+ ATOM_I2C_RECORD record; -+ ATOM_I2C_ID_CONFIG_ACCESS *config; -+ -+ dc_service_memset(&record, 0, sizeof(record)); -+ -+ config = &tbl->sucI2cId + index - 1; -+ -+ record.sucI2cId.bfHW_Capable = -+ config->sbfAccess.bfHW_Capable; -+ record.sucI2cId.bfI2C_LineMux = -+ config->sbfAccess.bfI2C_LineMux; -+ record.sucI2cId.bfHW_EngineID = -+ config->sbfAccess.bfHW_EngineID; -+ -+ return get_gpio_i2c_info(bp, &record, info); -+ } -+ } -+ -+ return BP_RESULT_NORECORD; -+} -+ -+enum bp_result dal_bios_parser_get_i2c_info(struct bios_parser *bp, -+ 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; -+ -+ 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; -+} -+ -+enum bp_result dal_bios_parser_get_voltage_ddc_info(struct bios_parser *bp, -+ 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}; -+ -+ if (!DATA_TABLES(VoltageObjectInfo)) -+ return result; -+ -+ voltage_info_address = get_image(bp, -+ DATA_TABLES(VoltageObjectInfo), -+ sizeof(ATOM_COMMON_TABLE_HEADER)); -+ -+ header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; -+ -+ get_atom_data_table_revision(header, &revision); -+ -+ switch (revision.major) { -+ case 1: -+ case 2: -+ result = get_voltage_ddc_info_v1(&i2c_line, header, -+ voltage_info_address); -+ break; -+ case 3: -+ if (revision.minor != 1) -+ break; -+ result = get_voltage_ddc_info_v3(&i2c_line, index, header, -+ voltage_info_address); -+ break; -+ } -+ -+ if (result == BP_RESULT_OK) -+ result = dal_bios_parser_get_thermal_ddc_info(bp, -+ i2c_line, info); -+ -+ -+ return result; -+} -+ -+enum bp_result dal_bios_parser_get_thermal_ddc_info( -+ struct bios_parser *bp, -+ uint32_t i2c_channel_id, -+ struct graphics_object_i2c_info *info) -+{ -+ 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); -+} -+ -+enum bp_result dal_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; -+} -+ -+enum bp_result dal_bios_parser_get_hpd_info(struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct graphics_object_hpd_info *info) -+{ -+ 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; -+} -+ -+uint32_t dal_bios_parser_get_gpio_record( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct bp_gpio_cntl_info *gpio_record, -+ uint32_t record_size) -+{ -+ 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 dal_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; -+} -+ -+enum bp_result dal_bios_parser_get_device_tag( -+ struct bios_parser *bp, -+ struct graphics_object_id connector_object_id, -+ uint32_t device_tag_index, -+ struct connector_device_tag_info *info) -+{ -+ 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 (dal_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); -+ -+enum bp_result dal_bios_parser_get_firmware_info( -+ struct bios_parser *bp, -+ struct firmware_info *info) -+{ -+ 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; -+ -+ dc_service_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; -+ -+ dc_service_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; -+ -+ dc_service_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]; -+ -+ dc_service_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; -+} -+ -+enum bp_result dal_bios_parser_transmitter_control( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl) -+{ -+ if (!bp->cmd_tbl.transmitter_control) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.transmitter_control(bp, cntl); -+} -+ -+enum bp_result dal_bios_parser_encoder_control( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ if (!bp->cmd_tbl.dig_encoder_control) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.dig_encoder_control(bp, cntl); -+} -+ -+enum bp_result dal_bios_parser_adjust_pixel_clock( -+ struct bios_parser *bp, -+ struct bp_adjust_pixel_clock_parameters *bp_params) -+{ -+ if (!bp->cmd_tbl.adjust_display_pll) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.adjust_display_pll(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_set_pixel_clock( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params) -+{ -+ if (!bp->cmd_tbl.set_pixel_clock) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.set_pixel_clock(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_enable_spread_spectrum_on_ppll( -+ struct bios_parser *bp, -+ struct bp_spread_spectrum_parameters *bp_params, -+ bool enable) -+{ -+ 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); -+ -+} -+ -+enum bp_result dal_bios_parser_program_crtc_timing( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params) -+{ -+ if (!bp->cmd_tbl.set_crtc_timing) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.set_crtc_timing(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_program_display_engine_pll( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params) -+{ -+ -+ if (!bp->cmd_tbl.program_clock) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.program_clock(bp, bp_params); -+ -+} -+ -+enum signal_type dal_bios_parser_dac_load_detect( -+ struct bios_parser *bp, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type display_signal) -+{ -+ if (!bp->cmd_tbl.dac_load_detection) -+ return SIGNAL_TYPE_NONE; -+ -+ return bp->cmd_tbl.dac_load_detection(bp, encoder, connector, -+ display_signal); -+} -+ -+enum bp_result dal_bios_parser_get_divider_for_target_display_clock( -+ struct bios_parser *bp, -+ struct bp_display_clock_parameters *bp_params) -+{ -+ if (!bp->cmd_tbl.compute_memore_engine_pll) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.compute_memore_engine_pll(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_dvo_encoder_control( -+ struct bios_parser *bp, -+ struct bp_dvo_encoder_control *cntl) -+{ -+ if (!bp->cmd_tbl.dvo_encoder_control) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.dvo_encoder_control(bp, cntl); -+} -+ -+enum bp_result dal_bios_parser_enable_crtc( -+ struct bios_parser *bp, -+ enum controller_id id, -+ bool enable) -+{ -+ if (!bp->cmd_tbl.enable_crtc) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.enable_crtc(bp, id, enable); -+} -+ -+enum bp_result dal_bios_parser_blank_crtc( -+ struct bios_parser *bp, -+ struct bp_blank_crtc_parameters *bp_params, -+ bool blank) -+{ -+ if (!bp->cmd_tbl.blank_crtc) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.blank_crtc(bp, bp_params, blank); -+} -+ -+enum bp_result dal_bios_parser_crtc_source_select( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params) -+{ -+ if (!bp->cmd_tbl.select_crtc_source) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.select_crtc_source(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_set_overscan( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_overscan_parameters *bp_params) -+{ -+ -+ if (!bp->cmd_tbl.set_crtc_overscan) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.set_crtc_overscan(bp, bp_params); -+} -+ -+enum bp_result dal_bios_parser_enable_memory_requests( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ bool enable) -+{ -+ if (!bp->cmd_tbl.enable_crtc_mem_req) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.enable_crtc_mem_req(bp, controller_id, enable); -+} -+ -+enum bp_result dal_bios_parser_external_encoder_control( -+ struct bios_parser *bp, -+ struct bp_external_encoder_control *cntl) -+{ -+ if (!bp->cmd_tbl.external_encoder_control) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.external_encoder_control(bp, cntl); -+} -+ -+enum bp_result dal_bios_parser_enable_disp_power_gating( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ enum bp_pipe_control_action action) -+{ -+ if (!bp->cmd_tbl.enable_disp_power_gating) -+ return BP_RESULT_FAILURE; -+ -+ return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, -+ action); -+} -+ -+bool dal_bios_parser_is_device_id_supported( -+ struct bios_parser *bp, -+ struct device_id id) -+{ -+ uint32_t mask = get_support_mask_for_device_id(id); -+ -+ return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; -+} -+ -+enum bp_result dal_bios_parser_crt_control( -+ struct bios_parser *bp, -+ enum engine_id engine_id, -+ bool enable, -+ uint32_t pixel_clock) -+{ -+ 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); -+/** -+ * dal_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 -+ */ -+enum bp_result dal_bios_parser_get_spread_spectrum_info( -+ struct bios_parser *bp, -+ enum as_signal_type signal, -+ uint32_t index, -+ struct spread_spectrum_info *ss_info) -+{ -+ 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)); -+ -+ dc_service_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 (dal_bios_parser_get_embedded_panel_info(bp, &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; -+ -+ dc_service_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); -+ -+enum bp_result dal_bios_parser_get_embedded_panel_info( -+ struct bios_parser *bp, -+ struct embedded_panel_info *info) -+{ -+ 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; -+ -+ dc_service_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; -+ -+ dc_service_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; -+} -+ -+/** -+ * dal_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 -+ * -+ */ -+enum bp_result dal_bios_parser_get_encoder_cap_info( -+ struct bios_parser *bp, -+ struct graphics_object_id object_id, -+ struct bp_encoder_cap_info *info) -+{ -+ 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; -+} -+ -+/** -+ * dal_bios_parser_get_din_connector_info -+ * @brief -+ * Get GPIO record for the DIN connector, this GPIO tells whether there is a -+ * CV dumb dongle -+ * attached to the DIN connector to perform load detection for the the -+ * appropriate signal -+ * -+ * @param id - DIN connector object id -+ * @param info - GPIO record infor -+ * @return Bios parser result code -+ */ -+enum bp_result dal_bios_parser_get_din_connector_info( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct din_connector_info *info) -+{ -+ ATOM_COMMON_RECORD_HEADER *header; -+ ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *record = NULL; -+ ATOM_OBJECT *object; -+ uint32_t offset; -+ enum bp_result result = BP_RESULT_NORECORD; -+ -+ /* no output buffer provided */ -+ if (!info) { -+ BREAK_TO_DEBUGGER(); /* Invalid output buffer */ -+ return BP_RESULT_BADINPUT; -+ } -+ -+ object = get_bios_object(bp, id); -+ if (!object) { -+ BREAK_TO_DEBUGGER(); /* Invalid object id */; -+ return BP_RESULT_BADINPUT; -+ } -+ -+ offset = le16_to_cpu(object->usRecordOffset) -+ + bp->object_info_tbl_offset; -+ -+ for (;;) { -+ header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); -+ -+ if (!header) { -+ result = BP_RESULT_BADBIOSTABLE; -+ break; -+ } -+ -+ offset += header->ucRecordSize; -+ -+ /* get out of the loop if no more records */ -+ if (LAST_RECORD_TYPE == header->ucRecordType || -+ !header->ucRecordSize) -+ break; -+ -+ if (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE != -+ header->ucRecordType) -+ continue; -+ -+ if (sizeof(ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD) -+ > header->ucRecordSize) -+ continue; -+ -+ record = (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *)header; -+ result = BP_RESULT_OK; -+ break; -+ } -+ -+ /* return if the record not found */ -+ if (result != BP_RESULT_OK) -+ return result; -+ -+ info->gpio_id = record->ucGPIOID; -+ info->gpio_tv_active_state = (record->ucTVActiveState != 0); -+ -+ return result; -+} -+ -+static uint32_t get_ss_entry_number( -+ struct bios_parser *bp, -+ uint32_t id); -+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( -+ struct bios_parser *bp, -+ uint32_t id); -+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( -+ struct bios_parser *bp, -+ uint32_t id); -+static uint32_t get_ss_entry_number_from_ss_info_tbl( -+ struct bios_parser *bp, -+ uint32_t id); -+ -+/** -+ * BiosParserObject::GetNumberofSpreadSpectrumEntry -+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from -+ * the VBIOS that match the SSid (to be converted from signal) -+ * -+ * @param[in] signal, ASSignalType to be converted to SSid -+ * @return number of SS Entry that match the signal -+ */ -+uint32_t dal_bios_parser_get_ss_entry_number( -+ struct bios_parser *bp, -+ enum as_signal_type signal) -+{ -+ 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 (dal_bios_parser_get_embedded_panel_info(bp, &panel_info) -+ == BP_RESULT_OK) -+ id_local = panel_info.ss_id; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ if (id_local == SS_ID_UNKNOWN) -+ return number; -+ -+ table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - -+ sizeof(ATOM_COMMON_TABLE_HEADER)) / -+ sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); -+ -+ for (i = 0; i < table_size; i++) -+ if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { -+ number = 1; -+ break; -+ } -+ -+ return number; -+} -+ -+ -+/** -+ * get_ss_entry_number -+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or -+ * SS_Info table from the VBIOS -+ * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or -+ * SS_Info. -+ * -+ * @param id, spread sprectrum info index -+ * @return Bios parser result code -+ */ -+static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) -+{ -+ if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) -+ return get_ss_entry_number_from_ss_info_tbl(bp, id); -+ -+ return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); -+} -+ -+/** -+ * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 -+ * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table -+ * Ver 2.1 from the VBIOS -+ * There will not be multiple entry for Ver 2.1 -+ * -+ * @param id, spread sprectrum info index -+ * @return number of SS Entry that match the id -+ */ -+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( -+ struct bios_parser *bp, -+ uint32_t id) -+{ -+ ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; -+ ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; -+ uint32_t size; -+ uint32_t i; -+ -+ if (!DATA_TABLES(ASIC_InternalSS_Info)) -+ return 0; -+ -+ header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, -+ DATA_TABLES(ASIC_InternalSS_Info)); -+ -+ size = (le16_to_cpu(header_include->sHeader.usStructureSize) -+ - sizeof(ATOM_COMMON_TABLE_HEADER)) -+ / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); -+ -+ tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) -+ &header_include->asSpreadSpectrum[0]; -+ for (i = 0; i < size; i++) -+ if (tbl[i].ucClockIndication == (uint8_t)id) -+ return 1; -+ -+ return 0; -+} -+/** -+ * get_ss_entry_number_from_internal_ss_info_table_V3_1 -+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of -+ * the VBIOS that matches id -+ * -+ * @param[in] id, spread sprectrum id -+ * @return number of SS Entry that match the id -+ */ -+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( -+ struct bios_parser *bp, -+ uint32_t id) -+{ -+ uint32_t number = 0; -+ ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; -+ ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; -+ uint32_t size; -+ uint32_t i; -+ -+ if (!DATA_TABLES(ASIC_InternalSS_Info)) -+ return number; -+ -+ header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, -+ DATA_TABLES(ASIC_InternalSS_Info)); -+ size = (le16_to_cpu(header_include->sHeader.usStructureSize) - -+ sizeof(ATOM_COMMON_TABLE_HEADER)) / -+ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); -+ -+ tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) -+ &header_include->asSpreadSpectrum[0]; -+ -+ for (i = 0; i < size; i++) -+ if (tbl[i].ucClockIndication == (uint8_t)id) -+ number++; -+ -+ return number; -+} -+ -+static ATOM_FAKE_EDID_PATCH_RECORD *get_faked_edid_record( -+ struct bios_parser *bp) -+{ -+ uint32_t size; -+ uint8_t *record; -+ ATOM_LVDS_INFO_V12 *info; -+ -+ if (!DATA_TABLES(LVDS_Info)) -+ return NULL; -+ -+ info = GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); -+ -+ if (!info) -+ return NULL; -+ -+ if (1 != info->sHeader.ucTableFormatRevision -+ || 2 > info->sHeader.ucTableContentRevision) -+ return NULL; -+ -+ if (!le16_to_cpu(info->usExtInfoTableOffset)) -+ return NULL; -+ -+ record = GET_IMAGE(uint8_t, DATA_TABLES(LVDS_Info) -+ + le16_to_cpu(info->usExtInfoTableOffset)); -+ -+ if (!record) -+ return NULL; -+ -+ for (;;) { -+ if (ATOM_RECORD_END_TYPE == *record) -+ return NULL; -+ -+ if (LCD_FAKE_EDID_PATCH_RECORD_TYPE == *record) -+ break; -+ -+ size = get_record_size(record); -+ -+ if (!size) -+ return NULL; -+ -+ record += size; -+ } -+ -+ return (ATOM_FAKE_EDID_PATCH_RECORD *)record; -+} -+ -+enum bp_result dal_bios_parser_get_faked_edid_len( -+ struct bios_parser *bp, -+ uint32_t *len) -+{ -+ ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp); -+ -+ if (!edid_record) -+ return BP_RESULT_NORECORD; -+ -+ *len = get_edid_size(edid_record); -+ -+ return BP_RESULT_OK; -+} -+ -+enum bp_result dal_bios_parser_get_faked_edid_buf( -+ struct bios_parser *bp, -+ uint8_t *buff, -+ uint32_t len) -+{ -+ ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp); -+ uint32_t edid_size; -+ -+ if (!edid_record) -+ return BP_RESULT_NORECORD; -+ -+ edid_size = get_edid_size(edid_record); -+ -+ if (len < edid_size) -+ return BP_RESULT_BADINPUT; /* buffer not big enough to fill */ -+ -+ dc_service_memmove(buff, &edid_record->ucFakeEDIDString, edid_size); -+ -+ return BP_RESULT_OK; -+} -+ -+/** -+ * dal_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 -+ */ -+enum bp_result dal_bios_parser_get_gpio_pin_info( -+ struct bios_parser *bp, -+ uint32_t gpio_id, -+ struct gpio_pin_info *info) -+{ -+ ATOM_GPIO_PIN_LUT *header; -+ uint32_t count = 0; -+ uint32_t i = 0; -+ -+ if (!DATA_TABLES(GPIO_Pin_LUT)) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT)); -+ if (!header) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT) -+ > le16_to_cpu(header->sHeader.usStructureSize)) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (1 != header->sHeader.ucTableContentRevision) -+ return BP_RESULT_UNSUPPORTED; -+ -+ count = (le16_to_cpu(header->sHeader.usStructureSize) -+ - sizeof(ATOM_COMMON_TABLE_HEADER)) -+ / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); -+ for (i = 0; i < count; ++i) { -+ if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) -+ continue; -+ -+ info->offset = -+ (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); -+ info->offset_y = info->offset + 2; -+ info->offset_en = info->offset + 1; -+ info->offset_mask = info->offset - 1; -+ -+ info->mask = (uint32_t) (1 << -+ header->asGPIO_Pin[i].ucGpioPinBitShift); -+ info->mask_y = info->mask + 2; -+ info->mask_en = info->mask + 1; -+ info->mask_mask = info->mask - 1; -+ -+ return BP_RESULT_OK; -+ } -+ -+ return BP_RESULT_NORECORD; -+} -+ -+/** -+ * BiosParserObject::EnumEmbeddedPanelPatchMode -+ * Get embedded panel patch mode -+ * -+ * @param index, mode index -+ * @param info, embedded panel patch mode structure -+ * @return Bios parser result code -+ */ -+enum bp_result dal_bios_parser_enum_embedded_panel_patch_mode( -+ struct bios_parser *bp, -+ uint32_t index, -+ struct embedded_panel_patch_mode *mode) -+{ -+ uint32_t record_size; -+ uint32_t record_index; -+ uint8_t *record; -+ ATOM_LVDS_INFO_V12 *info; -+ ATOM_PATCH_RECORD_MODE *mode_record; -+ ATOM_MASTER_LIST_OF_DATA_TABLES *list_of_tables; -+ -+ if (!mode) -+ return BP_RESULT_BADINPUT; -+ -+ list_of_tables = &bp->master_data_tbl->ListOfDataTables; -+ if (!list_of_tables->LVDS_Info) -+ return BP_RESULT_UNSUPPORTED; -+ -+ info = GET_IMAGE(ATOM_LVDS_INFO_V12, list_of_tables->LVDS_Info); -+ -+ if (!info) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (1 != info->sHeader.ucTableFormatRevision -+ || 2 > info->sHeader.ucTableContentRevision) -+ return BP_RESULT_UNSUPPORTED; -+ -+ if (!le16_to_cpu(info->usExtInfoTableOffset)) -+ return BP_RESULT_UNSUPPORTED; -+ -+ record = GET_IMAGE(uint8_t, list_of_tables->LVDS_Info + -+ le16_to_cpu(info->usExtInfoTableOffset)); -+ -+ if (!record) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ for (record_index = 0;;) { -+ if (ATOM_RECORD_END_TYPE == *record) -+ return BP_RESULT_NORECORD; -+ -+ if (LCD_MODE_PATCH_RECORD_MODE_TYPE == *record) { -+ if (record_index == index) -+ break; -+ record_index++; -+ } -+ -+ record_size = get_record_size(record); -+ -+ if (!record_size) -+ return BP_RESULT_NORECORD; -+ -+ record += record_size; -+ } -+ -+ mode_record = (ATOM_PATCH_RECORD_MODE *) record; -+ -+ mode->width = le16_to_cpu(mode_record->usHDisp); -+ mode->height = le16_to_cpu(mode_record->usVDisp); -+ -+ return BP_RESULT_OK; -+} -+ -+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, -+ ATOM_I2C_RECORD *record, -+ struct graphics_object_i2c_info *info) -+{ -+ ATOM_GPIO_I2C_INFO *header; -+ uint32_t count = 0; -+ -+ if (!info) -+ return BP_RESULT_BADINPUT; -+ -+ /* get the GPIO_I2C info */ -+ if (!DATA_TABLES(GPIO_I2C_Info)) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); -+ if (!header) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) -+ > le16_to_cpu(header->sHeader.usStructureSize)) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (1 != header->sHeader.ucTableContentRevision) -+ return BP_RESULT_UNSUPPORTED; -+ -+ /* get data count */ -+ count = (le16_to_cpu(header->sHeader.usStructureSize) -+ - sizeof(ATOM_COMMON_TABLE_HEADER)) -+ / sizeof(ATOM_GPIO_I2C_ASSIGMENT); -+ if (count < record->sucI2cId.bfI2C_LineMux) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ /* get the GPIO_I2C_INFO */ -+ info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; -+ info->i2c_line = record->sucI2cId.bfI2C_LineMux; -+ info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; -+ info->i2c_slave_address = record->ucI2CAddr; -+ -+ info->gpio_info.clk_mask_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); -+ info->gpio_info.clk_en_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); -+ info->gpio_info.clk_y_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); -+ info->gpio_info.clk_a_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); -+ info->gpio_info.data_mask_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); -+ info->gpio_info.data_en_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); -+ info->gpio_info.data_y_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); -+ info->gpio_info.data_a_register_index = -+ le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); -+ -+ info->gpio_info.clk_mask_shift = -+ header->asGPIO_Info[info->i2c_line].ucClkMaskShift; -+ info->gpio_info.clk_en_shift = -+ header->asGPIO_Info[info->i2c_line].ucClkEnShift; -+ info->gpio_info.clk_y_shift = -+ header->asGPIO_Info[info->i2c_line].ucClkY_Shift; -+ info->gpio_info.clk_a_shift = -+ header->asGPIO_Info[info->i2c_line].ucClkA_Shift; -+ info->gpio_info.data_mask_shift = -+ header->asGPIO_Info[info->i2c_line].ucDataMaskShift; -+ info->gpio_info.data_en_shift = -+ header->asGPIO_Info[info->i2c_line].ucDataEnShift; -+ info->gpio_info.data_y_shift = -+ header->asGPIO_Info[info->i2c_line].ucDataY_Shift; -+ info->gpio_info.data_a_shift = -+ header->asGPIO_Info[info->i2c_line].ucDataA_Shift; -+ -+ return BP_RESULT_OK; -+} -+ -+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, -+ struct graphics_object_id id) -+{ -+ uint32_t offset; -+ ATOM_OBJECT_TABLE *tbl; -+ uint32_t i; -+ -+ switch (id.type) { -+ case OBJECT_TYPE_ENCODER: -+ offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); -+ break; -+ -+ case OBJECT_TYPE_CONNECTOR: -+ offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); -+ break; -+ -+ case OBJECT_TYPE_ROUTER: -+ offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); -+ break; -+ -+ case OBJECT_TYPE_GENERIC: -+ if (bp->object_info_tbl.revision.minor < 3) -+ return NULL; -+ offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); -+ break; -+ -+ default: -+ return NULL; -+ } -+ -+ offset += bp->object_info_tbl_offset; -+ -+ tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset); -+ if (!tbl) -+ return NULL; -+ -+ for (i = 0; i < tbl->ucNumberOfObjects; i++) -+ if (dal_graphics_object_id_is_equal(id, -+ object_id_from_bios_object_id( -+ le16_to_cpu(tbl->asObjects[i].usObjectID)))) -+ return &tbl->asObjects[i]; -+ -+ return NULL; -+} -+ -+static uint32_t get_dest_obj_list(struct bios_parser *bp, -+ ATOM_OBJECT *object, uint16_t **id_list) -+{ -+ uint32_t offset; -+ uint8_t *number; -+ -+ if (!object) { -+ BREAK_TO_DEBUGGER(); /* Invalid object id */ -+ return 0; -+ } -+ -+ offset = le16_to_cpu(object->usSrcDstTableOffset) -+ + bp->object_info_tbl_offset; -+ -+ number = GET_IMAGE(uint8_t, offset); -+ if (!number) -+ return 0; -+ -+ offset += sizeof(uint8_t); -+ offset += sizeof(uint16_t) * (*number); -+ -+ number = GET_IMAGE(uint8_t, offset); -+ if ((!number) || (!*number)) -+ return 0; -+ -+ offset += sizeof(uint8_t); -+ *id_list = (uint16_t *)get_image(bp, offset, -+ *number * sizeof(uint16_t)); -+ -+ if (!*id_list) -+ return 0; -+ -+ return *number; -+} -+ -+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, -+ uint16_t **id_list) -+{ -+ uint32_t offset; -+ uint8_t *number; -+ -+ if (!object) { -+ BREAK_TO_DEBUGGER(); /* Invalid object id */ -+ return 0; -+ } -+ -+ offset = le16_to_cpu(object->usSrcDstTableOffset) -+ + bp->object_info_tbl_offset; -+ -+ number = GET_IMAGE(uint8_t, offset); -+ if (!number) -+ return 0; -+ -+ offset += sizeof(uint8_t); -+ *id_list = (uint16_t *)get_image(bp, offset, -+ *number * sizeof(uint16_t)); -+ -+ if (!*id_list) -+ return 0; -+ -+ return *number; -+} -+ -+static uint32_t get_dst_number_from_object(struct bios_parser *bp, -+ ATOM_OBJECT *object) -+{ -+ uint32_t offset; -+ uint8_t *number; -+ -+ if (!object) { -+ BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/ -+ return 0; -+ } -+ -+ offset = le16_to_cpu(object->usSrcDstTableOffset) -+ + bp->object_info_tbl_offset; -+ -+ number = GET_IMAGE(uint8_t, offset); -+ if (!number) -+ return 0; -+ -+ offset += sizeof(uint8_t); -+ offset += sizeof(uint16_t) * (*number); -+ -+ number = GET_IMAGE(uint8_t, offset); -+ -+ if (!number) -+ return 0; -+ -+ return *number; -+} -+ -+static uint8_t *get_image(struct bios_parser *bp, -+ uint32_t offset, -+ uint32_t size) -+{ -+ if (bp->bios && offset + size < bp->bios_size) -+ return bp->bios + offset; -+ else -+ return NULL; -+} -+ -+static uint32_t get_record_size(uint8_t *record) -+{ -+ switch (*record) { -+ case LCD_MODE_PATCH_RECORD_MODE_TYPE: -+ return sizeof(ATOM_PATCH_RECORD_MODE); -+ -+ case LCD_RTS_RECORD_TYPE: -+ return sizeof(ATOM_LCD_RTS_RECORD); -+ -+ case LCD_CAP_RECORD_TYPE: -+ return sizeof(ATOM_LCD_MODE_CONTROL_CAP); -+ -+ case LCD_FAKE_EDID_PATCH_RECORD_TYPE: { -+ ATOM_FAKE_EDID_PATCH_RECORD *fake_record = -+ (ATOM_FAKE_EDID_PATCH_RECORD *) record; -+ uint32_t edid_size = get_edid_size(fake_record); -+ -+ return sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + edid_size -+ - sizeof(fake_record->ucFakeEDIDString); -+ } -+ -+ case LCD_PANEL_RESOLUTION_RECORD_TYPE: -+ return sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); -+ -+ default: -+ return 0; -+ } -+} -+ -+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid) -+{ -+ uint32_t length = edid->ucFakeEDIDLength; -+ -+ if (length < 128) -+ length = length * 128; -+ -+ return length; -+} -+ -+static struct graphics_object_id object_id_from_bios_object_id( -+ uint32_t bios_object_id) -+{ -+ enum object_type type; -+ enum object_enum_id enum_id; -+ struct graphics_object_id go_id = { 0 }; -+ -+ type = object_type_from_bios_object_id(bios_object_id); -+ -+ if (OBJECT_TYPE_UNKNOWN == type) -+ return go_id; -+ -+ enum_id = enum_id_from_bios_object_id(bios_object_id); -+ -+ if (ENUM_ID_UNKNOWN == enum_id) -+ return go_id; -+ -+ go_id = dal_graphics_object_id_init( -+ id_from_bios_object_id(type, bios_object_id), enum_id, type); -+ -+ return go_id; -+} -+ -+static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) -+{ -+ uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) -+ >> OBJECT_TYPE_SHIFT; -+ enum object_type object_type; -+ -+ switch (bios_object_type) { -+ case GRAPH_OBJECT_TYPE_GPU: -+ object_type = OBJECT_TYPE_GPU; -+ break; -+ case GRAPH_OBJECT_TYPE_ENCODER: -+ object_type = OBJECT_TYPE_ENCODER; -+ break; -+ case GRAPH_OBJECT_TYPE_CONNECTOR: -+ object_type = OBJECT_TYPE_CONNECTOR; -+ break; -+ case GRAPH_OBJECT_TYPE_ROUTER: -+ object_type = OBJECT_TYPE_ROUTER; -+ break; -+ case GRAPH_OBJECT_TYPE_GENERIC: -+ object_type = OBJECT_TYPE_GENERIC; -+ break; -+ default: -+ object_type = OBJECT_TYPE_UNKNOWN; -+ break; -+ } -+ -+ return object_type; -+} -+ -+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) -+{ -+ uint32_t bios_enum_id = -+ (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; -+ enum object_enum_id id; -+ -+ switch (bios_enum_id) { -+ case GRAPH_OBJECT_ENUM_ID1: -+ id = ENUM_ID_1; -+ break; -+ case GRAPH_OBJECT_ENUM_ID2: -+ id = ENUM_ID_2; -+ break; -+ case GRAPH_OBJECT_ENUM_ID3: -+ id = ENUM_ID_3; -+ break; -+ case GRAPH_OBJECT_ENUM_ID4: -+ id = ENUM_ID_4; -+ break; -+ case GRAPH_OBJECT_ENUM_ID5: -+ id = ENUM_ID_5; -+ break; -+ case GRAPH_OBJECT_ENUM_ID6: -+ id = ENUM_ID_6; -+ break; -+ case GRAPH_OBJECT_ENUM_ID7: -+ id = ENUM_ID_7; -+ break; -+ default: -+ id = ENUM_ID_UNKNOWN; -+ break; -+ } -+ -+ return id; -+} -+ -+static uint32_t id_from_bios_object_id(enum object_type type, -+ uint32_t bios_object_id) -+{ -+ switch (type) { -+ case OBJECT_TYPE_GPU: -+ return gpu_id_from_bios_object_id(bios_object_id); -+ case OBJECT_TYPE_ENCODER: -+ return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); -+ case OBJECT_TYPE_CONNECTOR: -+ return (uint32_t)connector_id_from_bios_object_id( -+ bios_object_id); -+ case OBJECT_TYPE_GENERIC: -+ return generic_id_from_bios_object_id(bios_object_id); -+ default: -+ return 0; -+ } -+} -+ -+static enum connector_id connector_id_from_bios_object_id( -+ uint32_t bios_object_id) -+{ -+ uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); -+ -+ enum connector_id id; -+ -+ switch (bios_connector_id) { -+ case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: -+ id = CONNECTOR_ID_SINGLE_LINK_DVII; -+ break; -+ case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: -+ id = CONNECTOR_ID_DUAL_LINK_DVII; -+ break; -+ case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: -+ id = CONNECTOR_ID_SINGLE_LINK_DVID; -+ break; -+ case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: -+ id = CONNECTOR_ID_DUAL_LINK_DVID; -+ break; -+ case CONNECTOR_OBJECT_ID_VGA: -+ id = CONNECTOR_ID_VGA; -+ break; -+ case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: -+ id = CONNECTOR_ID_HDMI_TYPE_A; -+ break; -+ case CONNECTOR_OBJECT_ID_LVDS: -+ id = CONNECTOR_ID_LVDS; -+ break; -+ case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: -+ id = CONNECTOR_ID_PCIE; -+ break; -+ case CONNECTOR_OBJECT_ID_HARDCODE_DVI: -+ id = CONNECTOR_ID_HARDCODE_DVI; -+ break; -+ case CONNECTOR_OBJECT_ID_DISPLAYPORT: -+ id = CONNECTOR_ID_DISPLAY_PORT; -+ break; -+ case CONNECTOR_OBJECT_ID_eDP: -+ id = CONNECTOR_ID_EDP; -+ break; -+ case CONNECTOR_OBJECT_ID_MXM: -+ id = CONNECTOR_ID_MXM; -+ break; -+ default: -+ id = CONNECTOR_ID_UNKNOWN; -+ break; -+ } -+ -+ return id; -+} -+ -+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) -+{ -+ uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); -+ enum encoder_id id; -+ -+ switch (bios_encoder_id) { -+ case ENCODER_OBJECT_ID_INTERNAL_LVDS: -+ id = ENCODER_ID_INTERNAL_LVDS; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_TMDS1: -+ id = ENCODER_ID_INTERNAL_TMDS1; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_TMDS2: -+ id = ENCODER_ID_INTERNAL_TMDS2; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_DAC1: -+ id = ENCODER_ID_INTERNAL_DAC1; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_DAC2: -+ id = ENCODER_ID_INTERNAL_DAC2; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_SDVOA: -+ id = ENCODER_ID_INTERNAL_SDVOA; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_SDVOB: -+ id = ENCODER_ID_INTERNAL_SDVOB; -+ break; -+ case ENCODER_OBJECT_ID_SI170B: -+ id = ENCODER_ID_EXTERNAL_SI170B; -+ break; -+ case ENCODER_OBJECT_ID_CH7303: -+ id = ENCODER_ID_EXTERNAL_CH7303; -+ break; -+ case ENCODER_OBJECT_ID_CH7301: -+ id = ENCODER_ID_EXTERNAL_CH7301; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_DVO1: -+ id = ENCODER_ID_INTERNAL_DVO1; -+ break; -+ case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: -+ id = ENCODER_ID_EXTERNAL_SDVOA; -+ break; -+ case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: -+ id = ENCODER_ID_EXTERNAL_SDVOB; -+ break; -+ case ENCODER_OBJECT_ID_TITFP513: -+ id = ENCODER_ID_EXTERNAL_TITFP513; -+ break; -+ case ENCODER_OBJECT_ID_INTERNAL_LVTM1: -+ id = ENCODER_ID_INTERNAL_LVTM1; -+ break; -+ case ENCODER_OBJECT_ID_VT1623: -+ id = ENCODER_ID_EXTERNAL_VT1623; -+ break; -+ case ENCODER_OBJECT_ID_HDMI_SI1930: -+ id = ENCODER_ID_EXTERNAL_SI1930; -+ 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_DVO1: -+ id = ENCODER_ID_INTERNAL_KLDSCP_DVO1; -+ 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_SI178: -+ id = ENCODER_ID_EXTERNAL_SI178; -+ 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_VT1625: -+ id = ENCODER_ID_EXTERNAL_VT1625; -+ break; -+ case ENCODER_OBJECT_ID_HDMI_SI1932: -+ id = ENCODER_ID_EXTERNAL_SI1932; -+ break; -+ case ENCODER_OBJECT_ID_DP_AN9801: -+ id = ENCODER_ID_EXTERNAL_AN9801; -+ break; -+ case ENCODER_OBJECT_ID_DP_DP501: -+ id = ENCODER_ID_EXTERNAL_DP501; -+ 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_GENERAL_EXTERNAL_DVO: -+ id = ENCODER_ID_EXTERNAL_GENERIC_DVO; -+ 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; -+ break; -+ } -+ -+ return id; -+} -+ -+uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) -+{ -+ return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; -+} -+ -+enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) -+{ -+ uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); -+ -+ enum generic_id id; -+ -+ switch (bios_generic_id) { -+ case GENERIC_OBJECT_ID_MXM_OPM: -+ id = GENERIC_ID_MXM_OPM; -+ break; -+ case GENERIC_OBJECT_ID_GLSYNC: -+ id = GENERIC_ID_GLSYNC; -+ break; -+ case GENERIC_OBJECT_ID_STEREO_PIN: -+ id = GENERIC_ID_STEREO; -+ break; -+ default: -+ id = GENERIC_ID_UNKNOWN; -+ break; -+ } -+ -+ return id; -+} -+ -+static struct device_id device_type_from_device_id(uint16_t device_id) -+{ -+ -+ struct device_id result_device_id; -+ -+ switch (device_id) { -+ case ATOM_DEVICE_LCD1_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_LCD; -+ result_device_id.enum_id = 1; -+ break; -+ -+ case ATOM_DEVICE_LCD2_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_LCD; -+ result_device_id.enum_id = 2; -+ break; -+ -+ case ATOM_DEVICE_CRT1_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_CRT; -+ result_device_id.enum_id = 1; -+ break; -+ -+ case ATOM_DEVICE_CRT2_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_CRT; -+ result_device_id.enum_id = 2; -+ break; -+ -+ case ATOM_DEVICE_DFP1_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 1; -+ break; -+ -+ case ATOM_DEVICE_DFP2_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 2; -+ break; -+ -+ case ATOM_DEVICE_DFP3_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 3; -+ break; -+ -+ case ATOM_DEVICE_DFP4_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 4; -+ break; -+ -+ case ATOM_DEVICE_DFP5_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 5; -+ break; -+ -+ case ATOM_DEVICE_DFP6_SUPPORT: -+ result_device_id.device_type = DEVICE_TYPE_DFP; -+ result_device_id.enum_id = 6; -+ break; -+ -+ default: -+ BREAK_TO_DEBUGGER(); /* Invalid device Id */ -+ result_device_id.device_type = DEVICE_TYPE_UNKNOWN; -+ result_device_id.enum_id = 0; -+ } -+ return result_device_id; -+} -+ -+static void get_atom_data_table_revision( -+ ATOM_COMMON_TABLE_HEADER *atom_data_tbl, -+ struct atom_data_revision *tbl_revision) -+{ -+ if (!tbl_revision) -+ return; -+ -+ /* initialize the revision to 0 which is invalid revision */ -+ tbl_revision->major = 0; -+ tbl_revision->minor = 0; -+ -+ if (!atom_data_tbl) -+ return; -+ -+ tbl_revision->major = -+ (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); -+ tbl_revision->minor = -+ (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); -+} -+ -+static uint32_t signal_to_ss_id(enum as_signal_type signal) -+{ -+ uint32_t clk_id_ss = 0; -+ -+ switch (signal) { -+ case AS_SIGNAL_TYPE_DVI: -+ clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; -+ break; -+ case AS_SIGNAL_TYPE_HDMI: -+ clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; -+ break; -+ case AS_SIGNAL_TYPE_LVDS: -+ clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; -+ break; -+ case AS_SIGNAL_TYPE_DISPLAY_PORT: -+ clk_id_ss = ASIC_INTERNAL_SS_ON_DP; -+ break; -+ case AS_SIGNAL_TYPE_GPU_PLL: -+ clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; -+ break; -+ default: -+ break; -+ } -+ return clk_id_ss; -+} -+ -+static uint32_t get_support_mask_for_device_id(struct device_id device_id) -+{ -+ enum dal_device_type device_type = device_id.device_type; -+ uint32_t enum_id = device_id.enum_id; -+ -+ switch (device_type) { -+ case DEVICE_TYPE_LCD: -+ switch (enum_id) { -+ case 1: -+ return ATOM_DEVICE_LCD1_SUPPORT; -+ case 2: -+ return ATOM_DEVICE_LCD2_SUPPORT; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_CRT: -+ switch (enum_id) { -+ case 1: -+ return ATOM_DEVICE_CRT1_SUPPORT; -+ case 2: -+ return ATOM_DEVICE_CRT2_SUPPORT; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_DFP: -+ switch (enum_id) { -+ case 1: -+ return ATOM_DEVICE_DFP1_SUPPORT; -+ case 2: -+ return ATOM_DEVICE_DFP2_SUPPORT; -+ case 3: -+ return ATOM_DEVICE_DFP3_SUPPORT; -+ case 4: -+ return ATOM_DEVICE_DFP4_SUPPORT; -+ case 5: -+ return ATOM_DEVICE_DFP5_SUPPORT; -+ case 6: -+ return ATOM_DEVICE_DFP6_SUPPORT; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_CV: -+ switch (enum_id) { -+ case 1: -+ return ATOM_DEVICE_CV_SUPPORT; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_TV: -+ switch (enum_id) { -+ case 1: -+ return ATOM_DEVICE_TV1_SUPPORT; -+ default: -+ break; -+ } -+ break; -+ default: -+ break; -+ }; -+ -+ /* Unidentified device ID, return empty support mask. */ -+ return 0; -+} -+ -+/** -+* HwContext interface for writing MM registers -+*/ -+ -+static bool i2c_read( -+ struct bios_parser *bp, -+ struct graphics_object_i2c_info *i2c_info, -+ uint8_t *buffer, -+ uint32_t length) -+{ -+ struct ddc *ddc; -+ uint8_t offset[2] = { 0, 0 }; -+ bool result = false; -+ struct i2c_command cmd; -+ -+ ddc = dal_adapter_service_obtain_ddc_from_i2c_info(bp->as, i2c_info); -+ -+ if (!ddc) -+ return result; -+ -+ /*Using SW engine */ -+ cmd.engine = I2C_COMMAND_ENGINE_SW; -+ cmd.speed = dal_adapter_service_get_sw_i2c_speed(bp->as); -+ -+ { -+ struct i2c_payload payloads[] = { -+ { -+ .address = i2c_info->i2c_slave_address >> 1, -+ .data = offset, -+ .length = sizeof(offset), -+ .write = true -+ }, -+ { -+ .address = i2c_info->i2c_slave_address >> 1, -+ .data = buffer, -+ .length = length, -+ .write = false -+ } -+ }; -+ -+ cmd.payloads = payloads; -+ cmd.number_of_payloads = ARRAY_SIZE(payloads); -+ -+ result = dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(bp->as), -+ ddc, -+ &cmd); -+ } -+ -+ dal_adapter_service_release_ddc(bp->as, ddc); -+ -+ return result; -+} -+ -+/** -+ * Read external display connection info table through i2c. -+ * validate the GUID and checksum. -+ * -+ * @return enum bp_result whether all data was sucessfully read -+ */ -+static enum bp_result get_ext_display_connection_info( -+ struct bios_parser *bp, -+ ATOM_OBJECT *opm_object, -+ ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl) -+{ -+ bool config_tbl_present = false; -+ ATOM_I2C_RECORD *i2c_record = NULL; -+ uint32_t i = 0; -+ -+ if (opm_object == NULL) -+ return BP_RESULT_BADINPUT; -+ -+ i2c_record = get_i2c_record(bp, opm_object); -+ -+ if (i2c_record != NULL) { -+ ATOM_GPIO_I2C_INFO *gpio_i2c_header; -+ struct graphics_object_i2c_info i2c_info; -+ -+ gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO, -+ bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info); -+ -+ if (NULL == gpio_i2c_header) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) != -+ BP_RESULT_OK) -+ return BP_RESULT_BADBIOSTABLE; -+ -+ if (i2c_read( -+ bp, -+ &i2c_info, -+ (uint8_t *)ext_display_connection_info_tbl, -+ sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) { -+ config_tbl_present = true; -+ } -+ } -+ -+ /* Validate GUID */ -+ if (config_tbl_present) -+ for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) { -+ if (ext_display_connection_info_tbl->ucGuid[i] -+ != ext_display_connection_guid[i]) { -+ config_tbl_present = false; -+ break; -+ } -+ } -+ -+ /* Validate checksum */ -+ if (config_tbl_present) { -+ uint8_t check_sum = 0; -+ uint8_t *buf = -+ (uint8_t *)ext_display_connection_info_tbl; -+ -+ for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); -+ i++) { -+ check_sum += buf[i]; -+ } -+ -+ if (check_sum != 0) -+ config_tbl_present = false; -+ } -+ -+ if (config_tbl_present) -+ return BP_RESULT_OK; -+ else -+ return BP_RESULT_FAILURE; -+} -+ -+/* -+ * Gets the first device ID in the same group as the given ID for enumerating. -+ * For instance, if any DFP device ID is passed, returns the device ID for DFP1. -+ * -+ * The first device ID in the same group as the passed device ID, or 0 if no -+ * matching device group found. -+ */ -+static uint32_t enum_first_device_id(uint32_t dev_id) -+{ -+ /* Return the first in the group that this ID belongs to. */ -+ if (dev_id & ATOM_DEVICE_CRT_SUPPORT) -+ return ATOM_DEVICE_CRT1_SUPPORT; -+ else if (dev_id & ATOM_DEVICE_DFP_SUPPORT) -+ return ATOM_DEVICE_DFP1_SUPPORT; -+ else if (dev_id & ATOM_DEVICE_LCD_SUPPORT) -+ return ATOM_DEVICE_LCD1_SUPPORT; -+ else if (dev_id & ATOM_DEVICE_TV_SUPPORT) -+ return ATOM_DEVICE_TV1_SUPPORT; -+ else if (dev_id & ATOM_DEVICE_CV_SUPPORT) -+ return ATOM_DEVICE_CV_SUPPORT; -+ -+ /* No group found for this device ID. */ -+ -+ dal_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 = -+ dal_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; -+ -+ dc_service_memset(&ext_display_connection_info_tbl, 0, -+ sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO)); -+ -+ connector_tbl_offset = bp->object_info_tbl_offset -+ + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); -+ connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); -+ -+ /* Read Connector info table from EEPROM through i2c */ -+ if (get_ext_display_connection_info( -+ bp, -+ opm_object, -+ &ext_display_connection_info_tbl) != BP_RESULT_OK) { -+ if (bp->headless_no_opm) { -+ /* Failed to read OPM, remove all non-CF connectors. */ -+ for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { -+ object = &connector_tbl->asObjects[i]; -+ object_id = object_id_from_bios_object_id( -+ le16_to_cpu(object->usObjectID)); -+ if (OBJECT_TYPE_CONNECTOR == object_id.type) -+ object->usObjectID = cpu_to_le16(0); -+ } -+ -+ return BP_RESULT_OK; -+ } -+ -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: Failed to read Connection Info Table", __func__); -+ return BP_RESULT_UNSUPPORTED; -+ } -+ -+ /* Get pointer to AUX/DDC and HPD LUTs */ -+ aux_ddc_lut_record = -+ get_ext_connector_aux_ddc_lut_record(bp, opm_object); -+ hpd_pin_lut_record = -+ get_ext_connector_hpd_pin_lut_record(bp, opm_object); -+ -+ if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL)) -+ return BP_RESULT_UNSUPPORTED; -+ -+ /* Cache support bits for currently unmapped device types. */ -+ if (bp->remap_device_tags) { -+ for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { -+ uint32_t j; -+ /* Remove support for all non-MXM connectors. */ -+ object = &connector_tbl->asObjects[i]; -+ object_id = object_id_from_bios_object_id( -+ le16_to_cpu(object->usObjectID)); -+ if ((OBJECT_TYPE_CONNECTOR != object_id.type) || -+ (CONNECTOR_ID_MXM == object_id.id)) -+ continue; -+ -+ /* Remove support for all device tags. */ -+ if (dal_bios_parser_get_device_tag_record( -+ bp, object, &dev_tag_record) != BP_RESULT_OK) -+ continue; -+ -+ for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) { -+ ATOM_CONNECTOR_DEVICE_TAG *device_tag = -+ &dev_tag_record->asDeviceTag[j]; -+ cached_device_support &= -+ ~le16_to_cpu(device_tag->usDeviceID); -+ } -+ } -+ } -+ -+ /* Find all MXM connector objects and patch them with connector info -+ * from the external display connection info table. */ -+ for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { -+ uint32_t j; -+ -+ object = &connector_tbl->asObjects[i]; -+ object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); -+ if ((OBJECT_TYPE_CONNECTOR != object_id.type) || -+ (CONNECTOR_ID_MXM != object_id.id)) -+ continue; -+ -+ /* Get the correct connection info table entry based on the enum -+ * id. */ -+ ext_display_path = get_ext_display_path_entry( -+ &ext_display_connection_info_tbl, -+ le16_to_cpu(object->usObjectID)); -+ if (!ext_display_path) -+ return BP_RESULT_FAILURE; -+ -+ /* Patch device connector ID */ -+ object->usObjectID = -+ cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector)); -+ -+ /* Patch device tag, ulACPIDeviceEnum. */ -+ add_device_tag_from_ext_display_path( -+ bp, -+ object, -+ ext_display_path, -+ &cached_device_support); -+ -+ /* Patch HPD info */ -+ if (ext_display_path->ucExtHPDPINLutIndex < -+ MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) { -+ hpd_record = get_hpd_record(bp, object); -+ if (hpd_record) { -+ uint8_t index = -+ ext_display_path->ucExtHPDPINLutIndex; -+ hpd_record->ucHPDIntGPIOID = -+ hpd_pin_lut_record->ucHPDPINMap[index]; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ /* Invalid hpd record */ -+ return BP_RESULT_FAILURE; -+ } -+ } -+ -+ /* Patch I2C/AUX info */ -+ if (ext_display_path->ucExtHPDPINLutIndex < -+ MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) { -+ i2c_record = get_i2c_record(bp, object); -+ if (i2c_record) { -+ uint8_t index = -+ ext_display_path->ucExtAUXDDCLutIndex; -+ i2c_record->sucI2cId = -+ aux_ddc_lut_record->ucAUXDDCMap[index]; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ /* Invalid I2C record */ -+ return BP_RESULT_FAILURE; -+ } -+ } -+ -+ /* Merge with other MXM connectors that map to the same physical -+ * connector. */ -+ for (j = i + 1; -+ j < connector_tbl->ucNumberOfObjects; j++) { -+ ATOM_OBJECT *next_object; -+ struct graphics_object_id next_object_id; -+ EXT_DISPLAY_PATH *next_ext_display_path; -+ -+ next_object = &connector_tbl->asObjects[j]; -+ next_object_id = object_id_from_bios_object_id( -+ le16_to_cpu(next_object->usObjectID)); -+ -+ if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) && -+ (CONNECTOR_ID_MXM == next_object_id.id)) -+ continue; -+ -+ next_ext_display_path = get_ext_display_path_entry( -+ &ext_display_connection_info_tbl, -+ le16_to_cpu(next_object->usObjectID)); -+ -+ if (next_ext_display_path == NULL) -+ return BP_RESULT_FAILURE; -+ -+ /* Merge if using same connector. */ -+ if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) == -+ le16_to_cpu(ext_display_path->usDeviceConnector)) && -+ (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) { -+ /* Clear duplicate connector from table. */ -+ next_object->usObjectID = cpu_to_le16(0); -+ add_device_tag_from_ext_display_path( -+ bp, -+ object, -+ ext_display_path, -+ &cached_device_support); -+ } -+ } -+ } -+ -+ /* Find all encoders which have an MXM object as their destination. -+ * Replace the MXM object with the real connector Id from the external -+ * display connection info table */ -+ -+ encoder_table_offset = bp->object_info_tbl_offset -+ + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); -+ encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); -+ -+ for (i = 0; i < encoder_table->ucNumberOfObjects; i++) { -+ uint32_t j; -+ -+ object = &encoder_table->asObjects[i]; -+ -+ dst_number = get_dest_obj_list(bp, object, &dst_object_id_list); -+ -+ for (j = 0; j < dst_number; j++) { -+ object_id = object_id_from_bios_object_id( -+ dst_object_id_list[j]); -+ -+ if ((OBJECT_TYPE_CONNECTOR != object_id.type) || -+ (CONNECTOR_ID_MXM != object_id.id)) -+ continue; -+ -+ /* Get the correct connection info table entry based on -+ * the enum id. */ -+ ext_display_path = -+ get_ext_display_path_entry( -+ &ext_display_connection_info_tbl, -+ dst_object_id_list[j]); -+ -+ if (ext_display_path == NULL) -+ return BP_RESULT_FAILURE; -+ -+ dst_object_id_list[j] = -+ le16_to_cpu(ext_display_path->usDeviceConnector); -+ } -+ } -+ -+ return BP_RESULT_OK; -+} -+ -+/* -+ * Check whether we need to patch the VBIOS connector info table with -+ * data from an external display connection info table. This is -+ * necessary to support MXM boards with an OPM (output personality -+ * module). With these designs, the VBIOS connector info table -+ * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves -+ * the external connection info table through i2c and then looks up the -+ * connector ID to find the real connector type (e.g. DFP1). -+ * -+ */ -+ -+static void process_ext_display_connection_info(struct bios_parser *bp) -+{ -+ ATOM_OBJECT_TABLE *connector_tbl; -+ uint32_t connector_tbl_offset; -+ struct graphics_object_id object_id; -+ ATOM_OBJECT *object; -+ bool mxm_connector_found = false; -+ bool null_entry_found = false; -+ uint32_t i = 0; -+ -+ connector_tbl_offset = bp->object_info_tbl_offset + -+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); -+ connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); -+ -+ /* Look for MXM connectors to determine whether we need patch the VBIOS -+ * connector info table. Look for null entries to determine whether we -+ * need to compact connector table. */ -+ for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { -+ object = &connector_tbl->asObjects[i]; -+ object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); -+ -+ if ((OBJECT_TYPE_CONNECTOR == object_id.type) && -+ (CONNECTOR_ID_MXM == object_id.id)) { -+ /* Once we found MXM connector - we can break */ -+ mxm_connector_found = true; -+ break; -+ } else if (OBJECT_TYPE_CONNECTOR != object_id.type) { -+ /* We need to continue looping - to check if MXM -+ * connector present */ -+ null_entry_found = true; -+ } -+ } -+ -+ /* Patch BIOS image */ -+ if (mxm_connector_found || null_entry_found) { -+ uint32_t connectors_num = 0; -+ uint8_t *original_bios; -+ /* Step 1: Replace bios image with the new copy which will be -+ * patched */ -+ bp->bios_local_image = dc_service_alloc(bp->ctx, bp->bios_size); -+ if (bp->bios_local_image == NULL) { -+ BREAK_TO_DEBUGGER(); -+ /* Failed to alloc bp->bios_local_image */ -+ return; -+ } -+ -+ dc_service_memmove(bp->bios_local_image, bp->bios, bp->bios_size); -+ original_bios = bp->bios; -+ bp->bios = bp->bios_local_image; -+ connector_tbl = -+ GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); -+ -+ /* Step 2: (only if MXM connector found) Patch BIOS image with -+ * info from external module */ -+ if (mxm_connector_found && -+ patch_bios_image_from_ext_display_connection_info(bp) != -+ BP_RESULT_OK) { -+ /* Patching the bios image has failed. We will copy -+ * again original image provided and afterwards -+ * only remove null entries */ -+ dc_service_memmove( -+ bp->bios_local_image, -+ original_bios, -+ bp->bios_size); -+ } -+ -+ /* Step 3: Compact connector table (remove null entries, valid -+ * entries moved to beginning) */ -+ for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { -+ object = &connector_tbl->asObjects[i]; -+ object_id = object_id_from_bios_object_id( -+ le16_to_cpu(object->usObjectID)); -+ -+ if (OBJECT_TYPE_CONNECTOR != object_id.type) -+ continue; -+ -+ if (i != connectors_num) { -+ dc_service_memmove( -+ &connector_tbl-> -+ asObjects[connectors_num], -+ object, -+ sizeof(ATOM_OBJECT)); -+ } -+ ++connectors_num; -+ } -+ connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num; -+ } -+} -+ -+void dal_bios_parser_post_init(struct bios_parser *bp) -+{ -+ process_ext_display_connection_info(bp); -+} -+ -+bool dal_bios_parser_is_accelerated_mode( -+ struct bios_parser *bp) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ return bp->bios_helper->is_accelerated_mode( -+ bp->ctx); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+ return false; -+#endif -+} -+ -+/** -+* dal_bios_parser_set_scratch_connected -+* -+* @brief -+* update VBIOS scratch register about connected displays -+* -+* @param -+* bool - update scratch register or just prepare info to be updated -+* bool - connection state -+* const ConnectorDeviceTagInfo* - pointer to device type and enum ID -+*/ -+void dal_bios_parser_set_scratch_connected( -+ struct bios_parser *bp, -+ struct graphics_object_id connector_id, -+ bool connected, -+ const struct connector_device_tag_info *device_tag) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ bp->bios_helper->set_scratch_connected( -+ bp->ctx, -+ connector_id, connected, device_tag); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+#endif -+} -+ -+/** -+* dal_bios_parser_set_scratch_critical_state -+* -+* @brief -+* update critical state bit in VBIOS scratch register -+* -+* @param -+* bool - to set or reset state -+*/ -+void dal_bios_parser_set_scratch_critical_state( -+ struct bios_parser *bp, -+ bool state) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ bp->bios_helper->set_scratch_critical_state( -+ bp->ctx, state); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+#endif -+} -+ -+void dal_bios_parser_set_scratch_acc_mode_change( -+ struct bios_parser *bp) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ bp->bios_helper->set_scratch_acc_mode_change( -+ bp->ctx); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+#endif -+} -+ -+/** -+* dal_bios_parser_prepare_scratch_active_and_requested -+* -+* @brief -+* update VBIOS scratch registers about active and requested displays -+* -+* @param -+* enum controller_id - controller Id -+* enum signal_type signal - signal type used on display -+* const struct connector_device_tag_info * - pointer to display type and -+* enum Id -+*/ -+void dal_bios_parser_prepare_scratch_active_and_requested( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ enum signal_type signal, -+ const struct connector_device_tag_info *device_tag) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ bp->bios_helper->prepare_scratch_active_and_requested( -+ bp->ctx, -+ &bp->vbios_helper_data, -+ controller_id, -+ signal, -+ device_tag); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+#endif -+} -+ -+void dal_bios_parser_set_scratch_active_and_requested( -+ struct bios_parser *bp) -+{ -+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT -+ bp->bios_helper->set_scratch_active_and_requested( -+ bp->ctx, -+ &bp->vbios_helper_data); -+#else -+ dal_logger_write(bp->ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_BIOS_CMD_TABLE, -+ "%s: VBIOS is not supported", __func__); -+#endif -+} -+ -+/* -+ * get_integrated_info_v8 -+ * -+ * @brief -+ * Get V8 integrated BIOS information -+ * -+ * @param -+ * bios_parser *bp - [in]BIOS parser handler to get master data table -+ * integrated_info *info - [out] store and output integrated info -+ * -+ * @return -+ * enum bp_result - BP_RESULT_OK if information is available, -+ * BP_RESULT_BADBIOSTABLE otherwise. -+ */ -+static enum bp_result get_integrated_info_v8( -+ struct bios_parser *bp, -+ struct integrated_info *info) -+{ -+ enum bp_result result = BP_RESULT_BADBIOSTABLE; -+ ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; -+ uint32_t i; -+ -+ info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, -+ bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); -+ -+ if (info_v8 != NULL) { -+ info->boot_up_engine_clock = -+ le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; -+ info->dentist_vco_freq = -+ le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; -+ info->boot_up_uma_clock = -+ le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; -+ -+ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { -+ /* Convert [10KHz] into [KHz] */ -+ info->disp_clk_voltage[i].max_supported_clk = -+ le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. -+ ulMaximumSupportedCLK) * 10; -+ info->disp_clk_voltage[i].voltage_index = -+ le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); -+ } -+ -+ info->boot_up_req_display_vector = -+ le32_to_cpu(info_v8->ulBootUpReqDisplayVector); -+ info->gpu_cap_info = -+ le32_to_cpu(info_v8->ulGPUCapInfo); -+ -+ /* -+ * system_config: Bit[0] = 0 : PCIE power gating disabled -+ * = 1 : PCIE power gating enabled -+ * Bit[1] = 0 : DDR-PLL shut down disabled -+ * = 1 : DDR-PLL shut down enabled -+ * Bit[2] = 0 : DDR-PLL power down disabled -+ * = 1 : DDR-PLL power down enabled -+ */ -+ info->system_config = le32_to_cpu(info_v8->ulSystemConfig); -+ info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); -+ info->boot_up_nb_voltage = -+ le16_to_cpu(info_v8->usBootUpNBVoltage); -+ info->ext_disp_conn_info_offset = -+ le16_to_cpu(info_v8->usExtDispConnInfoOffset); -+ info->memory_type = info_v8->ucMemoryType; -+ info->ma_channel_number = info_v8->ucUMAChannelNumber; -+ info->gmc_restore_reset_time = -+ le32_to_cpu(info_v8->ulGMCRestoreResetTime); -+ -+ info->minimum_n_clk = -+ le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); -+ for (i = 1; i < 4; ++i) -+ info->minimum_n_clk = -+ info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? -+ info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); -+ -+ info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); -+ info->ddr_dll_power_up_time = -+ le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); -+ info->ddr_pll_power_up_time = -+ le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); -+ info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); -+ info->lvds_ss_percentage = -+ le16_to_cpu(info_v8->usLvdsSSPercentage); -+ info->lvds_sspread_rate_in_10hz = -+ le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); -+ info->hdmi_ss_percentage = -+ le16_to_cpu(info_v8->usHDMISSPercentage); -+ info->hdmi_sspread_rate_in_10hz = -+ le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); -+ info->dvi_ss_percentage = -+ le16_to_cpu(info_v8->usDVISSPercentage); -+ info->dvi_sspread_rate_in_10_hz = -+ le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); -+ -+ info->max_lvds_pclk_freq_in_single_link = -+ le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); -+ info->lvds_misc = info_v8->ucLvdsMisc; -+ info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = -+ info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; -+ info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = -+ info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; -+ info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = -+ info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; -+ info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = -+ info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; -+ info->lvds_pwr_off_seq_de_to_dig_on_in4ms = -+ info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; -+ info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = -+ info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; -+ info->lvds_off_to_on_delay_in_4ms = -+ info_v8->ucLVDSOffToOnDelay_in4Ms; -+ info->lvds_bit_depth_control_val = -+ le32_to_cpu(info_v8->ulLCDBitDepthControlVal); -+ -+ for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { -+ /* Convert [10KHz] into [KHz] */ -+ info->avail_s_clk[i].supported_s_clk = -+ le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; -+ info->avail_s_clk[i].voltage_index = -+ le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); -+ info->avail_s_clk[i].voltage_id = -+ le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); -+ } -+ -+ for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { -+ info->ext_disp_conn_info.gu_id[i] = -+ info_v8->sExtDispConnInfo.ucGuid[i]; -+ } -+ -+ for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { -+ info->ext_disp_conn_info.path[i].device_connector_id = -+ object_id_from_bios_object_id( -+ le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); -+ -+ info->ext_disp_conn_info.path[i].ext_encoder_obj_id = -+ object_id_from_bios_object_id( -+ le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); -+ -+ info->ext_disp_conn_info.path[i].device_tag = -+ le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); -+ info->ext_disp_conn_info.path[i].device_acpi_enum = -+ le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); -+ info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = -+ info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; -+ info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = -+ info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; -+ info->ext_disp_conn_info.path[i].channel_mapping.raw = -+ info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; -+ } -+ info->ext_disp_conn_info.checksum = -+ info_v8->sExtDispConnInfo.ucChecksum; -+ -+ result = BP_RESULT_OK; -+ } -+ -+ return result; -+} -+ -+/* -+ * get_integrated_info_v8 -+ * -+ * @brief -+ * Get V8 integrated BIOS information -+ * -+ * @param -+ * bios_parser *bp - [in]BIOS parser handler to get master data table -+ * integrated_info *info - [out] store and output integrated info -+ * -+ * @return -+ * enum bp_result - BP_RESULT_OK if information is available, -+ * BP_RESULT_BADBIOSTABLE otherwise. -+ */ -+static enum bp_result get_integrated_info_v9( -+ struct bios_parser *bp, -+ struct integrated_info *info) -+{ -+ enum bp_result result = BP_RESULT_BADBIOSTABLE; -+ ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; -+ uint32_t i; -+ -+ info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, -+ bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); -+ -+ if (info_v9 != NULL) { -+ info->boot_up_engine_clock = -+ le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; -+ info->dentist_vco_freq = -+ le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; -+ info->boot_up_uma_clock = -+ le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; -+ -+ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { -+ /* Convert [10KHz] into [KHz] */ -+ info->disp_clk_voltage[i].max_supported_clk = -+ le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; -+ info->disp_clk_voltage[i].voltage_index = -+ le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); -+ } -+ -+ info->boot_up_req_display_vector = -+ le32_to_cpu(info_v9->ulBootUpReqDisplayVector); -+ info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); -+ -+ /* -+ * system_config: Bit[0] = 0 : PCIE power gating disabled -+ * = 1 : PCIE power gating enabled -+ * Bit[1] = 0 : DDR-PLL shut down disabled -+ * = 1 : DDR-PLL shut down enabled -+ * Bit[2] = 0 : DDR-PLL power down disabled -+ * = 1 : DDR-PLL power down enabled -+ */ -+ info->system_config = le32_to_cpu(info_v9->ulSystemConfig); -+ info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); -+ info->boot_up_nb_voltage = -+ le16_to_cpu(info_v9->usBootUpNBVoltage); -+ info->ext_disp_conn_info_offset = -+ le16_to_cpu(info_v9->usExtDispConnInfoOffset); -+ info->memory_type = info_v9->ucMemoryType; -+ info->ma_channel_number = info_v9->ucUMAChannelNumber; -+ info->gmc_restore_reset_time = -+ le32_to_cpu(info_v9->ulGMCRestoreResetTime); -+ -+ info->minimum_n_clk = -+ le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); -+ for (i = 1; i < 4; ++i) -+ info->minimum_n_clk = -+ info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? -+ info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); -+ -+ info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); -+ info->ddr_dll_power_up_time = -+ le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); -+ info->ddr_pll_power_up_time = -+ le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); -+ info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); -+ info->lvds_ss_percentage = -+ le16_to_cpu(info_v9->usLvdsSSPercentage); -+ info->lvds_sspread_rate_in_10hz = -+ le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); -+ info->hdmi_ss_percentage = -+ le16_to_cpu(info_v9->usHDMISSPercentage); -+ info->hdmi_sspread_rate_in_10hz = -+ le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); -+ info->dvi_ss_percentage = -+ le16_to_cpu(info_v9->usDVISSPercentage); -+ info->dvi_sspread_rate_in_10_hz = -+ le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); -+ -+ info->max_lvds_pclk_freq_in_single_link = -+ le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); -+ info->lvds_misc = info_v9->ucLvdsMisc; -+ info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = -+ info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; -+ info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = -+ info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; -+ info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = -+ info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; -+ info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = -+ info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; -+ info->lvds_pwr_off_seq_de_to_dig_on_in4ms = -+ info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; -+ info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = -+ info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; -+ info->lvds_off_to_on_delay_in_4ms = -+ info_v9->ucLVDSOffToOnDelay_in4Ms; -+ info->lvds_bit_depth_control_val = -+ le32_to_cpu(info_v9->ulLCDBitDepthControlVal); -+ -+ for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { -+ /* Convert [10KHz] into [KHz] */ -+ info->avail_s_clk[i].supported_s_clk = -+ le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; -+ info->avail_s_clk[i].voltage_index = -+ le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); -+ info->avail_s_clk[i].voltage_id = -+ le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); -+ } -+ -+ for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { -+ info->ext_disp_conn_info.gu_id[i] = -+ info_v9->sExtDispConnInfo.ucGuid[i]; -+ } -+ -+ for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { -+ info->ext_disp_conn_info.path[i].device_connector_id = -+ object_id_from_bios_object_id( -+ le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); -+ -+ info->ext_disp_conn_info.path[i].ext_encoder_obj_id = -+ object_id_from_bios_object_id( -+ le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); -+ -+ info->ext_disp_conn_info.path[i].device_tag = -+ le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); -+ info->ext_disp_conn_info.path[i].device_acpi_enum = -+ le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); -+ info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = -+ info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; -+ info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = -+ info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; -+ info->ext_disp_conn_info.path[i].channel_mapping.raw = -+ info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; -+ } -+ info->ext_disp_conn_info.checksum = -+ info_v9->sExtDispConnInfo.ucChecksum; -+ -+ result = BP_RESULT_OK; -+ } -+ -+ return result; -+} -+ -+/* -+ * construct_integrated_info -+ * -+ * @brief -+ * Get integrated BIOS information based on table revision -+ * -+ * @param -+ * bios_parser *bp - [in]BIOS parser handler to get master data table -+ * integrated_info *info - [out] store and output integrated info -+ * -+ * @return -+ * enum bp_result - BP_RESULT_OK if information is available, -+ * BP_RESULT_BADBIOSTABLE otherwise. -+ */ -+static enum bp_result construct_integrated_info( -+ struct bios_parser *bp, -+ struct integrated_info *info) -+{ -+ enum bp_result result = BP_RESULT_BADBIOSTABLE; -+ -+ ATOM_COMMON_TABLE_HEADER *header; -+ struct atom_data_revision revision; -+ -+ if (info != NULL && -+ bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { -+ header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, -+ bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); -+ -+ get_atom_data_table_revision(header, &revision); -+ -+ /* Don't need to check major revision as they are all 1 */ -+ switch (revision.minor) { -+ case 8: -+ result = get_integrated_info_v8(bp, info); -+ break; -+ case 9: -+ result = get_integrated_info_v9(bp, info); -+ break; -+ default: -+ return result; -+ -+ } -+ } -+ -+ /* Sort voltage table from low to high*/ -+ if (result == BP_RESULT_OK) { -+ struct clock_voltage_caps temp = {0, 0}; -+ uint32_t i; -+ uint32_t j; -+ -+ for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { -+ for (j = i; j > 0; --j) { -+ if ( -+ info->disp_clk_voltage[j].max_supported_clk < -+ info->disp_clk_voltage[j-1].max_supported_clk) { -+ /* swap j and j - 1*/ -+ temp = info->disp_clk_voltage[j-1]; -+ info->disp_clk_voltage[j-1] = -+ info->disp_clk_voltage[j]; -+ info->disp_clk_voltage[j] = temp; -+ } -+ } -+ } -+ -+ } -+ -+ return result; -+} -+ -+/* -+ * dal_bios_parser_create_integrated_info -+ * -+ * @brief -+ * Create integrated info -+ * -+ * @param -+ * bios_parser *bp - [in] BIOS parser handler -+ * -+ * @return -+ * struct integrated_info * - pointer to the newly created integrated info -+ */ -+struct integrated_info *dal_bios_parser_create_integrated_info( -+ struct bios_parser *bp) -+{ -+ struct integrated_info *info = NULL; -+ -+ info = dc_service_alloc(bp->ctx, sizeof(struct integrated_info)); -+ -+ if (info == NULL) { -+ ASSERT_CRITICAL(0); -+ return NULL; -+ } -+ -+ if (construct_integrated_info(bp, info) == BP_RESULT_OK) -+ return info; -+ -+ dc_service_free(bp->ctx, info); -+ -+ return NULL; -+} -+ -+/* -+ * dal_bios_parser_destroy_integrated_info -+ * -+ * @brief -+ * Destroy provided integrated info -+ * -+ * @param -+ * struct integrated_info **info - [in] info to be destroied -+ */ -+void dal_bios_parser_destroy_integrated_info(struct dc_context *ctx, struct integrated_info **info) -+{ -+ if (info == NULL) { -+ ASSERT_CRITICAL(0); -+ return; -+ } -+ -+ if (*info != NULL) { -+ dc_service_free(ctx, *info); -+ *info = NULL; -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h -new file mode 100644 -index 0000000..db169f1 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.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_BIOS_PARSER_H__ -+#define __DAL_BIOS_PARSER_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_context *ctx; -+ struct adapter_service *as; -+ -+ struct object_info_table object_info_tbl; -+ uint32_t object_info_tbl_offset; -+ ATOM_MASTER_DATA_TABLE *master_data_tbl; -+ -+ uint8_t *bios; -+ uint32_t bios_size; -+ -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ const struct bios_parser_helper *bios_helper; -+ struct vbios_helper_data vbios_helper_data; -+#endif /* CONFIG_DRM_AMD_DAL_VBIOS_PRESENT */ -+ -+ const struct command_table_helper *cmd_helper; -+ struct cmd_tbl cmd_tbl; -+ -+ uint8_t *bios_local_image; -+ enum lcd_scale lcd_scale; -+ -+ bool remap_device_tags; -+ bool headless_no_opm; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c -new file mode 100644 -index 0000000..0089800 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c -@@ -0,0 +1,193 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+#include "bios_parser_helper.h" -+#include "command_table_helper.h" -+#include "command_table.h" -+#include "bios_parser.h" -+ -+bool dal_bios_parser_init_bios_helper( -+ struct bios_parser *bp, -+ enum dce_version version) -+{ -+ switch (version) { -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ bp->bios_helper = dal_bios_parser_helper_dce110_get_table(); -+ return true; -+ -+#endif -+ default: -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+} -+ -+bool dal_bios_parser_is_lid_open( -+ struct bios_parser *bp) -+{ -+ const struct graphics_object_id encoder = dal_graphics_object_id_init( -+ ENCODER_ID_INTERNAL_UNIPHY, -+ ENUM_ID_UNKNOWN, -+ OBJECT_TYPE_UNKNOWN); -+ const struct graphics_object_id connector = dal_graphics_object_id_init( -+ CONNECTOR_ID_LVDS, -+ ENUM_ID_UNKNOWN, -+ OBJECT_TYPE_UNKNOWN); -+ -+ enum signal_type signal; -+ -+ /* check if VBIOS reported LCD as connected */ -+ signal = bp->bios_helper->detect_sink(bp->ctx, -+ encoder, connector, SIGNAL_TYPE_LVDS); -+ -+ if (signal == SIGNAL_TYPE_NONE) -+ return false; -+ -+ return bp->bios_helper->is_lid_open(bp->ctx); -+} -+ -+bool dal_bios_parser_is_lid_status_changed( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->is_lid_status_changed( -+ bp->ctx); -+} -+ -+bool dal_bios_parser_is_display_config_changed( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->is_display_config_changed( -+ bp->ctx); -+} -+ -+/** -+* dal_bios_parser_set_scratch_lcd_scale -+* -+* @brief -+* update VBIOS scratch pad registers about LCD scale -+* -+* @param -+* bool - to set to full panel mode or aspect-ratio mode -+*/ -+void dal_bios_parser_set_scratch_lcd_scale( -+ struct bios_parser *bp, -+ enum lcd_scale scale) -+{ -+ bp->bios_helper->set_scratch_lcd_scale( -+ bp->ctx, scale); -+} -+ -+/** -+* dal_bios_parser_get_scratch_lcd_scale -+* -+* @brief -+* get LCD Scale Mode from VBIOS scratch register -+* -+* @param -+* NONE -+*/ -+enum lcd_scale dal_bios_parser_get_scratch_lcd_scale( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->get_scratch_lcd_scale( -+ bp->ctx); -+} -+ -+void dal_bios_parser_get_bios_event_info( -+ struct bios_parser *bp, -+ struct bios_event_info *info) -+{ -+ bp->bios_helper->get_bios_event_info( -+ bp->ctx, info); -+} -+ -+/* ABM related */ -+ -+void dal_bios_parser_update_requested_backlight_level( -+ struct bios_parser *bp, -+ uint32_t backlight_8bit) -+{ -+ bp->bios_helper->update_requested_backlight_level( -+ bp->ctx, -+ backlight_8bit); -+} -+ -+uint32_t dal_bios_parser_get_requested_backlight_level( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->get_requested_backlight_level( -+ bp->ctx); -+} -+ -+void dal_bios_parser_take_backlight_control( -+ struct bios_parser *bp, -+ bool cntl) -+{ -+ bp->bios_helper->take_backlight_control( -+ bp->ctx, cntl); -+} -+ -+/** -+ * dal_bios_parser_is_active_display -+ * Check video bios active display. -+ */ -+bool dal_bios_parser_is_active_display( -+ struct bios_parser *bp, -+ enum signal_type signal, -+ const struct connector_device_tag_info *device_tag) -+{ -+ return bp->bios_helper->is_active_display( -+ bp->ctx, signal, device_tag); -+} -+ -+/** -+ * dal_bios_parser_get_embedded_display_controller_id -+ * Get controller ID for embedded display from scratch registers -+ */ -+enum controller_id dal_bios_parser_get_embedded_display_controller_id( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->get_embedded_display_controller_id( -+ bp->ctx); -+} -+ -+/** -+ * dal_bios_parser_get_embedded_display_refresh_rate -+ * Get refresh rate for embedded display from scratch registers -+ */ -+uint32_t dal_bios_parser_get_embedded_display_refresh_rate( -+ struct bios_parser *bp) -+{ -+ return bp->bios_helper->get_embedded_display_refresh_rate( -+ bp->ctx); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h -new file mode 100644 -index 0000000..d0e9de9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h -@@ -0,0 +1,108 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_BIOS_PARSER_HELPER_H__ -+#define __DAL_BIOS_PARSER_HELPER_H__ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/bios_parser_helper_dce110.h" -+#endif -+ -+struct bios_parser; -+ -+struct vbios_helper_data { -+ uint32_t active; -+ uint32_t requested; -+}; -+ -+struct bios_parser_helper { -+ enum signal_type (*detect_sink)( -+ struct dc_context *ctx, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type signal); -+ bool (*is_lid_open)( -+ struct dc_context *ctx); -+ bool (*is_lid_status_changed)( -+ struct dc_context *ctx); -+ bool (*is_display_config_changed)( -+ struct dc_context *ctx); -+ void (*set_scratch_acc_mode_change)( -+ struct dc_context *ctx); -+ bool (*is_accelerated_mode)( -+ struct dc_context *ctx); -+ void (*set_scratch_critical_state)( -+ struct dc_context *ctx, -+ bool state); -+ void (*prepare_scratch_active_and_requested)( -+ struct dc_context *ctx, -+ struct vbios_helper_data *data, -+ enum controller_id id, enum signal_type s, -+ const struct connector_device_tag_info *dev_tag); -+ void (*set_scratch_active_and_requested)( -+ struct dc_context *ctx, -+ struct vbios_helper_data *d); -+ void (*set_scratch_connected)( -+ struct dc_context *ctx, -+ struct graphics_object_id id, -+ bool connected, -+ const struct connector_device_tag_info *device_tag); -+ void (*set_scratch_lcd_scale)( -+ struct dc_context *ctx, -+ enum lcd_scale lcd_scale_request); -+ enum lcd_scale (*get_scratch_lcd_scale)( -+ struct dc_context *ctx); -+ uint32_t (*fmt_control)( -+ struct dc_context *ctx, -+ enum controller_id id, uint32_t *value); -+ uint32_t (*fmt_bit_depth_control)( -+ struct dc_context *ctx, -+ enum controller_id id, -+ uint32_t *value); -+ void (*get_bios_event_info)( -+ struct dc_context *ctx, -+ struct bios_event_info *info); -+ void (*take_backlight_control)( -+ struct dc_context *ctx, bool control); -+ uint32_t (*get_requested_backlight_level)( -+ struct dc_context *ctx); -+ void (*update_requested_backlight_level)( -+ struct dc_context *ctx, -+ uint32_t backlight_8bit); -+ bool (*is_active_display)( -+ struct dc_context *ctx, -+ enum signal_type signal, -+ const struct connector_device_tag_info *dev_tag); -+ enum controller_id (*get_embedded_display_controller_id)( -+ struct dc_context *ctx); -+ uint32_t (*get_embedded_display_refresh_rate)( -+ struct dc_context *ctx); -+}; -+ -+bool dal_bios_parser_init_bios_helper( -+ struct bios_parser *bp, -+ enum dce_version ver); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c -new file mode 100644 -index 0000000..a807ab6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c -@@ -0,0 +1,2616 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_interface.h" -+ -+#include "command_table.h" -+#include "command_table_helper.h" -+#include "bios_parser_helper.h" -+#include "bios_parser.h" -+ -+#define EXEC_BIOS_CMD_TABLE(command, params)\ -+ (cgs_atom_exec_cmd_table(bp->ctx->cgs_device, \ -+ GetIndexIntoMasterTable(COMMAND, command), \ -+ ¶ms) == 0) -+ -+#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\ -+ cgs_atom_get_cmd_table_revs(bp->ctx->cgs_device, \ -+ GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) -+ -+#define BIOS_CMD_TABLE_PARA_REVISION(command)\ -+ dal_bios_cmd_table_para_revision(bp->ctx, \ -+ GetIndexIntoMasterTable(COMMAND, command)) -+ -+ -+static void init_dig_encoder_control(struct bios_parser *bp); -+static void init_dvo_encoder_control(struct bios_parser *bp); -+static void init_transmitter_control(struct bios_parser *bp); -+static void init_set_pixel_clock(struct bios_parser *bp); -+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); -+static void init_adjust_display_pll(struct bios_parser *bp); -+static void init_dac_encoder_control(struct bios_parser *bp); -+static void init_dac_output_control(struct bios_parser *bp); -+static void init_dac_load_detection(struct bios_parser *bp); -+static void init_blank_crtc(struct bios_parser *bp); -+static void init_set_crtc_timing(struct bios_parser *bp); -+static void init_set_crtc_overscan(struct bios_parser *bp); -+static void init_select_crtc_source(struct bios_parser *bp); -+static void init_enable_crtc(struct bios_parser *bp); -+static void init_enable_crtc_mem_req(struct bios_parser *bp); -+static void init_compute_memore_engine_pll(struct bios_parser *bp); -+static void init_external_encoder_control(struct bios_parser *bp); -+static void init_enable_disp_power_gating(struct bios_parser *bp); -+static void init_program_clock(struct bios_parser *bp); -+ -+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) -+{ -+ init_dig_encoder_control(bp); -+ init_dvo_encoder_control(bp); -+ init_transmitter_control(bp); -+ init_set_pixel_clock(bp); -+ init_enable_spread_spectrum_on_ppll(bp); -+ init_adjust_display_pll(bp); -+ init_dac_encoder_control(bp); -+ init_dac_output_control(bp); -+ init_dac_load_detection(bp); -+ init_blank_crtc(bp); -+ init_set_crtc_timing(bp); -+ init_set_crtc_overscan(bp); -+ init_select_crtc_source(bp); -+ init_enable_crtc(bp); -+ init_enable_crtc_mem_req(bp); -+ init_program_clock(bp); -+ init_compute_memore_engine_pll(bp); -+ init_external_encoder_control(bp); -+ init_enable_disp_power_gating(bp); -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** D I G E N C O D E R C O N T R O L -+** -+******************************************************************************** -+*******************************************************************************/ -+static enum bp_result encoder_control_digx_v3( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+ -+static enum bp_result encoder_control_digx_v4( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+static void init_encoder_control_dig_v1(struct bios_parser *bp); -+ -+static void init_dig_encoder_control(struct bios_parser *bp) -+{ -+ uint32_t version = -+ BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); -+ -+ switch (version) { -+ case 4: -+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; -+ break; -+ case 2: -+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; -+ break; -+ default: -+ init_encoder_control_dig_v1(bp); -+ break; -+ } -+} -+ -+static enum bp_result encoder_control_dig_v1( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+static enum bp_result encoder_control_dig1_v1( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+static enum bp_result encoder_control_dig2_v1( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+ -+static void init_encoder_control_dig_v1(struct bios_parser *bp) -+{ -+ struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; -+ -+ if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl)) -+ cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1; -+ else -+ cmd_tbl->encoder_control_dig1 = NULL; -+ -+ if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl)) -+ cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1; -+ else -+ cmd_tbl->encoder_control_dig2 = NULL; -+ -+ cmd_tbl->dig_encoder_control = encoder_control_dig_v1; -+} -+ -+static enum bp_result encoder_control_dig_v1( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; -+ -+ if (cntl != NULL) -+ switch (cntl->engine_id) { -+ case ENGINE_ID_DIGA: -+ if (cmd_tbl->encoder_control_dig1 != NULL) -+ result = -+ cmd_tbl->encoder_control_dig1(bp, cntl); -+ break; -+ case ENGINE_ID_DIGB: -+ if (cmd_tbl->encoder_control_dig2 != NULL) -+ result = -+ cmd_tbl->encoder_control_dig2(bp, cntl); -+ break; -+ -+ default: -+ break; -+ } -+ -+ return result; -+} -+ -+static enum bp_result encoder_control_dig1_v1( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; -+ -+ bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); -+ -+ 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, ¶ms); -+ -+ if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result encoder_control_digx_v3( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; -+ -+ if (LANE_COUNT_FOUR < cntl->lanes_number) -+ params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ -+ else -+ params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ -+ -+ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); -+ -+ /* We need to convert from KHz units into 10KHz units */ -+ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); -+ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ params.ucEncoderMode = -+ (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( -+ cntl->signal, -+ cntl->enable_dp_audio); -+ params.ucLaneNum = (uint8_t)(cntl->lanes_number); -+ -+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24); -+ break; -+ case COLOR_DEPTH_121212: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24); -+ break; -+ case COLOR_DEPTH_161616: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24); -+ break; -+ default: -+ break; -+ } -+ -+ if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result encoder_control_digx_v4( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; -+ -+ if (LANE_COUNT_FOUR < cntl->lanes_number) -+ params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ -+ else -+ params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ -+ -+ -+ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); -+ -+ /* We need to convert from KHz units into 10KHz units */ -+ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); -+ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ params.ucEncoderMode = -+ (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( -+ cntl->signal, -+ cntl->enable_dp_audio)); -+ params.ucLaneNum = (uint8_t)(cntl->lanes_number); -+ -+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24); -+ break; -+ case COLOR_DEPTH_121212: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24); -+ break; -+ case COLOR_DEPTH_161616: -+ params.usPixelClock = -+ cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24); -+ break; -+ default: -+ break; -+ } -+ -+ if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** DVO ENCODER CONTROL -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result dvo_encoder_control_v3( -+ struct bios_parser *bp, -+ struct bp_dvo_encoder_control *cntl); -+ -+static void init_dvo_encoder_control(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(DVOEncoderControl)) { -+ case 3: -+ bp->cmd_tbl.dvo_encoder_control = dvo_encoder_control_v3; -+ break; -+ default: -+ bp->cmd_tbl.dvo_encoder_control = NULL; -+ break; -+ } -+} -+ -+static enum bp_result dvo_encoder_control_v3( -+ struct bios_parser *bp, -+ struct bp_dvo_encoder_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DVO_ENCODER_CONTROL_PARAMETERS_V3 params; -+ uint8_t config = 0; -+ -+ if (cntl->memory_rate == DVO_ENCODER_MEMORY_RATE_SDR) -+ config |= DVO_ENCODER_CONFIG_SDR_SPEED; -+ -+ switch (cntl->interface_width) { -+ case DVO_ENCODER_INTERFACE_WIDTH_FULL24BIT: -+ config |= DVO_ENCODER_CONFIG_24BIT; -+ break; -+ case DVO_ENCODER_INTERFACE_WIDTH_HIGH12BIT: -+ config |= DVO_ENCODER_CONFIG_UPPER12BIT; -+ break; -+ default: -+ config |= DVO_ENCODER_CONFIG_LOW12BIT; -+ break; -+ } -+ -+ /* We need to convert from KHz units into 10KHz units */ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ params.ucAction = (uint8_t) cntl->action; -+ params.usPixelClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10)); -+ params.ucDVOConfig = config; -+ -+ if (EXEC_BIOS_CMD_TABLE(DVOEncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** TRANSMITTER CONTROL -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result transmitter_control_v2( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl); -+static enum bp_result transmitter_control_v3( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl); -+static enum bp_result transmitter_control_v4( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl); -+static enum bp_result transmitter_control_v1_5( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl); -+ -+static 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; -+ 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); -+ -+ dc_service_memset(¶ms, 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); -+ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ -+ switch (cntl->transmitter) { -+ case TRANSMITTER_UNIPHY_A: -+ case TRANSMITTER_UNIPHY_B: -+ case TRANSMITTER_UNIPHY_C: -+ case TRANSMITTER_UNIPHY_D: -+ case TRANSMITTER_UNIPHY_E: -+ case TRANSMITTER_UNIPHY_F: -+ case TRANSMITTER_TRAVIS_LCD: -+ break; -+ default: -+ return BP_RESULT_BADINPUT; -+ } -+ -+ if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id)) -+ return BP_RESULT_BADINPUT; -+ -+ /* fill information based on the action */ -+ switch (cntl->action) { -+ case TRANSMITTER_CONTROL_INIT: -+ if (dual_link_conn) { -+ /* on INIT this bit should be set according to the -+ * phisycal connector -+ * Bit0: dual link connector flag -+ * =0 connector is single link connector -+ * =1 connector is dual link connector -+ */ -+ params.acConfig.fDualLinkConnector = 1; -+ } -+ -+ /* connector object id */ -+ params.usInitInfo = -+ cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); -+ break; -+ case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: -+ /* votage swing and pre-emphsis */ -+ params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; -+ params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; -+ break; -+ default: -+ if (dual_link_conn && cntl->multi_path) -+ /* on ENABLE/DISABLE this bit should be set according to -+ * actual timing (number of lanes) -+ * Bit0: dual link connector flag -+ * =0 connector is single link connector -+ * =1 connector is dual link connector -+ */ -+ params.acConfig.fDualLinkConnector = 1; -+ -+ /* if dual-link */ -+ if (LANE_COUNT_FOUR < cntl->lanes_number) { -+ /* on ENABLE/DISABLE this bit should be set according to -+ * actual timing (number of lanes) -+ * Bit0: dual link connector flag -+ * =0 connector is single link connector -+ * =1 connector is dual link connector -+ */ -+ params.acConfig.fDualLinkConnector = 1; -+ -+ /* link rate, half for dual link -+ * We need to convert from KHz units into 20KHz units -+ */ -+ params.usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); -+ } else { -+ /* link rate, half for dual link -+ * We need to convert from KHz units into 10KHz units -+ */ -+ params.usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24); -+ break; -+ case COLOR_DEPTH_121212: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24); -+ break; -+ case COLOR_DEPTH_161616: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24); -+ break; -+ default: -+ break; -+ } -+ } -+ break; -+ } -+ -+ /* 00 - coherent mode -+ * 01 - incoherent mode -+ */ -+ -+ params.acConfig.fCoherentMode = cntl->coherent; -+ -+ if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) -+ || (TRANSMITTER_UNIPHY_D == cntl->transmitter) -+ || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) -+ /* Bit2: Transmitter Link selection -+ * =0 when bit0=0, single link A/C/E, when bit0=1, -+ * master link A/C/E -+ * =1 when bit0=0, single link B/D/F, when bit0=1, -+ * master link B/D/F -+ */ -+ params.acConfig.ucLinkSel = 1; -+ -+ if (ENGINE_ID_DIGB == cntl->engine_id) -+ /* Bit3: Transmitter data source selection -+ * =0 DIGA is data source. -+ * =1 DIGB is data source. -+ * This bit is only useful when ucAction= ATOM_ENABLE -+ */ -+ params.acConfig.ucEncoderSel = 1; -+ -+ /* Bit[7:6]: Transmitter selection -+ * =0 UNIPHY_ENCODER: UNIPHYA/B -+ * =1 UNIPHY1_ENCODER: UNIPHYC/D -+ * =2 UNIPHY2_ENCODER: UNIPHYE/F -+ * =3 reserved -+ */ -+ params.acConfig.ucTransmitterSel = -+ (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter); -+ -+ params.ucLaneNum = (uint8_t)cntl->lanes_number; -+ -+ params.acConfig.ucRefClkSource = (uint8_t)pll_id; -+ -+ params.ucAction = (uint8_t)cntl->action; -+ -+ if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result transmitter_control_v4( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params; -+ uint32_t ref_clk_src_id; -+ enum connector_id conn_id = -+ dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); -+ const struct command_table_helper *cmd = bp->cmd_helper; -+ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ -+ switch (cntl->transmitter) { -+ case TRANSMITTER_UNIPHY_A: -+ case TRANSMITTER_UNIPHY_B: -+ case TRANSMITTER_UNIPHY_C: -+ case TRANSMITTER_UNIPHY_D: -+ case TRANSMITTER_UNIPHY_E: -+ case TRANSMITTER_UNIPHY_F: -+ case TRANSMITTER_TRAVIS_LCD: -+ break; -+ default: -+ return BP_RESULT_BADINPUT; -+ } -+ -+ if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id)) -+ return BP_RESULT_BADINPUT; -+ -+ switch (cntl->action) { -+ case TRANSMITTER_CONTROL_INIT: -+ { -+ if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || -+ (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) -+ /* on INIT this bit should be set according to the -+ * phisycal connector -+ * Bit0: dual link connector flag -+ * =0 connector is single link connector -+ * =1 connector is dual link connector -+ */ -+ params.acConfig.fDualLinkConnector = 1; -+ -+ /* connector object id */ -+ params.usInitInfo = -+ cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); -+ } -+ break; -+ case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: -+ /* votage swing and pre-emphsis */ -+ params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select); -+ params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings); -+ break; -+ default: -+ if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || -+ (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) -+ /* on ENABLE/DISABLE this bit should be set according to -+ * actual timing (number of lanes) -+ * Bit0: dual link connector flag -+ * =0 connector is single link connector -+ * =1 connector is dual link connector -+ */ -+ params.acConfig.fDualLinkConnector = 1; -+ -+ /* if dual-link */ -+ if (LANE_COUNT_FOUR < cntl->lanes_number) -+ /* link rate, half for dual link -+ * We need to convert from KHz units into 20KHz units -+ */ -+ params.usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); -+ else { -+ /* link rate, half for dual link -+ * We need to convert from KHz units into 10KHz units -+ */ -+ params.usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ -+ if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24); -+ break; -+ case COLOR_DEPTH_121212: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24); -+ break; -+ case COLOR_DEPTH_161616: -+ params.usPixelClock = -+ cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24); -+ break; -+ default: -+ break; -+ } -+ } -+ break; -+ } -+ -+ /* 00 - coherent mode -+ * 01 - incoherent mode -+ */ -+ -+ params.acConfig.fCoherentMode = cntl->coherent; -+ -+ if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) -+ || (TRANSMITTER_UNIPHY_D == cntl->transmitter) -+ || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) -+ /* Bit2: Transmitter Link selection -+ * =0 when bit0=0, single link A/C/E, when bit0=1, -+ * master link A/C/E -+ * =1 when bit0=0, single link B/D/F, when bit0=1, -+ * master link B/D/F -+ */ -+ params.acConfig.ucLinkSel = 1; -+ -+ if (ENGINE_ID_DIGB == cntl->engine_id) -+ /* Bit3: Transmitter data source selection -+ * =0 DIGA is data source. -+ * =1 DIGB is data source. -+ * This bit is only useful when ucAction= ATOM_ENABLE -+ */ -+ params.acConfig.ucEncoderSel = 1; -+ -+ /* Bit[7:6]: Transmitter selection -+ * =0 UNIPHY_ENCODER: UNIPHYA/B -+ * =1 UNIPHY1_ENCODER: UNIPHYC/D -+ * =2 UNIPHY2_ENCODER: UNIPHYE/F -+ * =3 reserved -+ */ -+ params.acConfig.ucTransmitterSel = -+ (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter)); -+ params.ucLaneNum = (uint8_t)(cntl->lanes_number); -+ params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id); -+ params.ucAction = (uint8_t)(cntl->action); -+ -+ if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result transmitter_control_v1_5( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ const struct command_table_helper *cmd = bp->cmd_helper; -+ DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params; -+ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter); -+ params.ucAction = (uint8_t)cntl->action; -+ params.ucLaneNum = (uint8_t)cntl->lanes_number; -+ params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id; -+ -+ params.ucDigMode = -+ cmd->signal_type_to_atom_dig_mode(cntl->signal); -+ params.asConfig.ucPhyClkSrcId = -+ cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id); -+ /* 00 - coherent mode */ -+ params.asConfig.ucCoherentMode = cntl->coherent; -+ params.asConfig.ucHPDSel = -+ cmd->hpd_sel_to_atom(cntl->hpd_sel); -+ params.ucDigEncoderSel = -+ cmd->dig_encoder_sel_to_atom(cntl->engine_id); -+ params.ucDPLaneSet = (uint8_t) cntl->lane_settings; -+ params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10)); -+ /* -+ * In SI/TN case, caller have to set usPixelClock as following: -+ * DP mode: usPixelClock = DP_LINK_CLOCK/10 -+ * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz) -+ * DVI single link mode: usPixelClock = pixel clock -+ * DVI dual link mode: usPixelClock = pixel clock -+ * HDMI mode: usPixelClock = pixel clock * deep_color_ratio -+ * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp) -+ * LVDS mode: usPixelClock = pixel clock -+ */ -+ switch (cntl->signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ switch (cntl->color_depth) { -+ case COLOR_DEPTH_101010: -+ params.usSymClock = -+ cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24); -+ break; -+ case COLOR_DEPTH_121212: -+ params.usSymClock = -+ cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24); -+ break; -+ case COLOR_DEPTH_161616: -+ params.usSymClock = -+ cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24); -+ break; -+ default: -+ break; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** 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 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; -+ 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; -+ -+ dc_service_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; -+ -+ dc_service_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; -+ -+ dc_service_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; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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 bool adjust_display_pll_bug_patch(ADJUST_DISPLAY_PLL_PARAMETERS *params) -+{ -+ /* vbios bug: pixel clock should not be doubled for DVO with 24bit -+ * interface */ -+ if ((params->ucTransmitterID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) -+ && (params->ucDVOConfig == DVO_ENCODER_CONFIG_24BIT)) -+ /* the current pixel clock is good. no adjustment is required */ -+ return true; -+ return false; -+} -+ -+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); -+ params.ucDVOConfig = (uint8_t)(bp_params->dvo_config); -+ -+ if (adjust_display_pll_bug_patch(¶ms) -+ || 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_clock_10KHz_out = -+ le16_to_cpu((uint64_t)params.usPixelClock); -+ uint64_t pixel_clock = (uint64_t)bp_params->pixel_clock; -+ -+ bp_params->adjusted_pixel_clock = -+ div_u64(pixel_clock * pixel_clock_10KHz_out, -+ pixel_clock_10KHz_in); -+ result = BP_RESULT_OK; -+ } -+ -+ 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; -+ -+ dc_service_memset(¶ms, 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 (DISP_PLL_CONFIG_DVO_DDR_MODE_LOW_12BIT == -+ bp_params->display_pll_config) -+ params.sInput.ucDispPllConfig = -+ DISPPLL_CONFIG_DVO_DDR_SPEED | -+ DISPPLL_CONFIG_DVO_LOW12BIT; -+ else if (DISP_PLL_CONFIG_DVO_DDR_MODE_UPPER_12BIT == -+ bp_params->display_pll_config) -+ params.sInput.ucDispPllConfig = -+ DISPPLL_CONFIG_DVO_DDR_SPEED | -+ DISPPLL_CONFIG_DVO_UPPER12BIT; -+ else if (DISP_PLL_CONFIG_DVO_DDR_MODE_24BIT == -+ bp_params->display_pll_config) -+ params.sInput.ucDispPllConfig = -+ DISPPLL_CONFIG_DVO_DDR_SPEED | DISPPLL_CONFIG_DVO_24BIT; -+ else -+ /* this does not mean anything here */ -+ params.sInput.ucDispPllConfig = -+ (uint8_t)(bp_params->display_pll_config); -+ -+ 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( -+ ¶ms, -+ 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( -+ ¶ms, -+ enable, -+ pixel_clock, -+ dac_standard); -+ -+ if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** DAC OUTPUT CONTROL -+** -+******************************************************************************** -+*******************************************************************************/ -+static enum bp_result dac1_output_control_v1( -+ struct bios_parser *bp, -+ bool enable); -+static enum bp_result dac2_output_control_v1( -+ struct bios_parser *bp, -+ bool enable); -+ -+static void init_dac_output_control(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) { -+ case 1: -+ bp->cmd_tbl.dac1_output_control = dac1_output_control_v1; -+ break; -+ default: -+ bp->cmd_tbl.dac1_output_control = NULL; -+ break; -+ } -+ switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) { -+ case 1: -+ bp->cmd_tbl.dac2_output_control = dac2_output_control_v1; -+ break; -+ default: -+ bp->cmd_tbl.dac2_output_control = NULL; -+ break; -+ } -+} -+ -+static enum bp_result dac1_output_control_v1( -+ struct bios_parser *bp, bool enable) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; -+ -+ if (enable) -+ params.ucAction = ATOM_ENABLE; -+ else -+ params.ucAction = ATOM_DISABLE; -+ -+ if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result dac2_output_control_v1( -+ struct bios_parser *bp, bool enable) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; -+ -+ if (enable) -+ params.ucAction = ATOM_ENABLE; -+ else -+ params.ucAction = ATOM_DISABLE; -+ -+ if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** DAC LOAD DETECTION -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum signal_type dac_load_detection_v3( -+ struct bios_parser *bp, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type display_signal); -+ -+static void init_dac_load_detection(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) { -+ case 3: -+ bp->cmd_tbl.dac_load_detection = dac_load_detection_v3; -+ break; -+ default: -+ bp->cmd_tbl.dac_load_detection = NULL; -+ break; -+ } -+} -+ -+static enum signal_type dac_load_detection_v3( -+ struct bios_parser *bp, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type display_signal) -+{ -+ DAC_LOAD_DETECTION_PS_ALLOCATION params; -+ enum signal_type signal = SIGNAL_TYPE_NONE; -+ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ -+ /* load detection is cupported for CRT, TV and CV */ -+ switch (display_signal) { -+ case SIGNAL_TYPE_RGB: -+ switch (dal_graphics_object_id_get_encoder_id(encoder)) { -+ case ENCODER_ID_INTERNAL_DAC1: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC1: -+ params.sDacload.usDeviceID = -+ cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); -+ break; -+ case ENCODER_ID_INTERNAL_DAC2: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC2: -+ params.sDacload.usDeviceID = -+ cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); -+ break; -+ default: -+ break; -+ } -+ break; -+ default: -+ return signal; -+ } -+ -+ /* set the encoder to detect on */ -+ switch (dal_graphics_object_id_get_encoder_id(encoder)) { -+ case ENCODER_ID_INTERNAL_DAC1: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC1: -+ params.sDacload.ucDacType = ATOM_DAC_A; -+ break; -+ case ENCODER_ID_INTERNAL_DAC2: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC2: -+ params.sDacload.ucDacType = ATOM_DAC_B; -+ break; -+ case ENCODER_ID_EXTERNAL_CH7303: -+ params.sDacload.ucDacType = ATOM_EXT_DAC; -+ break; -+ default: -+ return signal; -+ } -+ -+ if (!EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params)) -+ return signal; -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ signal = bp->bios_helper->detect_sink( -+ bp->ctx, -+ encoder, -+ connector, -+ display_signal); -+#else -+ BREAK_TO_DEBUGGER(); /* VBios is needed */ -+#endif -+ -+ return signal; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** BLANK CRTC -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result blank_crtc_v1( -+ struct bios_parser *bp, -+ struct bp_blank_crtc_parameters *bp_params, -+ bool blank); -+ -+static void init_blank_crtc(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) { -+ case 1: -+ bp->cmd_tbl.blank_crtc = blank_crtc_v1; -+ break; -+ default: -+ bp->cmd_tbl.blank_crtc = NULL; -+ break; -+ } -+} -+ -+static enum bp_result blank_crtc_v1( -+ struct bios_parser *bp, -+ struct bp_blank_crtc_parameters *bp_params, -+ bool blank) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ BLANK_CRTC_PARAMETERS params = {0}; -+ uint8_t atom_controller_id; -+ -+ if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, -+ &atom_controller_id)) { -+ params.ucCRTC = (uint8_t)atom_controller_id; -+ -+ if (blank) -+ params.ucBlanking = ATOM_BLANKING; -+ else -+ params.ucBlanking = ATOM_BLANKING_OFF; -+ params.usBlackColorRCr = -+ cpu_to_le16((uint16_t)bp_params->black_color_rcr); -+ params.usBlackColorGY = -+ cpu_to_le16((uint16_t)bp_params->black_color_gy); -+ params.usBlackColorBCb = -+ cpu_to_le16((uint16_t)bp_params->black_color_bcb); -+ -+ if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params)) -+ result = BP_RESULT_OK; -+ } else -+ /* Not support more than two CRTC as current ASIC, update this -+ * if needed. -+ */ -+ result = BP_RESULT_BADINPUT; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** SET CRTC TIMING -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result set_crtc_using_dtd_timing_v3( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params); -+static enum bp_result set_crtc_timing_v1( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params); -+ -+static void init_set_crtc_timing(struct bios_parser *bp) -+{ -+ uint32_t dtd_version = -+ BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming); -+ if (dtd_version > 2) -+ switch (dtd_version) { -+ case 3: -+ bp->cmd_tbl.set_crtc_timing = -+ set_crtc_using_dtd_timing_v3; -+ break; -+ default: -+ bp->cmd_tbl.set_crtc_timing = NULL; -+ break; -+ } -+ else -+ switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) { -+ case 1: -+ bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1; -+ break; -+ default: -+ bp->cmd_tbl.set_crtc_timing = NULL; -+ break; -+ } -+} -+ -+static enum bp_result set_crtc_timing_v1( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0}; -+ uint8_t atom_controller_id; -+ -+ if (bp->cmd_helper->controller_id_to_atom( -+ bp_params->controller_id, &atom_controller_id)) -+ params.ucCRTC = atom_controller_id; -+ -+ params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total)); -+ params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable)); -+ params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start)); -+ params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width)); -+ params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total)); -+ params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable)); -+ params.usV_SyncStart = -+ cpu_to_le16((uint16_t)(bp_params->v_sync_start)); -+ params.usV_SyncWidth = -+ cpu_to_le16((uint16_t)(bp_params->v_sync_width)); -+ -+ -+ /* VBIOS does not expect any value except zero into this call, for -+ * underscan use another entry ProgramOverscan call but when mode -+ * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok, -+ * but when same ,but 60 Hz there is corruption -+ * DAL1 does not allow the mode 1776x1000@60 -+ */ -+ params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right; -+ params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left; -+ params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom; -+ params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top; -+ -+ if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); -+ -+ if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); -+ -+ if (bp_params->flags.INTERLACE) { -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); -+ -+ /* original DAL code has this condition to apply tis for -+ * non-TV/CV only due to complex MV testing for possible -+ * impact -+ * if (pACParameters->signal != SignalType_YPbPr && -+ * pACParameters->signal != SignalType_Composite && -+ * pACParameters->signal != SignalType_SVideo) -+ */ -+ /* HW will deduct 0.5 line from 2nd feild. -+ * i.e. for 1080i, it is 2 lines for 1st field, 2.5 -+ * lines for the 2nd feild. we need input as 5 instead -+ * of 4, but it is 4 either from Edid data -+ * (spec CEA 861) or CEA timing table. -+ */ -+ params.usV_SyncStart = -+ cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1)); -+ } -+ -+ if (bp_params->flags.HORZ_COUNT_BY_TWO) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); -+ -+ if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+static enum bp_result set_crtc_using_dtd_timing_v3( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0}; -+ uint8_t atom_controller_id; -+ -+ if (bp->cmd_helper->controller_id_to_atom( -+ bp_params->controller_id, &atom_controller_id)) -+ params.ucCRTC = atom_controller_id; -+ -+ /* bios usH_Size wants h addressable size */ -+ params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable); -+ /* bios usH_Blanking_Time wants borders included in blanking */ -+ params.usH_Blanking_Time = -+ cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable)); -+ /* bios usV_Size wants v addressable size */ -+ params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable); -+ /* bios usV_Blanking_Time wants borders included in blanking */ -+ params.usV_Blanking_Time = -+ cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable)); -+ /* bios usHSyncOffset is the offset from the end of h addressable, -+ * our horizontalSyncStart is the offset from the beginning -+ * of h addressable */ -+ params.usH_SyncOffset = -+ cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable)); -+ params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); -+ /* bios usHSyncOffset is the offset from the end of v addressable, -+ * our verticalSyncStart is the offset from the beginning of -+ * v addressable */ -+ params.usV_SyncOffset = -+ cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable)); -+ params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); -+ -+ /* we assume that overscan from original timing does not get bigger -+ * than 255 -+ * we will program all the borders in the Set CRTC Overscan call below -+ */ -+ -+ if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); -+ -+ if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); -+ -+ -+ if (bp_params->flags.INTERLACE) { -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); -+ -+ /* original DAL code has this condition to apply this -+ * for non-TV/CV only -+ * due to complex MV testing for possible impact -+ * if ( pACParameters->signal != SignalType_YPbPr && -+ * pACParameters->signal != SignalType_Composite && -+ * pACParameters->signal != SignalType_SVideo) -+ */ -+ { -+ /* HW will deduct 0.5 line from 2nd feild. -+ * i.e. for 1080i, it is 2 lines for 1st field, -+ * 2.5 lines for the 2nd feild. we need input as 5 -+ * instead of 4. -+ * but it is 4 either from Edid data (spec CEA 861) -+ * or CEA timing table. -+ */ -+ params.usV_SyncOffset = -+ cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1); -+ -+ } -+ } -+ -+ if (bp_params->flags.HORZ_COUNT_BY_TWO) -+ params.susModeMiscInfo.usAccess = -+ cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); -+ -+ if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** SET CRTC OVERSCAN -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result set_crtc_overscan_v1( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_overscan_parameters *bp_params); -+ -+static void init_set_crtc_overscan(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan)) { -+ case 1: -+ bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1; -+ break; -+ default: -+ bp->cmd_tbl.set_crtc_overscan = NULL; -+ break; -+ } -+} -+ -+static enum bp_result set_crtc_overscan_v1( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_overscan_parameters *bp_params) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ SET_CRTC_OVERSCAN_PARAMETERS params = {0}; -+ uint8_t atom_controller_id; -+ -+ if (bp->cmd_helper->controller_id_to_atom( -+ bp_params->controller_id, &atom_controller_id)) -+ params.ucCRTC = atom_controller_id; -+ else -+ return BP_RESULT_BADINPUT; -+ -+ params.usOverscanRight = -+ cpu_to_le16((uint16_t)bp_params->h_overscan_right); -+ params.usOverscanLeft = -+ cpu_to_le16((uint16_t)bp_params->h_overscan_left); -+ params.usOverscanBottom = -+ cpu_to_le16((uint16_t)bp_params->v_overscan_bottom); -+ params.usOverscanTop = -+ cpu_to_le16((uint16_t)bp_params->v_overscan_top); -+ -+ if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** SELECT CRTC SOURCE -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result select_crtc_source_v2( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params); -+static enum bp_result select_crtc_source_v3( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params); -+ -+static void init_select_crtc_source(struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) { -+ case 2: -+ bp->cmd_tbl.select_crtc_source = select_crtc_source_v2; -+ break; -+ case 3: -+ bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; -+ break; -+ default: -+ bp->cmd_tbl.select_crtc_source = NULL; -+ break; -+ } -+} -+ -+static enum bp_result select_crtc_source_v2( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ SELECT_CRTC_SOURCE_PARAMETERS_V2 params; -+ uint8_t atom_controller_id; -+ uint32_t atom_engine_id; -+ enum signal_type s = bp_params->signal; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 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; -+ -+ dc_service_memset(¶ms, 0, sizeof(params)); -+ -+ cntl_params = ¶ms.sExtEncoder; -+ -+ encoder = cntl->encoder_id; -+ -+ /* check if encoder supports external encoder control table */ -+ switch (dal_graphics_object_id_get_encoder_id(encoder)) { -+ case ENCODER_ID_EXTERNAL_NUTMEG: -+ case ENCODER_ID_EXTERNAL_TRAVIS: -+ is_input_signal_dp = true; -+ break; -+ -+ default: -+ BREAK_TO_DEBUGGER(); -+ return BP_RESULT_BADINPUT; -+ } -+ -+ /* Fill information based on the action -+ * -+ * Bit[6:4]: indicate external encoder, applied to all functions. -+ * =0: external encoder1, mapped to external encoder enum id1 -+ * =1: external encoder2, mapped to external encoder enum id2 -+ * -+ * enum ObjectEnumId -+ * { -+ * EnumId_Unknown = 0, -+ * EnumId_1, -+ * EnumId_2, -+ * }; -+ */ -+ cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4); -+ -+ switch (cntl->action) { -+ case EXTERNAL_ENCODER_CONTROL_INIT: -+ /* output display connector type. Only valid in encoder -+ * initialization */ -+ cntl_params->usConnectorId = -+ cpu_to_le16((uint16_t)cntl->connector_obj_id.id); -+ break; -+ case EXTERNAL_ENCODER_CONTROL_SETUP: -+ /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in -+ * 10KHz -+ * output display device pixel clock frequency in unit of 10KHz. -+ * Only valid in setup and enableoutput -+ */ -+ cntl_params->usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ /* Indicate display output signal type drive by external -+ * encoder, only valid in setup and enableoutput */ -+ cntl_params->ucEncoderMode = -+ (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( -+ cntl->signal, false); -+ -+ if (is_input_signal_dp) { -+ /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, -+ * only valid in encoder setup with DP mode. */ -+ if (LINK_RATE_HIGH == cntl->link_rate) -+ cntl_params->ucConfig |= 1; -+ /* output color depth Indicate encoder data bpc format -+ * in DP mode, only valid in encoder setup in DP mode. -+ */ -+ cntl_params->ucBitPerColor = -+ (uint8_t)(cntl->color_depth); -+ } -+ /* Indicate how many lanes used by external encoder, only valid -+ * in encoder setup and enableoutput. */ -+ cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); -+ break; -+ case EXTERNAL_ENCODER_CONTROL_ENABLE: -+ cntl_params->usPixelClock = -+ cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); -+ cntl_params->ucEncoderMode = -+ (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( -+ cntl->signal, false); -+ cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; -+ break; -+ default: -+ break; -+ } -+ -+ cntl_params->ucAction = (uint8_t)cntl->action; -+ -+ if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params)) -+ result = BP_RESULT_OK; -+ -+ if (EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT == cntl->action) { -+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT) -+ if (BP_RESULT_OK == result) -+ /* get VBIOS result from scratch register. -+ * ExternalEncoderControl runs detection and save result -+ * in BIOS scratch registers. */ -+ cntl->signal = bp->bios_helper->detect_sink( -+ bp->ctx, -+ encoder, -+ cntl->connector_obj_id, -+ cntl->signal); -+ else/* BIOS table does not work. */ -+#endif -+ { -+ BREAK_TO_DEBUGGER(); /* VBios is needed */ -+ cntl->signal = SIGNAL_TYPE_NONE; -+ } -+ } -+ -+ return result; -+} -+ -+/******************************************************************************* -+******************************************************************************** -+** -+** ENABLE DISPLAY POWER GATING -+** -+******************************************************************************** -+*******************************************************************************/ -+ -+static enum bp_result enable_disp_power_gating_v2_1( -+ struct bios_parser *bp, -+ enum controller_id crtc_id, -+ enum bp_pipe_control_action action); -+ -+static void init_enable_disp_power_gating( -+ struct bios_parser *bp) -+{ -+ switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) { -+ case 1: -+ bp->cmd_tbl.enable_disp_power_gating = -+ enable_disp_power_gating_v2_1; -+ break; -+ default: -+ bp->cmd_tbl.enable_disp_power_gating = NULL; -+ break; -+ } -+} -+ -+static enum bp_result enable_disp_power_gating_v2_1( -+ struct bios_parser *bp, -+ enum controller_id crtc_id, -+ enum bp_pipe_control_action action) -+{ -+ enum bp_result result = BP_RESULT_FAILURE; -+ -+ ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 params = {0}; -+ uint8_t atom_crtc_id; -+ -+ if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) -+ params.ucDispPipeId = atom_crtc_id; -+ else -+ return BP_RESULT_BADINPUT; -+ -+ params.ucEnable = -+ bp->cmd_helper->disp_power_gating_action_to_atom(action); -+ -+ if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params)) -+ result = BP_RESULT_OK; -+ -+ return result; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h -new file mode 100644 -index 0000000..814d31f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h -@@ -0,0 +1,117 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_COMMAND_TABLE_H__ -+#define __DAL_COMMAND_TABLE_H__ -+ -+struct bios_parser; -+struct bp_encoder_control; -+ -+struct cmd_tbl { -+ enum bp_result (*dig_encoder_control)( -+ struct bios_parser *bp, -+ struct bp_encoder_control *control); -+ enum bp_result (*encoder_control_dig1)( -+ struct bios_parser *bp, -+ struct bp_encoder_control *control); -+ enum bp_result (*encoder_control_dig2)( -+ struct bios_parser *bp, -+ struct bp_encoder_control *control); -+ enum bp_result (*dvo_encoder_control)( -+ struct bios_parser *bp, -+ struct bp_dvo_encoder_control *cntl); -+ enum bp_result (*transmitter_control)( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *control); -+ enum bp_result (*set_pixel_clock)( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params); -+ enum bp_result (*enable_spread_spectrum_on_ppll)( -+ struct bios_parser *bp, -+ struct bp_spread_spectrum_parameters *bp_params, -+ bool enable); -+ enum bp_result (*adjust_display_pll)( -+ struct bios_parser *bp, -+ struct bp_adjust_pixel_clock_parameters *bp_params); -+ enum bp_result (*dac1_encoder_control)( -+ struct bios_parser *bp, -+ bool enable, -+ uint32_t pixel_clock, -+ uint8_t dac_standard); -+ enum bp_result (*dac2_encoder_control)( -+ struct bios_parser *bp, -+ bool enable, -+ uint32_t pixel_clock, -+ uint8_t dac_standard); -+ enum bp_result (*dac1_output_control)( -+ struct bios_parser *bp, -+ bool enable); -+ enum bp_result (*dac2_output_control)( -+ struct bios_parser *bp, -+ bool enable); -+ enum signal_type (*dac_load_detection)( -+ struct bios_parser *bp, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type display_signal); -+ enum bp_result (*blank_crtc)( -+ struct bios_parser *bp, -+ struct bp_blank_crtc_parameters *bp_params, -+ bool blank); -+ enum bp_result (*set_crtc_timing)( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params); -+ enum bp_result (*set_crtc_overscan)( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_overscan_parameters *bp_params); -+ enum bp_result (*select_crtc_source)( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params); -+ enum bp_result (*enable_crtc)( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ bool enable); -+ enum bp_result (*enable_crtc_mem_req)( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ bool enable); -+ enum bp_result (*program_clock)( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params); -+ enum bp_result (*compute_memore_engine_pll)( -+ struct bios_parser *bp, -+ struct bp_display_clock_parameters *bp_params); -+ enum bp_result (*external_encoder_control)( -+ struct bios_parser *bp, -+ struct bp_external_encoder_control *cntl); -+ enum bp_result (*enable_disp_power_gating)( -+ struct bios_parser *bp, -+ enum controller_id crtc_id, -+ enum bp_pipe_control_action action); -+}; -+ -+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c -new file mode 100644 -index 0000000..dad1426 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c -@@ -0,0 +1,315 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+ -+#include "command_table_helper.h" -+ -+bool dal_bios_parser_init_cmd_tbl_helper( -+ const struct command_table_helper **h, -+ enum dce_version dce) -+{ -+ switch (dce) { -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ *h = dal_cmd_tbl_helper_dce110_get_table(); -+ return true; -+ -+#endif -+ default: -+ /* Unsupported DCE */ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+} -+ -+/* real implementations */ -+ -+bool dal_cmd_table_helper_controller_id_to_atom( -+ enum controller_id id, -+ uint8_t *atom_id) -+{ -+ if (atom_id == NULL) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ switch (id) { -+ case CONTROLLER_ID_D0: -+ *atom_id = ATOM_CRTC1; -+ return true; -+ case CONTROLLER_ID_D1: -+ *atom_id = ATOM_CRTC2; -+ return true; -+ case CONTROLLER_ID_D2: -+ *atom_id = ATOM_CRTC3; -+ return true; -+ case CONTROLLER_ID_D3: -+ *atom_id = ATOM_CRTC4; -+ return true; -+ case CONTROLLER_ID_D4: -+ *atom_id = ATOM_CRTC5; -+ return true; -+ case CONTROLLER_ID_D5: -+ *atom_id = ATOM_CRTC6; -+ return true; -+ case CONTROLLER_ID_UNDERLAY0: -+ *atom_id = ATOM_UNDERLAY_PIPE0; -+ return true; -+ case CONTROLLER_ID_UNDEFINED: -+ *atom_id = ATOM_CRTC_INVALID; -+ return true; -+ default: -+ /* Wrong controller id */ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+} -+ -+/** -+* translate_transmitter_bp_to_atom -+* -+* @brief -+* Translate the Transmitter to the corresponding ATOM BIOS value -+* -+* @param -+* input transmitter -+* output digitalTransmitter -+* // =00: Digital Transmitter1 ( UNIPHY linkAB ) -+* // =01: Digital Transmitter2 ( UNIPHY linkCD ) -+* // =02: Digital Transmitter3 ( UNIPHY linkEF ) -+*/ -+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( -+ enum transmitter t) -+{ -+ switch (t) { -+ case TRANSMITTER_UNIPHY_A: -+ case TRANSMITTER_UNIPHY_B: -+ case TRANSMITTER_TRAVIS_LCD: -+ return 0; -+ case TRANSMITTER_UNIPHY_C: -+ case TRANSMITTER_UNIPHY_D: -+ return 1; -+ case TRANSMITTER_UNIPHY_E: -+ case TRANSMITTER_UNIPHY_F: -+ return 2; -+ default: -+ /* Invalid Transmitter Type! */ -+ BREAK_TO_DEBUGGER(); -+ return 0; -+ } -+} -+ -+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( -+ enum signal_type s, -+ bool enable_dp_audio) -+{ -+ switch (s) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ return ATOM_ENCODER_MODE_DVI; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ return ATOM_ENCODER_MODE_HDMI; -+ case SIGNAL_TYPE_LVDS: -+ return ATOM_ENCODER_MODE_LVDS; -+ case SIGNAL_TYPE_EDP: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ if (enable_dp_audio) -+ return ATOM_ENCODER_MODE_DP_AUDIO; -+ else -+ return ATOM_ENCODER_MODE_DP; -+ case SIGNAL_TYPE_RGB: -+ return ATOM_ENCODER_MODE_CRT; -+ default: -+ return ATOM_ENCODER_MODE_CRT; -+ } -+} -+ -+void dal_cmd_table_helper_assign_control_parameter( -+ const struct command_table_helper *h, -+ struct bp_encoder_control *control, -+ DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param) -+{ -+ /* there are three transmitter blocks, each one has two links 4-lanes -+ * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in -+ * each transmitter block B, D and F as link 1, third transmitter block -+ * has non splitable links (UniphyE and UniphyF can not be configured -+ * separately to drive two different streams) -+ */ -+ if ((control->transmitter == TRANSMITTER_UNIPHY_B) || -+ (control->transmitter == TRANSMITTER_UNIPHY_D) || -+ (control->transmitter == TRANSMITTER_UNIPHY_F)) { -+ /* Bit2: Link Select -+ * =0: PHY linkA/C/E -+ * =1: PHY linkB/D/F -+ */ -+ ctrl_param->acConfig.ucLinkSel = 1; -+ } -+ -+ /* Bit[4:3]: Transmitter Selection -+ * =00: Digital Transmitter1 ( UNIPHY linkAB ) -+ * =01: Digital Transmitter2 ( UNIPHY linkCD ) -+ * =02: Digital Transmitter3 ( UNIPHY linkEF ) -+ * =03: Reserved -+ */ -+ ctrl_param->acConfig.ucTransmitterSel = -+ (uint8_t)(h->transmitter_bp_to_atom(control->transmitter)); -+ -+ /* We need to convert from KHz units into 10KHz units */ -+ ctrl_param->ucAction = h->encoder_action_to_atom(control->action); -+ ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10)); -+ ctrl_param->ucEncoderMode = -+ (uint8_t)(h->encoder_mode_bp_to_atom( -+ control->signal, control->enable_dp_audio)); -+ ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number); -+} -+ -+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( -+ enum clock_source_id id, -+ uint32_t *ref_clk_src_id) -+{ -+ if (ref_clk_src_id == NULL) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ switch (id) { -+ case CLOCK_SOURCE_ID_PLL1: -+ *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; -+ return true; -+ case CLOCK_SOURCE_ID_PLL2: -+ *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; -+ return true; -+ case CLOCK_SOURCE_ID_DCPLL: -+ *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; -+ return true; -+ case CLOCK_SOURCE_ID_EXTERNAL: -+ *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; -+ return true; -+ case CLOCK_SOURCE_ID_UNDEFINED: -+ *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; -+ return true; -+ default: -+ /* Unsupported clock source id */ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+} -+ -+uint8_t dal_cmd_table_helper_encoder_id_to_atom( -+ enum encoder_id id) -+{ -+ switch (id) { -+ case ENCODER_ID_INTERNAL_LVDS: -+ return ENCODER_OBJECT_ID_INTERNAL_LVDS; -+ case ENCODER_ID_INTERNAL_TMDS1: -+ return ENCODER_OBJECT_ID_INTERNAL_TMDS1; -+ case ENCODER_ID_INTERNAL_TMDS2: -+ return ENCODER_OBJECT_ID_INTERNAL_TMDS2; -+ case ENCODER_ID_INTERNAL_DAC1: -+ return ENCODER_OBJECT_ID_INTERNAL_DAC1; -+ case ENCODER_ID_INTERNAL_DAC2: -+ return ENCODER_OBJECT_ID_INTERNAL_DAC2; -+ case ENCODER_ID_INTERNAL_SDVOA: -+ return ENCODER_OBJECT_ID_INTERNAL_SDVOA; -+ case ENCODER_ID_INTERNAL_SDVOB: -+ return ENCODER_OBJECT_ID_INTERNAL_SDVOB; -+ case ENCODER_ID_EXTERNAL_SI170B: -+ return ENCODER_OBJECT_ID_SI170B; -+ case ENCODER_ID_EXTERNAL_CH7303: -+ return ENCODER_OBJECT_ID_CH7303; -+ case ENCODER_ID_EXTERNAL_CH7301: -+ return ENCODER_OBJECT_ID_CH7301; -+ case ENCODER_ID_INTERNAL_DVO1: -+ return ENCODER_OBJECT_ID_INTERNAL_DVO1; -+ case ENCODER_ID_EXTERNAL_SDVOA: -+ return ENCODER_OBJECT_ID_EXTERNAL_SDVOA; -+ case ENCODER_ID_EXTERNAL_SDVOB: -+ return ENCODER_OBJECT_ID_EXTERNAL_SDVOB; -+ case ENCODER_ID_EXTERNAL_TITFP513: -+ return ENCODER_OBJECT_ID_TITFP513; -+ case ENCODER_ID_INTERNAL_LVTM1: -+ return ENCODER_OBJECT_ID_INTERNAL_LVTM1; -+ case ENCODER_ID_EXTERNAL_VT1623: -+ return ENCODER_OBJECT_ID_VT1623; -+ case ENCODER_ID_EXTERNAL_SI1930: -+ return ENCODER_OBJECT_ID_HDMI_SI1930; -+ 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_DVO1: -+ return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; -+ 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_SI178: -+ return ENCODER_OBJECT_ID_SI178; -+ 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_EXTERNAL_VT1625: -+ return ENCODER_OBJECT_ID_VT1625; -+ case ENCODER_ID_EXTERNAL_SI1932: -+ return ENCODER_OBJECT_ID_HDMI_SI1932; -+ case ENCODER_ID_EXTERNAL_AN9801: -+ return ENCODER_OBJECT_ID_DP_AN9801; -+ case ENCODER_ID_EXTERNAL_DP501: -+ return ENCODER_OBJECT_ID_DP_DP501; -+ 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_EXTERNAL_GENERIC_DVO: -+ return ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO; -+ case ENCODER_ID_UNKNOWN: -+ return ENCODER_OBJECT_ID_NONE; -+ default: -+ /* Invalid encoder id */ -+ BREAK_TO_DEBUGGER(); -+ return ENCODER_OBJECT_ID_NONE; -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h -new file mode 100644 -index 0000000..e5c00de ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h -@@ -0,0 +1,87 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_COMMAND_TABLE_HELPER_H__ -+#define __DAL_COMMAND_TABLE_HELPER_H__ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/command_table_helper_dce110.h" -+#endif -+ -+struct command_table_helper { -+ bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); -+ uint8_t (*encoder_action_to_atom)( -+ enum bp_encoder_control_action action); -+ uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s, -+ bool enable_dp_audio); -+ bool (*engine_bp_to_atom)(enum engine_id engine_id, -+ uint32_t *atom_engine_id); -+ void (*assign_control_parameter)( -+ const struct command_table_helper *h, -+ struct bp_encoder_control *control, -+ DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); -+ bool (*clock_source_id_to_atom)(enum clock_source_id id, -+ uint32_t *atom_pll_id); -+ bool (*clock_source_id_to_ref_clk_src)( -+ enum clock_source_id id, -+ uint32_t *ref_clk_src_id); -+ uint8_t (*transmitter_bp_to_atom)(enum transmitter t); -+ uint8_t (*encoder_id_to_atom)(enum encoder_id id); -+ uint8_t (*clock_source_id_to_atom_phy_clk_src_id)( -+ enum clock_source_id id); -+ uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s); -+ uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id); -+ uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id); -+ uint8_t (*phy_id_to_atom)(enum transmitter t); -+ uint8_t (*disp_power_gating_action_to_atom)( -+ enum bp_pipe_control_action action); -+}; -+ -+bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h, -+ enum dce_version dce); -+ -+bool dal_cmd_table_helper_controller_id_to_atom( -+ enum controller_id id, -+ uint8_t *atom_id); -+ -+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( -+ enum signal_type s, -+ bool enable_dp_audio); -+ -+void dal_cmd_table_helper_assign_control_parameter( -+ const struct command_table_helper *h, -+ struct bp_encoder_control *control, -+DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); -+ -+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( -+ enum clock_source_id id, -+ uint32_t *ref_clk_src_id); -+ -+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( -+ enum transmitter t); -+ -+uint8_t dal_cmd_table_helper_encoder_id_to_atom( -+ enum encoder_id id); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c -new file mode 100644 -index 0000000..2cc2d2d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c -@@ -0,0 +1,484 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sub license, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+#include "include/logger_interface.h" -+ -+#include "../bios_parser_helper.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "bif/bif_5_1_d.h" -+ -+/** -+ * set_scratch_acc_mode_change -+ * -+ * @brief -+ * set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when -+ * VGA/non-Accelerated mode is set -+ * -+ * @param -+ * struct dc_context *ctx - [in] DAL context -+ */ -+static void set_scratch_acc_mode_change( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = 0; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ value |= ATOM_S6_ACC_MODE; -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+/* -+ * set_scratch_active_and_requested -+ * -+ * @brief -+ * Set VBIOS scratch pad registers about active and requested displays -+ * -+ * @param -+ * struct dc_context *ctx - [in] DAL context for register accessing -+ * struct vbios_helper_data *d - [in] values to write -+ */ -+static void set_scratch_active_and_requested( -+ struct dc_context *ctx, -+ struct vbios_helper_data *d) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* mmBIOS_SCRATCH_3 = mmBIOS_SCRATCH_0 + ATOM_ACTIVE_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_3; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S3_DEVICE_ACTIVE_MASK; -+ value |= (d->active & ATOM_S3_DEVICE_ACTIVE_MASK); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ /* mmBIOS_SCRATCH_6 = mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_6; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S6_ACC_REQ_MASK; -+ value |= (d->requested & ATOM_S6_ACC_REQ_MASK); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ /* mmBIOS_SCRATCH_5 = mmBIOS_SCRATCH_0 + ATOM_DOS_REQ_INFO_DEF */ -+ addr = mmBIOS_SCRATCH_5; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ value &= ~ATOM_S5_DOS_REQ_DEVICEw0; -+ value |= (d->active & ATOM_S5_DOS_REQ_DEVICEw0); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ d->active = 0; -+ d->requested = 0; -+} -+ -+/** -+ * get LCD Scale Mode from VBIOS scratch register -+ */ -+static enum lcd_scale get_scratch_lcd_scale( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = 0; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ if (value & ATOM_S6_REQ_LCD_EXPANSION_FULL) -+ return LCD_SCALE_FULLPANEL; -+ else if (value & ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO) -+ return LCD_SCALE_ASPECTRATIO; -+ else -+ return LCD_SCALE_NONE; -+} -+ -+/** -+ * prepare_scratch_active_and_requested -+ * -+ * @brief -+ * prepare and update VBIOS scratch pad registers about active and requested -+ * displays -+ * -+ * @param -+ * data - helper's shared data -+ * enum controller_ild - controller Id -+ * enum signal_type - signal type used on display -+ * const struct connector_device_tag_info* - pointer to display type and enum id -+ */ -+static void prepare_scratch_active_and_requested( -+ struct dc_context *ctx, -+ struct vbios_helper_data *data, -+ enum controller_id id, -+ enum signal_type s, -+ const struct connector_device_tag_info *dev_tag) -+{ -+ switch (s) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ if (dev_tag->dev_id.device_type == DEVICE_TYPE_DFP) -+ switch (dev_tag->dev_id.enum_id) { -+ case 1: -+ data->requested |= ATOM_S6_ACC_REQ_DFP1; -+ data->active |= ATOM_S3_DFP1_ACTIVE; -+ break; -+ case 2: -+ data->requested |= ATOM_S6_ACC_REQ_DFP2; -+ data->active |= ATOM_S3_DFP2_ACTIVE; -+ break; -+ case 3: -+ data->requested |= ATOM_S6_ACC_REQ_DFP3; -+ data->active |= ATOM_S3_DFP3_ACTIVE; -+ break; -+ case 4: -+ data->requested |= ATOM_S6_ACC_REQ_DFP4; -+ data->active |= ATOM_S3_DFP4_ACTIVE; -+ break; -+ case 5: -+ data->requested |= ATOM_S6_ACC_REQ_DFP5; -+ data->active |= ATOM_S3_DFP5_ACTIVE; -+ break; -+ case 6: -+ data->requested |= ATOM_S6_ACC_REQ_DFP6; -+ data->active |= ATOM_S3_DFP6_ACTIVE; -+ break; -+ default: -+ break; -+ } -+ break; -+ case SIGNAL_TYPE_LVDS: -+ case SIGNAL_TYPE_EDP: -+ data->requested |= ATOM_S6_ACC_REQ_LCD1; -+ data->active |= ATOM_S3_LCD1_ACTIVE; -+ break; -+ case SIGNAL_TYPE_RGB: -+ if (dev_tag->dev_id.device_type == DEVICE_TYPE_CRT) -+ switch (dev_tag->dev_id.enum_id) { -+ case 1: -+ data->requested |= ATOM_S6_ACC_REQ_CRT1; -+ data->active |= ATOM_S3_CRT1_ACTIVE; -+ break; -+ case 2: -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_COMPONENT_BIOS, -+ "%s: DAL does not support DAC2!\n", -+ __func__); -+ break; -+ default: -+ break; -+ } -+ break; -+ default: -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_BIOS, -+ LOG_MINOR_COMPONENT_BIOS, -+ "%s: No such signal!\n", -+ __func__); -+ break; -+ } -+} -+ -+/* -+ * is_accelerated_mode -+ * -+ * @brief -+ * set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when -+ * VGA/non-Accelerated mode is set -+ * -+ * @param -+ * struct dc_context *ctx -+ * -+ * @return -+ * true if in acceleration mode, false otherwise. -+ */ -+static bool is_accelerated_mode( -+ struct dc_context *ctx) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ return (value & ATOM_S6_ACC_MODE) ? true : false; -+} -+ -+#define BIOS_SCRATCH0_DAC_B_SHIFT 8 -+ -+/** -+ * detect_sink -+ * -+ * @brief -+ * read VBIOS scratch register to determine whether display for the specified -+ * signal is present and return the actual sink signal type -+ * For analog signals VBIOS load detection has to be called prior reading the -+ * register -+ * -+ * @param -+ * encoder - encoder id (to specify DAC) -+ * connector - connector id (to check CV on DIN) -+ * signal - signal (as display type) to check -+ * -+ * @return -+ * signal_type - actual (on the sink) signal type detected -+ */ -+static enum signal_type detect_sink( -+ struct dc_context *ctx, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type signal) -+{ -+ uint32_t bios_scratch0; -+ uint32_t encoder_id = encoder.id; -+ /* after DCE 10.x does not support DAC2, so assert and return -+ * SIGNAL_TYPE_NONE */ -+ if (encoder_id == ENCODER_ID_INTERNAL_DAC2 -+ || encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC2) { -+ ASSERT(false); -+ return SIGNAL_TYPE_NONE; -+ } -+ -+ bios_scratch0 = dal_read_reg(ctx, -+ mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF); -+ -+ /* In further processing we use DACB masks. If we want detect load on -+ * DACA, we need to shift the register so DACA bits will be in place of -+ * DACB bits -+ */ -+ if (encoder_id == ENCODER_ID_INTERNAL_DAC1 -+ || encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC1 -+ || encoder_id == ENCODER_ID_EXTERNAL_NUTMEG -+ || encoder_id == ENCODER_ID_EXTERNAL_TRAVIS) { -+ bios_scratch0 <<= BIOS_SCRATCH0_DAC_B_SHIFT; -+ } -+ -+ switch (signal) { -+ case SIGNAL_TYPE_RGB: { -+ if (bios_scratch0 & ATOM_S0_CRT2_MASK) -+ return SIGNAL_TYPE_RGB; -+ break; -+ } -+ case SIGNAL_TYPE_LVDS: { -+ if (bios_scratch0 & ATOM_S0_LCD1) -+ return SIGNAL_TYPE_LVDS; -+ break; -+ } -+ case SIGNAL_TYPE_EDP: { -+ if (bios_scratch0 & ATOM_S0_LCD1) -+ return SIGNAL_TYPE_EDP; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return SIGNAL_TYPE_NONE; -+} -+ -+/** -+ * set_scratch_connected -+ * -+ * @brief -+ * update BIOS_SCRATCH_0 register about connected displays -+ * -+ * @param -+ * bool - update scratch register or just prepare info to be updated -+ * bool - connection state -+ * const struct connector_device_tag_info * - pointer to device type and enum ID -+ */ -+static void set_scratch_connected( -+ struct dc_context *ctx, -+ struct graphics_object_id id, -+ bool connected, -+ const struct connector_device_tag_info *device_tag) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ uint32_t update = 0; -+ -+ switch (device_tag->dev_id.device_type) { -+ case DEVICE_TYPE_LCD: -+ /* For LCD VBIOS will update LCD Panel connected bit always and -+ * Lid state bit based on SBIOS info do not do anything here -+ * for LCD -+ */ -+ break; -+ case DEVICE_TYPE_CRT: -+ /* -+ * CRT is not supported in DCE11 -+ */ -+ break; -+ case DEVICE_TYPE_DFP: -+ switch (device_tag->dev_id.enum_id) { -+ case 1: -+ update |= ATOM_S0_DFP1; -+ break; -+ case 2: -+ update |= ATOM_S0_DFP2; -+ break; -+ case 3: -+ update |= ATOM_S0_DFP3; -+ break; -+ case 4: -+ update |= ATOM_S0_DFP4; -+ break; -+ case 5: -+ update |= ATOM_S0_DFP5; -+ break; -+ case 6: -+ update |= ATOM_S0_DFP6; -+ break; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_TYPE_CV: -+ /* DCE 8.0 does not support CV, -+ * so don't do anything */ -+ break; -+ -+ case DEVICE_TYPE_TV: -+ /* For TV VBIOS will update S-Video or -+ * Composite scratch bits on DAL_LoadDetect -+ * when called by driver, do not do anything -+ * here for TV -+ */ -+ break; -+ -+ default: -+ break; -+ -+ } -+ -+ /* update scratch register */ -+ addr = mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ if (connected) -+ value |= update; -+ else -+ value &= ~update; -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void set_scratch_critical_state( -+ struct dc_context *ctx, -+ bool state) -+{ -+ uint32_t addr = mmBIOS_SCRATCH_6; -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ if (state) -+ value |= ATOM_S6_CRITICAL_STATE; -+ else -+ value &= ~ATOM_S6_CRITICAL_STATE; -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void set_scratch_lcd_scale( -+ struct dc_context *ctx, -+ enum lcd_scale lcd_scale_request) -+{ -+ DAL_LOGGER_NOT_IMPL( -+ LOG_MINOR_COMPONENT_BIOS, -+ "Bios Parser:%s\n", -+ __func__); -+} -+ -+static bool is_lid_open(struct dc_context *ctx) -+{ -+ uint32_t bios_scratch6; -+ -+ bios_scratch6 = -+ dal_read_reg( -+ ctx, -+ mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF); -+ -+ /* lid is open if the bit is not set */ -+ if (!(bios_scratch6 & ATOM_S6_LID_STATE)) -+ return true; -+ -+ return false; -+} -+ -+/* function table */ -+static const struct bios_parser_helper bios_parser_helper_funcs = { -+ .detect_sink = detect_sink, -+ .fmt_bit_depth_control = NULL, -+ .fmt_control = NULL, -+ .get_bios_event_info = NULL, -+ .get_embedded_display_controller_id = NULL, -+ .get_embedded_display_refresh_rate = NULL, -+ .get_requested_backlight_level = NULL, -+ .get_scratch_lcd_scale = get_scratch_lcd_scale, -+ .is_accelerated_mode = is_accelerated_mode, -+ .is_active_display = NULL, -+ .is_display_config_changed = NULL, -+ .is_lid_open = is_lid_open, -+ .is_lid_status_changed = NULL, -+ .prepare_scratch_active_and_requested = -+ prepare_scratch_active_and_requested, -+ .set_scratch_acc_mode_change = set_scratch_acc_mode_change, -+ .set_scratch_active_and_requested = set_scratch_active_and_requested, -+ .set_scratch_connected = set_scratch_connected, -+ .set_scratch_critical_state = set_scratch_critical_state, -+ .set_scratch_lcd_scale = set_scratch_lcd_scale, -+ .take_backlight_control = NULL, -+ .update_requested_backlight_level = NULL, -+}; -+ -+/* -+ * dal_bios_parser_dce110_init_bios_helper -+ * -+ * @brief -+ * Initialize BIOS helper functions -+ * -+ * @param -+ * const struct command_table_helper **h - [out] struct of functions -+ * -+ */ -+ -+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table() -+{ -+ return &bios_parser_helper_funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h -new file mode 100644 -index 0000000..915f31a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sub license, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_BIOS_PARSER_HELPER_DCE110_H__ -+#define __DAL_BIOS_PARSER_HELPER_DCE110_H__ -+ -+struct bios_parser_helper; -+ -+/* Initialize BIOS helper functions */ -+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table(void); -+ -+#endif /* __DAL_BIOS_PARSER_HELPER_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c -new file mode 100644 -index 0000000..e75b51b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c -@@ -0,0 +1,369 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "atom.h" -+ -+#include "include/bios_parser_types.h" -+#include "include/adapter_service_types.h" -+ -+#include "../command_table_helper.h" -+ -+static uint8_t phy_id_to_atom(enum transmitter t) -+{ -+ uint8_t atom_phy_id; -+ -+ switch (t) { -+ case TRANSMITTER_UNIPHY_A: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYA; -+ break; -+ case TRANSMITTER_UNIPHY_B: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYB; -+ break; -+ case TRANSMITTER_UNIPHY_C: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYC; -+ break; -+ case TRANSMITTER_UNIPHY_D: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYD; -+ break; -+ case TRANSMITTER_UNIPHY_E: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYE; -+ break; -+ case TRANSMITTER_UNIPHY_F: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYF; -+ break; -+ case TRANSMITTER_UNIPHY_G: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYG; -+ break; -+ default: -+ atom_phy_id = ATOM_PHY_ID_UNIPHYA; -+ break; -+ } -+ return atom_phy_id; -+} -+ -+ -+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) -+{ -+ uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; -+ -+ switch (s) { -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_EDP: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; -+ break; -+ case SIGNAL_TYPE_LVDS: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; -+ break; -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; -+ break; -+ default: -+ atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; -+ break; -+ } -+ -+ return atom_dig_mode; -+} -+ -+static uint8_t clock_source_id_to_atom_phy_clk_src_id( -+ enum clock_source_id id) -+{ -+ uint8_t atom_phy_clk_src_id = 0; -+ -+ switch (id) { -+ case CLOCK_SOURCE_ID_PLL0: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; -+ break; -+ case CLOCK_SOURCE_ID_PLL1: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; -+ break; -+ case CLOCK_SOURCE_ID_PLL2: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; -+ break; -+ case CLOCK_SOURCE_ID_EXTERNAL: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; -+ break; -+ default: -+ atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; -+ break; -+ } -+ -+ return atom_phy_clk_src_id >> 2; -+} -+ -+static uint8_t hpd_sel_to_atom(enum hpd_source_id id) -+{ -+ uint8_t atom_hpd_sel = 0; -+ -+ switch (id) { -+ case HPD_SOURCEID1: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; -+ break; -+ case HPD_SOURCEID2: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; -+ break; -+ case HPD_SOURCEID3: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; -+ break; -+ case HPD_SOURCEID4: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; -+ break; -+ case HPD_SOURCEID5: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; -+ break; -+ case HPD_SOURCEID6: -+ atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; -+ break; -+ case HPD_SOURCEID_UNKNOWN: -+ default: -+ atom_hpd_sel = 0; -+ break; -+ } -+ return atom_hpd_sel >> 4; -+} -+ -+static uint8_t dig_encoder_sel_to_atom(enum engine_id id) -+{ -+ uint8_t atom_dig_encoder_sel = 0; -+ -+ switch (id) { -+ case ENGINE_ID_DIGA: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; -+ break; -+ case ENGINE_ID_DIGB: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; -+ break; -+ case ENGINE_ID_DIGC: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; -+ break; -+ case ENGINE_ID_DIGD: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; -+ break; -+ case ENGINE_ID_DIGE: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; -+ break; -+ case ENGINE_ID_DIGF: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; -+ break; -+ case ENGINE_ID_DIGG: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; -+ break; -+ case ENGINE_ID_UNKNOWN: -+ /* No DIG_FRONT is associated to DIG_BACKEND */ -+ atom_dig_encoder_sel = 0; -+ break; -+ default: -+ atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; -+ break; -+ } -+ -+ return atom_dig_encoder_sel; -+} -+ -+static bool clock_source_id_to_atom( -+ enum clock_source_id id, -+ uint32_t *atom_pll_id) -+{ -+ bool result = true; -+ -+ if (atom_pll_id != NULL) -+ switch (id) { -+ case CLOCK_SOURCE_ID_PLL0: -+ *atom_pll_id = ATOM_PPLL0; -+ break; -+ case CLOCK_SOURCE_ID_PLL1: -+ *atom_pll_id = ATOM_PPLL1; -+ break; -+ case CLOCK_SOURCE_ID_PLL2: -+ *atom_pll_id = ATOM_PPLL2; -+ break; -+ case CLOCK_SOURCE_ID_EXTERNAL: -+ *atom_pll_id = ATOM_PPLL_INVALID; -+ break; -+ case CLOCK_SOURCE_ID_DFS: -+ *atom_pll_id = ATOM_EXT_PLL1; -+ break; -+ case CLOCK_SOURCE_ID_VCE: -+ /* for VCE encoding, -+ * we need to pass in ATOM_PPLL_INVALID -+ */ -+ *atom_pll_id = ATOM_PPLL_INVALID; -+ break; -+ case CLOCK_SOURCE_ID_DP_DTO: -+ /* When programming DP DTO PLL ID should be invalid */ -+ *atom_pll_id = ATOM_PPLL_INVALID; -+ break; -+ case CLOCK_SOURCE_ID_UNDEFINED: -+ /* Should not happen */ -+ *atom_pll_id = ATOM_PPLL_INVALID; -+ result = false; -+ break; -+ default: -+ result = false; -+ break; -+ } -+ -+ return result; -+} -+ -+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -+{ -+ bool result = false; -+ -+ if (atom_engine_id != NULL) -+ switch (id) { -+ case ENGINE_ID_DIGA: -+ *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGB: -+ *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGC: -+ *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGD: -+ *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGE: -+ *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGF: -+ *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DIGG: -+ *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DVO: -+ *atom_engine_id = ASIC_EXT_DIG_ENCODER_ID; -+ result = true; -+ break; -+ case ENGINE_ID_DACA: -+ *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; -+ result = true; -+ break; -+ default: -+ break; -+ } -+ -+ return result; -+} -+ -+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) -+{ -+ uint8_t atom_action = 0; -+ -+ switch (action) { -+ case ENCODER_CONTROL_ENABLE: -+ atom_action = ATOM_ENABLE; -+ break; -+ case ENCODER_CONTROL_DISABLE: -+ atom_action = ATOM_DISABLE; -+ break; -+ case ENCODER_CONTROL_SETUP: -+ atom_action = ATOM_ENCODER_CMD_SETUP; -+ break; -+ case ENCODER_CONTROL_INIT: -+ atom_action = ATOM_ENCODER_INIT; -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ -+ break; -+ } -+ -+ return atom_action; -+} -+ -+static uint8_t disp_power_gating_action_to_atom( -+ enum bp_pipe_control_action action) -+{ -+ uint8_t atom_pipe_action = 0; -+ -+ switch (action) { -+ case ASIC_PIPE_DISABLE: -+ atom_pipe_action = ATOM_DISABLE; -+ break; -+ case ASIC_PIPE_ENABLE: -+ atom_pipe_action = ATOM_ENABLE; -+ break; -+ case ASIC_PIPE_INIT: -+ atom_pipe_action = ATOM_INIT; -+ break; -+ default: -+ ASSERT_CRITICAL(false); /* Unhandle action in driver! */ -+ break; -+ } -+ -+ return atom_pipe_action; -+} -+ -+/* function table */ -+static const struct command_table_helper command_table_helper_funcs = { -+ .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, -+ .encoder_action_to_atom = encoder_action_to_atom, -+ .engine_bp_to_atom = engine_bp_to_atom, -+ .clock_source_id_to_atom = clock_source_id_to_atom, -+ .clock_source_id_to_atom_phy_clk_src_id = -+ clock_source_id_to_atom_phy_clk_src_id, -+ .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, -+ .hpd_sel_to_atom = hpd_sel_to_atom, -+ .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, -+ .phy_id_to_atom = phy_id_to_atom, -+ .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, -+ .assign_control_parameter = NULL, -+ .clock_source_id_to_ref_clk_src = NULL, -+ .transmitter_bp_to_atom = NULL, -+ .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, -+ .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, -+}; -+ -+/* -+ * dal_cmd_tbl_helper_dce110_get_table -+ * -+ * @brief -+ * Initialize command table helper functions -+ * -+ * @param -+ * const struct command_table_helper **h - [out] struct of functions -+ * -+ */ -+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table() -+{ -+ return &command_table_helper_funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h -new file mode 100644 -index 0000000..eb60c2e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__ -+#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__ -+ -+struct command_table_helper; -+ -+/* Initialize command table helper functions */ -+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void); -+ -+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile -new file mode 100644 -index 0000000..7f1916b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile -@@ -0,0 +1,10 @@ -+# -+# Makefile for the 'calcs' sub-component of DAL. -+# It calculates Bandwidth and Watermarks values for HW programming -+# -+ -+BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o -+ -+AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) -+ -+AMD_DAL_FILES += $(AMD_DAL_BW_CALCS) -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c -new file mode 100644 -index 0000000..68618bb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c -@@ -0,0 +1,3478 @@ -+/* -+ * 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 "dc_services.h" -+ -+#include "bandwidth_calcs.h" -+ -+/******************************************************************************* -+ * Private Functions -+ ******************************************************************************/ -+ -+enum bw_defines { -+ def_ok, -+ def_na, -+ def_notok, -+ def_display_write_back420_chroma, -+ def_display_write_back420_luma, -+ def_graphics, -+ def_xl_pattern_solid, -+ def_xl_pattern_light_horizontal, -+ def_xl_pattern_checker, -+ def_notok_color, -+ def_na_color, -+ def_vb_black, -+ def_vb_white, -+ def_high_no_nbp_state_change_color, -+ def_high_no_nbp_state_change, -+ def_high_color, -+ def_mid_color, -+ def_low_color, -+ def_high, -+ def_mid, -+ def_low, -+ def_exceeded_allowed_maximum_sclk, -+ def_exceeded_allowed_maximum_bw, -+ def_exceeded_allowed_page_close_open, -+ def_exceeded_allowed_outstanding_pte_req_queue_size, -+ def_linear, -+ def_underlay444, -+ def_underlay422, -+ def_underlay420_chroma, -+ def_underlay420_luma, -+ def_any_lines, -+ def_auto, -+ def_manual, -+ def_portrait, -+ def_invalid_linear_or_stereo_mode, -+ def_invalid_rotation_or_bpp_or_stereo, -+ def_vsr_more_than_vtaps, -+ def_vsr_more_than_4, -+ def_ceil_htaps_div_4_more_or_eq_hsr, -+ def_hsr_more_than_htaps, -+ def_hsr_more_than_4, -+ def_none, -+ def_blended, -+ def_landscape -+}; -+ -+static void calculate_bandwidth(const struct bw_calcs_input_dceip *dceip, -+ const struct bw_calcs_input_vbios *vbios, -+ const struct bw_calcs_input_mode_data_internal *mode_data, -+ struct bw_results_internal *results) -+{ -+ const struct bw_fixed pixels_per_chunk = int_to_fixed(512); -+ const struct bw_fixed max_chunks_non_fbc_mode = int_to_fixed(16); -+ const uint32_t high = 2; -+ const uint32_t mid = 1; -+ const uint32_t low = 0; -+ -+ uint32_t i, j, k; -+ struct bw_fixed yclk[3]; -+ struct bw_fixed sclk[3]; -+ bool d0_underlay_enable; -+ bool d1_underlay_enable; -+ enum bw_defines v_filter_init_mode[maximum_number_of_surfaces]; -+ enum bw_defines tiling_mode[maximum_number_of_surfaces]; -+ enum bw_stereo_mode stereo_mode[maximum_number_of_surfaces]; -+ enum bw_defines surface_type[maximum_number_of_surfaces]; -+ enum bw_defines voltage; -+ enum bw_defines mode_background_color; -+ enum bw_defines mode_font_color; -+ enum bw_defines mode_pattern; -+ enum bw_defines sclk_message; -+ enum bw_defines yclk_message; -+ 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; -+ uint32_t y_clk_level; -+ uint32_t sclk_level; -+ yclk[high] = vbios->high_yclk; -+ yclk[mid] = vbios->high_yclk; -+ yclk[low] = vbios->low_yclk; -+ sclk[high] = vbios->high_sclk; -+ sclk[mid] = vbios->mid_sclk; -+ sclk[low] = vbios->low_sclk; -+ if (mode_data->d0_underlay_mode == ul_none) { -+ d0_underlay_enable = false; -+ } else { -+ d0_underlay_enable = true; -+ } -+ if (mode_data->d1_underlay_mode == ul_none) { -+ d1_underlay_enable = false; -+ } else { -+ d1_underlay_enable = true; -+ } -+ results->number_of_underlay_surfaces = int_to_fixed( -+ d0_underlay_enable + d1_underlay_enable); -+ if (mode_data->underlay_surface_type == yuv_420) { -+ surface_type[0] = def_underlay420_luma; -+ surface_type[2] = def_underlay420_luma; -+ results->bytes_per_pixel[0] = int_to_fixed(1); -+ results->bytes_per_pixel[2] = int_to_fixed(1); -+ surface_type[1] = def_underlay420_chroma; -+ surface_type[3] = def_underlay420_chroma; -+ results->bytes_per_pixel[1] = int_to_fixed(2); -+ results->bytes_per_pixel[3] = int_to_fixed(2); -+ results->lb_size_per_component[0] = -+ dceip->underlay420_luma_lb_size_per_component; -+ results->lb_size_per_component[1] = -+ dceip->underlay420_chroma_lb_size_per_component; -+ results->lb_size_per_component[2] = -+ dceip->underlay420_luma_lb_size_per_component; -+ results->lb_size_per_component[3] = -+ dceip->underlay420_chroma_lb_size_per_component; -+ } else if (mode_data->underlay_surface_type == yuv_422) { -+ surface_type[0] = def_underlay422; -+ surface_type[2] = def_underlay422; -+ results->bytes_per_pixel[0] = int_to_fixed(2); -+ results->bytes_per_pixel[2] = int_to_fixed(2); -+ results->lb_size_per_component[0] = -+ dceip->underlay422_lb_size_per_component; -+ results->lb_size_per_component[2] = -+ dceip->underlay422_lb_size_per_component; -+ } else { -+ surface_type[0] = def_underlay444; -+ surface_type[2] = def_underlay444; -+ results->bytes_per_pixel[0] = int_to_fixed(4); -+ results->bytes_per_pixel[2] = int_to_fixed(4); -+ results->lb_size_per_component[0] = -+ dceip->lb_size_per_component444; -+ results->lb_size_per_component[2] = -+ dceip->lb_size_per_component444; -+ } -+ if (d0_underlay_enable) { -+ if (mode_data->underlay_surface_type == yuv_420) { -+ results->enable[0] = true; -+ results->enable[1] = true; -+ } else { -+ results->enable[0] = true; -+ results->enable[1] = false; -+ } -+ } else { -+ results->enable[0] = false; -+ results->enable[1] = false; -+ } -+ if (d1_underlay_enable) { -+ if (mode_data->underlay_surface_type == yuv_420) { -+ results->enable[2] = true; -+ results->enable[3] = true; -+ } else { -+ results->enable[2] = true; -+ results->enable[3] = false; -+ } -+ } else { -+ results->enable[2] = false; -+ results->enable[3] = false; -+ } -+ -+ results->use_alpha[0] = false; -+ results->use_alpha[1] = false; -+ results->use_alpha[2] = false; -+ results->use_alpha[3] = false; -+ results->scatter_gather_enable_for_pipe[0] = -+ vbios->scatter_gather_enable; -+ results->scatter_gather_enable_for_pipe[1] = -+ vbios->scatter_gather_enable; -+ results->scatter_gather_enable_for_pipe[2] = -+ vbios->scatter_gather_enable; -+ results->scatter_gather_enable_for_pipe[3] = -+ vbios->scatter_gather_enable; -+ results->interlace_mode[0] = mode_data->graphics_interlace_mode; -+ results->interlace_mode[1] = mode_data->graphics_interlace_mode; -+ results->interlace_mode[2] = mode_data->graphics_interlace_mode; -+ results->interlace_mode[3] = mode_data->graphics_interlace_mode; -+ results->h_total[0] = mode_data->d0_htotal; -+ results->h_total[1] = mode_data->d0_htotal; -+ results->h_total[2] = mode_data->d1_htotal; -+ results->h_total[3] = mode_data->d1_htotal; -+ results->pixel_rate[0] = mode_data->d0_pixel_rate; -+ results->pixel_rate[1] = mode_data->d0_pixel_rate; -+ results->pixel_rate[2] = mode_data->d1_pixel_rate; -+ results->pixel_rate[3] = mode_data->d1_pixel_rate; -+ results->src_width[0] = mode_data->underlay_src_width; -+ results->src_width[1] = mode_data->underlay_src_width; -+ results->src_width[2] = mode_data->underlay_src_width; -+ results->src_width[3] = mode_data->underlay_src_width; -+ results->src_height[0] = mode_data->underlay_src_height; -+ results->src_height[1] = mode_data->underlay_src_height; -+ results->src_height[2] = mode_data->underlay_src_height; -+ results->src_height[3] = mode_data->underlay_src_height; -+ results->pitch_in_pixels[0] = mode_data->underlay_pitch_in_pixels; -+ results->pitch_in_pixels[1] = mode_data->underlay_pitch_in_pixels; -+ results->pitch_in_pixels[2] = mode_data->underlay_pitch_in_pixels; -+ results->pitch_in_pixels[3] = mode_data->underlay_pitch_in_pixels; -+ results->scale_ratio[0] = mode_data->d0_underlay_scale_ratio; -+ results->scale_ratio[1] = mode_data->d0_underlay_scale_ratio; -+ results->scale_ratio[2] = mode_data->d1_underlay_scale_ratio; -+ results->scale_ratio[3] = mode_data->d1_underlay_scale_ratio; -+ results->h_taps[0] = mode_data->underlay_htaps; -+ results->h_taps[1] = mode_data->underlay_htaps; -+ results->h_taps[2] = mode_data->underlay_htaps; -+ results->h_taps[3] = mode_data->underlay_htaps; -+ results->v_taps[0] = mode_data->underlay_vtaps; -+ results->v_taps[1] = mode_data->underlay_vtaps; -+ results->v_taps[2] = mode_data->underlay_vtaps; -+ results->v_taps[3] = mode_data->underlay_vtaps; -+ results->rotation_angle[0] = mode_data->underlay_rotation_angle; -+ results->rotation_angle[1] = mode_data->underlay_rotation_angle; -+ results->rotation_angle[2] = mode_data->underlay_rotation_angle; -+ results->rotation_angle[3] = mode_data->underlay_rotation_angle; -+ if (mode_data->underlay_tiling_mode == linear) { -+ tiling_mode[0] = def_linear; -+ tiling_mode[1] = def_linear; -+ tiling_mode[2] = def_linear; -+ tiling_mode[3] = def_linear; -+ } else { -+ tiling_mode[0] = def_landscape; -+ tiling_mode[1] = def_landscape; -+ tiling_mode[2] = def_landscape; -+ tiling_mode[3] = def_landscape; -+ } -+ stereo_mode[0] = mode_data->underlay_stereo_mode; -+ stereo_mode[1] = mode_data->underlay_stereo_mode; -+ stereo_mode[2] = mode_data->underlay_stereo_mode; -+ stereo_mode[3] = mode_data->underlay_stereo_mode; -+ results->lb_bpc[0] = mode_data->underlay_lb_bpc; -+ results->lb_bpc[1] = mode_data->underlay_lb_bpc; -+ results->lb_bpc[2] = mode_data->underlay_lb_bpc; -+ results->lb_bpc[3] = mode_data->underlay_lb_bpc; -+ results->compression_rate[0] = int_to_fixed(1); -+ results->compression_rate[1] = int_to_fixed(1); -+ results->compression_rate[2] = int_to_fixed(1); -+ results->compression_rate[3] = int_to_fixed(1); -+ results->access_one_channel_only[0] = false; -+ results->access_one_channel_only[1] = false; -+ results->access_one_channel_only[2] = false; -+ results->access_one_channel_only[3] = false; -+ results->cursor_width_pixels[0] = int_to_fixed(0); -+ results->cursor_width_pixels[1] = int_to_fixed(0); -+ results->cursor_width_pixels[2] = int_to_fixed(0); -+ results->cursor_width_pixels[3] = int_to_fixed(0); -+ for (i = 4; i <= maximum_number_of_surfaces - 3; i += 1) { -+ if (i < mode_data->number_of_displays + 4) { -+ if (i == 4 && mode_data->d0_underlay_mode == ul_only) { -+ results->enable[i] = false; -+ results->use_alpha[i] = false; -+ } else if (i == 4 -+ && mode_data->d0_underlay_mode == ul_blend) { -+ results->enable[i] = true; -+ results->use_alpha[i] = true; -+ } else if (i == 4) { -+ results->enable[i] = true; -+ results->use_alpha[i] = false; -+ } else if (i == 5 -+ && mode_data->d1_underlay_mode == ul_only) { -+ results->enable[i] = false; -+ results->use_alpha[i] = false; -+ } else if (i == 5 -+ && mode_data->d1_underlay_mode == ul_blend) { -+ results->enable[i] = true; -+ results->use_alpha[i] = true; -+ } else { -+ results->enable[i] = true; -+ results->use_alpha[i] = false; -+ } -+ } else { -+ results->enable[i] = false; -+ results->use_alpha[i] = false; -+ } -+ results->scatter_gather_enable_for_pipe[i] = -+ vbios->scatter_gather_enable; -+ surface_type[i] = def_graphics; -+ results->lb_size_per_component[i] = -+ dceip->lb_size_per_component444; -+ results->bytes_per_pixel[i] = -+ mode_data->graphics_bytes_per_pixel; -+ results->interlace_mode[i] = mode_data->graphics_interlace_mode; -+ results->h_taps[i] = mode_data->graphics_htaps; -+ results->v_taps[i] = mode_data->graphics_vtaps; -+ results->rotation_angle[i] = mode_data->graphics_rotation_angle; -+ if (mode_data->graphics_tiling_mode == linear) { -+ tiling_mode[i] = def_linear; -+ } else if (equ(mode_data->graphics_rotation_angle, -+ int_to_fixed(0)) -+ || equ(mode_data->graphics_rotation_angle, -+ int_to_fixed(180))) { -+ tiling_mode[i] = def_landscape; -+ } else { -+ tiling_mode[i] = def_portrait; -+ } -+ results->lb_bpc[i] = mode_data->graphics_lb_bpc; -+ if (i == 4) { -+ /* todo: check original d0_underlay_mode comparison, possible bug there*/ -+ if (mode_data->d0_fbc_enable -+ && (dceip->argb_compression_support -+ || mode_data->d0_underlay_mode -+ != ul_blend)) { -+ results->compression_rate[i] = -+ vbios->average_compression_rate; -+ results->access_one_channel_only[i] = -+ mode_data->d0_lpt_enable; -+ } else { -+ results->compression_rate[i] = int_to_fixed(1); -+ results->access_one_channel_only[i] = false; -+ } -+ results->h_total[i] = mode_data->d0_htotal; -+ results->pixel_rate[i] = mode_data->d0_pixel_rate; -+ results->src_width[i] = -+ mode_data->d0_graphics_src_width; -+ results->src_height[i] = -+ mode_data->d0_graphics_src_height; -+ results->pitch_in_pixels[i] = -+ mode_data->d0_graphics_src_width; -+ results->scale_ratio[i] = -+ mode_data->d0_graphics_scale_ratio; -+ stereo_mode[i] = mode_data->d0_graphics_stereo_mode; -+ } else if (i == 5) { -+ results->compression_rate[i] = int_to_fixed(1); -+ results->access_one_channel_only[i] = false; -+ results->h_total[i] = mode_data->d1_htotal; -+ results->pixel_rate[i] = mode_data->d1_pixel_rate; -+ results->src_width[i] = -+ mode_data->d1_graphics_src_width; -+ results->src_height[i] = -+ mode_data->d1_graphics_src_height; -+ results->pitch_in_pixels[i] = -+ mode_data->d1_graphics_src_width; -+ results->scale_ratio[i] = -+ mode_data->d1_graphics_scale_ratio; -+ stereo_mode[i] = mode_data->d1_graphics_stereo_mode; -+ } else { -+ results->compression_rate[i] = int_to_fixed(1); -+ results->access_one_channel_only[i] = false; -+ results->h_total[i] = mode_data->d2_htotal; -+ results->pixel_rate[i] = mode_data->d2_pixel_rate; -+ results->src_width[i] = -+ mode_data->d2_graphics_src_width; -+ results->src_height[i] = -+ mode_data->d2_graphics_src_height; -+ results->pitch_in_pixels[i] = -+ mode_data->d2_graphics_src_width; -+ results->scale_ratio[i] = -+ mode_data->d2_graphics_scale_ratio; -+ stereo_mode[i] = mode_data->d2_graphics_stereo_mode; -+ } -+ results->cursor_width_pixels[i] = vbios->cursor_width; -+ } -+ results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = -+ false; -+ results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = -+ false; -+ if (mode_data->d1_display_write_back_dwb_enable == true) { -+ results->enable[maximum_number_of_surfaces - 2] = true; -+ results->enable[maximum_number_of_surfaces - 1] = true; -+ } else { -+ results->enable[maximum_number_of_surfaces - 2] = false; -+ results->enable[maximum_number_of_surfaces - 1] = false; -+ } -+ surface_type[maximum_number_of_surfaces - 2] = -+ def_display_write_back420_luma; -+ surface_type[maximum_number_of_surfaces - 1] = -+ def_display_write_back420_chroma; -+ results->lb_size_per_component[maximum_number_of_surfaces - 2] = -+ dceip->underlay420_luma_lb_size_per_component; -+ results->lb_size_per_component[maximum_number_of_surfaces - 1] = -+ dceip->underlay420_chroma_lb_size_per_component; -+ results->bytes_per_pixel[maximum_number_of_surfaces - 2] = int_to_fixed( -+ 1); -+ results->bytes_per_pixel[maximum_number_of_surfaces - 1] = int_to_fixed( -+ 2); -+ results->interlace_mode[maximum_number_of_surfaces - 2] = -+ mode_data->graphics_interlace_mode; -+ results->interlace_mode[maximum_number_of_surfaces - 1] = -+ mode_data->graphics_interlace_mode; -+ results->h_taps[maximum_number_of_surfaces - 2] = int_to_fixed(1); -+ results->h_taps[maximum_number_of_surfaces - 1] = int_to_fixed(1); -+ results->v_taps[maximum_number_of_surfaces - 2] = int_to_fixed(1); -+ results->v_taps[maximum_number_of_surfaces - 1] = int_to_fixed(1); -+ results->rotation_angle[maximum_number_of_surfaces - 2] = int_to_fixed( -+ 0); -+ results->rotation_angle[maximum_number_of_surfaces - 1] = int_to_fixed( -+ 0); -+ tiling_mode[maximum_number_of_surfaces - 2] = def_linear; -+ tiling_mode[maximum_number_of_surfaces - 1] = def_linear; -+ results->lb_bpc[maximum_number_of_surfaces - 2] = int_to_fixed(8); -+ results->lb_bpc[maximum_number_of_surfaces - 1] = int_to_fixed(8); -+ results->compression_rate[maximum_number_of_surfaces - 2] = -+ int_to_fixed(1); -+ results->compression_rate[maximum_number_of_surfaces - 1] = -+ int_to_fixed(1); -+ results->access_one_channel_only[maximum_number_of_surfaces - 2] = -+ false; -+ results->access_one_channel_only[maximum_number_of_surfaces - 1] = -+ false; -+ results->h_total[maximum_number_of_surfaces - 2] = mode_data->d1_htotal; -+ results->h_total[maximum_number_of_surfaces - 1] = mode_data->d1_htotal; -+ results->pixel_rate[maximum_number_of_surfaces - 2] = -+ mode_data->d1_pixel_rate; -+ results->pixel_rate[maximum_number_of_surfaces - 1] = -+ mode_data->d1_pixel_rate; -+ results->src_width[maximum_number_of_surfaces - 2] = -+ mode_data->d1_graphics_src_width; -+ results->src_width[maximum_number_of_surfaces - 1] = -+ mode_data->d1_graphics_src_width; -+ results->src_height[maximum_number_of_surfaces - 2] = -+ mode_data->d1_graphics_src_height; -+ results->src_height[maximum_number_of_surfaces - 1] = -+ mode_data->d1_graphics_src_height; -+ results->pitch_in_pixels[maximum_number_of_surfaces - 2] = -+ mode_data->d1_graphics_src_width; -+ results->pitch_in_pixels[maximum_number_of_surfaces - 1] = -+ mode_data->d1_graphics_src_width; -+ results->scale_ratio[maximum_number_of_surfaces - 2] = int_to_fixed(1); -+ results->scale_ratio[maximum_number_of_surfaces - 1] = int_to_fixed(1); -+ stereo_mode[maximum_number_of_surfaces - 2] = mono; -+ stereo_mode[maximum_number_of_surfaces - 1] = mono; -+ results->cursor_width_pixels[maximum_number_of_surfaces - 2] = -+ int_to_fixed(0); -+ results->cursor_width_pixels[maximum_number_of_surfaces - 1] = -+ int_to_fixed(0); -+ results->use_alpha[maximum_number_of_surfaces - 2] = false; -+ results->use_alpha[maximum_number_of_surfaces - 1] = false; -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (equ(results->scale_ratio[i], int_to_fixed(1)) -+ && surface_type[i] == def_graphics -+ && stereo_mode[i] == mono -+ && results->interlace_mode[i] == false) { -+ results->h_taps[i] = int_to_fixed(1); -+ results->v_taps[i] = int_to_fixed(1); -+ } -+ if (surface_type[i] == def_display_write_back420_chroma -+ || surface_type[i] == def_underlay420_chroma) { -+ results->pitch_in_pixels_after_surface_type[i] = -+ bw_div(results->pitch_in_pixels[i], -+ int_to_fixed(2)); -+ results->src_width_after_surface_type = bw_div( -+ results->src_width[i], int_to_fixed(2)); -+ results->src_height_after_surface_type = bw_div( -+ results->src_height[i], -+ int_to_fixed(2)); -+ results->hsr_after_surface_type = bw_div( -+ results->scale_ratio[i], -+ int_to_fixed(2)); -+ results->vsr_after_surface_type = bw_div( -+ results->scale_ratio[i], -+ int_to_fixed(2)); -+ } else { -+ results->pitch_in_pixels_after_surface_type[i] = -+ results->pitch_in_pixels[i]; -+ results->src_width_after_surface_type = -+ results->src_width[i]; -+ results->src_height_after_surface_type = -+ results->src_height[i]; -+ results->hsr_after_surface_type = -+ results->scale_ratio[i]; -+ results->vsr_after_surface_type = -+ results->scale_ratio[i]; -+ } -+ if ((equ(results->rotation_angle[i], int_to_fixed(90)) -+ || equ(results->rotation_angle[i], -+ int_to_fixed(270))) -+ && surface_type[i] != def_graphics) { -+ results->src_width_after_rotation = -+ results->src_height_after_surface_type; -+ results->src_height_after_rotation = -+ results->src_width_after_surface_type; -+ results->hsr_after_rotation = -+ results->vsr_after_surface_type; -+ results->vsr_after_rotation = -+ results->hsr_after_surface_type; -+ } else { -+ results->src_width_after_rotation = -+ results->src_width_after_surface_type; -+ results->src_height_after_rotation = -+ results->src_height_after_surface_type; -+ results->hsr_after_rotation = -+ results->hsr_after_surface_type; -+ results->vsr_after_rotation = -+ results->vsr_after_surface_type; -+ } -+ if (stereo_mode[i] == top_bottom) { -+ results->source_width_pixels[i] = -+ results->src_width_after_rotation; -+ results->source_height_pixels = mul( -+ int_to_fixed(2), -+ results->src_height_after_rotation); -+ results->hsr_after_stereo = -+ results->hsr_after_rotation; -+ results->vsr_after_stereo = mul( -+ results->vsr_after_rotation, -+ int_to_fixed(1)); //todo: confirm correctness -+ } else if (stereo_mode[i] == side_by_side) { -+ results->source_width_pixels[i] = mul( -+ int_to_fixed(2), -+ results->src_width_after_rotation); -+ results->source_height_pixels = -+ results->src_height_after_rotation; -+ results->hsr_after_stereo = mul( -+ results->hsr_after_rotation, -+ int_to_fixed(1)); //todo: confirm correctness -+ results->vsr_after_stereo = -+ results->vsr_after_rotation; -+ } else { -+ results->source_width_pixels[i] = -+ results->src_width_after_rotation; -+ results->source_height_pixels = -+ results->src_height_after_rotation; -+ results->hsr_after_stereo = -+ results->hsr_after_rotation; -+ results->vsr_after_stereo = -+ results->vsr_after_rotation; -+ } -+ results->hsr[i] = results->hsr_after_stereo; -+ if (results->interlace_mode[i]) { -+ results->vsr[i] = mul(results->vsr_after_stereo, -+ int_to_fixed(2)); -+ } else { -+ results->vsr[i] = results->vsr_after_stereo; -+ } -+ if (mode_data->panning_and_bezel_adjustment != none) { -+ results->source_width_rounded_up_to_chunks[i] = -+ add( -+ bw_floor( -+ sub( -+ results->source_width_pixels[i], -+ int_to_fixed( -+ 1)), -+ int_to_fixed(128)), -+ int_to_fixed(256)); -+ } else { -+ results->source_width_rounded_up_to_chunks[i] = -+ bw_ceil(results->source_width_pixels[i], -+ int_to_fixed(128)); -+ } -+ results->source_height_rounded_up_to_chunks[i] = -+ results->source_height_pixels; -+ } -+ } -+ if (geq(dceip->number_of_graphics_pipes, -+ int_to_fixed(mode_data->number_of_displays)) -+ && geq(dceip->number_of_underlay_pipes, -+ results->number_of_underlay_surfaces) -+ && !(dceip->display_write_back_supported == false -+ && mode_data->d1_display_write_back_dwb_enable == true)) { -+ pipe_check = def_ok; -+ } else { -+ pipe_check = def_notok; -+ } -+ hsr_check = def_ok; -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (neq(results->hsr[i], int_to_fixed(1))) { -+ if (gtn(results->hsr[i], int_to_fixed(4))) { -+ hsr_check = def_hsr_more_than_4; -+ } else { -+ if (gtn(results->hsr[i], -+ results->h_taps[i])) { -+ hsr_check = -+ def_hsr_more_than_htaps; -+ } else { -+ if (dceip->pre_downscaler_enabled -+ == true -+ && gtn(results->hsr[i], -+ int_to_fixed(1)) -+ && leq(results->hsr[i], -+ bw_ceil( -+ bw_div( -+ results->h_taps[i], -+ int_to_fixed( -+ 4)), -+ int_to_fixed( -+ 1)))) { -+ hsr_check = -+ def_ceil_htaps_div_4_more_or_eq_hsr; -+ } -+ } -+ } -+ } -+ } -+ } -+ vsr_check = def_ok; -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (neq(results->vsr[i], int_to_fixed(1))) { -+ if (gtn(results->vsr[i], int_to_fixed(4))) { -+ vsr_check = def_vsr_more_than_4; -+ } else { -+ if (gtn(results->vsr[i], -+ results->v_taps[i])) { -+ vsr_check = -+ def_vsr_more_than_vtaps; -+ } -+ } -+ } -+ } -+ } -+ lb_size_check = def_ok; -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if ((dceip->pre_downscaler_enabled -+ && gtn(results->hsr[i], int_to_fixed(1)))) { -+ results->source_width_in_lb = bw_div( -+ results->source_width_pixels[i], -+ results->hsr[i]); -+ } else { -+ results->source_width_in_lb = -+ results->source_width_pixels[i]; -+ } -+ if (equ(results->lb_bpc[i], int_to_fixed(8))) { -+ results->lb_line_pitch = -+ bw_ceil( -+ mul(frc_to_fixed(24011, 3000), -+ bw_ceil( -+ results->source_width_in_lb, -+ int_to_fixed( -+ 8))), -+ int_to_fixed(48)); -+ } else if (equ(results->lb_bpc[i], int_to_fixed(10))) { -+ results->lb_line_pitch = -+ bw_ceil( -+ mul(frc_to_fixed(30023, 3000), -+ bw_ceil( -+ results->source_width_in_lb, -+ int_to_fixed( -+ 8))), -+ int_to_fixed(48)); -+ } else -+ // case else -+ { -+ results->lb_line_pitch = bw_ceil( -+ mul(results->source_width_in_lb, -+ results->lb_bpc[i]), -+ int_to_fixed(48)); -+ } -+ results->lb_partitions[i] = bw_floor( -+ bw_div(results->lb_size_per_component[i], -+ results->lb_line_pitch), -+ int_to_fixed(1)); -+ if ((surface_type[i] != def_graphics -+ || dceip->graphics_lb_nodownscaling_multi_line_prefetching -+ == true)) { -+ results->lb_partitions_max[i] = int_to_fixed( -+ 10); -+ } else { -+ results->lb_partitions_max[i] = int_to_fixed(7); -+ } -+ results->lb_partitions[i] = bw_min( -+ results->lb_partitions_max[i], -+ results->lb_partitions[i]); -+ if (gtn(add(results->v_taps[i], int_to_fixed(1)), -+ results->lb_partitions[i])) { -+ lb_size_check = def_notok; -+ } -+ } -+ } -+ if (mode_data->d0_fbc_enable -+ && (equ(mode_data->graphics_rotation_angle, int_to_fixed(90)) -+ || equ(mode_data->graphics_rotation_angle, -+ int_to_fixed(270)) -+ || mode_data->d0_graphics_stereo_mode != mono -+ || neq(mode_data->graphics_bytes_per_pixel, -+ int_to_fixed(4)))) { -+ fbc_check = def_invalid_rotation_or_bpp_or_stereo; -+ } else { -+ fbc_check = def_ok; -+ } -+ rotation_check = def_ok; -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if ((equ(results->rotation_angle[i], int_to_fixed(90)) -+ || equ(results->rotation_angle[i], -+ int_to_fixed(270))) -+ && (tiling_mode[i] == def_linear -+ || stereo_mode[i] != mono)) { -+ rotation_check = -+ def_invalid_linear_or_stereo_mode; -+ } -+ } -+ } -+ if (pipe_check == def_ok && hsr_check == def_ok && vsr_check == def_ok -+ && lb_size_check == def_ok && fbc_check == def_ok -+ && rotation_check == def_ok) { -+ mode_check = def_ok; -+ } else { -+ mode_check = def_notok; -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if ((equ(results->rotation_angle[i], int_to_fixed(90)) -+ || equ(results->rotation_angle[i], -+ int_to_fixed(270)))) { -+ if ((tiling_mode[i] == def_portrait)) { -+ results->orthogonal_rotation[i] = false; -+ } else { -+ results->orthogonal_rotation[i] = true; -+ } -+ } else { -+ if ((tiling_mode[i] == def_portrait)) { -+ results->orthogonal_rotation[i] = true; -+ } else { -+ results->orthogonal_rotation[i] = false; -+ } -+ } -+ if (equ(results->rotation_angle[i], int_to_fixed(90)) -+ || equ(results->rotation_angle[i], -+ int_to_fixed(270))) { -+ results->underlay_maximum_source_efficient_for_tiling = -+ dceip->underlay_maximum_height_efficient_for_tiling; -+ } else { -+ results->underlay_maximum_source_efficient_for_tiling = -+ dceip->underlay_maximum_width_efficient_for_tiling; -+ } -+ if (equ(dceip->de_tiling_buffer, int_to_fixed(0))) { -+ if (surface_type[i] -+ == def_display_write_back420_luma -+ || surface_type[i] -+ == def_display_write_back420_chroma) { -+ results->bytes_per_request[i] = -+ int_to_fixed(64); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed(64); -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(1); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(1); -+ } else if (tiling_mode[i] == def_linear) { -+ results->bytes_per_request[i] = -+ int_to_fixed(64); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed(64); -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(2); -+ } else { -+ if (surface_type[i] == def_graphics -+ || (gtn( -+ results->source_width_rounded_up_to_chunks[i], -+ bw_ceil( -+ results->underlay_maximum_source_efficient_for_tiling, -+ int_to_fixed( -+ 256))))) { -+ if (equ( -+ results->bytes_per_pixel[i], -+ int_to_fixed(8))) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(2); -+ if (results->orthogonal_rotation[i]) { -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ } else { -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 64); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 64); -+ } -+ } else if (equ( -+ results->bytes_per_pixel[i], -+ int_to_fixed(4))) { -+ if (results->orthogonal_rotation[i]) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed( -+ 2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed( -+ 2); -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 16); -+ } else { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed( -+ 2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed( -+ 2); -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 64); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 64); -+ } -+ } else if (equ( -+ results->bytes_per_pixel[i], -+ int_to_fixed(2))) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(2); -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ } else { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(2); -+ results->bytes_per_request[i] = -+ int_to_fixed( -+ 32); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed( -+ 16); -+ } -+ } else { -+ results->bytes_per_request[i] = -+ int_to_fixed(64); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed(64); -+ if (results->orthogonal_rotation[i]) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(8); -+ results->latency_hiding_lines[i] = -+ int_to_fixed(4); -+ } else { -+ if (equ( -+ results->bytes_per_pixel[i], -+ int_to_fixed( -+ 4))) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed( -+ 2); -+ results->latency_hiding_lines[i] = -+ int_to_fixed( -+ 2); -+ } else if (equ( -+ results->bytes_per_pixel[i], -+ int_to_fixed( -+ 2))) { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed( -+ 4); -+ results->latency_hiding_lines[i] = -+ int_to_fixed( -+ 4); -+ } else { -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed( -+ 8); -+ results->latency_hiding_lines[i] = -+ int_to_fixed( -+ 4); -+ } -+ } -+ } -+ } -+ } else { -+ results->bytes_per_request[i] = int_to_fixed( -+ 256); -+ results->useful_bytes_per_request[i] = -+ int_to_fixed(256); -+ results->lines_interleaved_in_mem_access[i] = -+ int_to_fixed(4); -+ results->latency_hiding_lines[i] = int_to_fixed( -+ 4); -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->v_filter_init[i] = -+ bw_floor( -+ bw_div( -+ (add( -+ add( -+ add( -+ results->vsr[i], -+ results->v_taps[i]), -+ mul( -+ mul( -+ frc_to_fixed( -+ 1, -+ 2), -+ results->vsr[i]), -+ int_to_fixed( -+ results->interlace_mode[i]))), -+ int_to_fixed(1))), -+ int_to_fixed(2)), -+ int_to_fixed(1)); -+ if (mode_data->panning_and_bezel_adjustment -+ == any_lines) { -+ results->v_filter_init[i] = add( -+ results->v_filter_init[i], -+ int_to_fixed(1)); -+ } -+ if (stereo_mode[i] == top_bottom) { -+ v_filter_init_mode[i] = def_manual; -+ results->v_filter_init[i] = bw_min( -+ results->v_filter_init[i], -+ int_to_fixed(4)); -+ } else { -+ v_filter_init_mode[i] = def_auto; -+ } -+ if (stereo_mode[i] == top_bottom) { -+ results->num_lines_at_frame_start = -+ int_to_fixed(1); -+ } else { -+ results->num_lines_at_frame_start = -+ int_to_fixed(3); -+ } -+ if ((gtn(results->vsr[i], int_to_fixed(1)) -+ && surface_type[i] == def_graphics) -+ || mode_data->panning_and_bezel_adjustment -+ == any_lines) { -+ results->line_buffer_prefetch[i] = int_to_fixed( -+ 0); -+ } else if ((((dceip->underlay_downscale_prefetch_enabled -+ == true && surface_type[i] != def_graphics) -+ || surface_type[i] == def_graphics) -+ && (gtn(results->lb_partitions[i], -+ add(results->v_taps[i], -+ bw_ceil(results->vsr[i], -+ int_to_fixed(1))))))) { -+ results->line_buffer_prefetch[i] = int_to_fixed( -+ 1); -+ } else { -+ results->line_buffer_prefetch[i] = int_to_fixed( -+ 0); -+ } -+ results->lb_lines_in_per_line_out_in_beginning_of_frame[i] = -+ bw_div( -+ bw_ceil(results->v_filter_init[i], -+ dceip->lines_interleaved_into_lb), -+ results->num_lines_at_frame_start); -+ if (equ(results->line_buffer_prefetch[i], -+ int_to_fixed(1))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ bw_max(int_to_fixed(1), -+ results->vsr[i]); -+ } else if (leq(results->vsr[i], int_to_fixed(1))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ int_to_fixed(1); -+ } else if (leq(results->vsr[i], -+ bw_div(int_to_fixed(4), int_to_fixed(3)))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ bw_div(int_to_fixed(4), int_to_fixed(3)); -+ } else if (leq(results->vsr[i], -+ bw_div(int_to_fixed(6), int_to_fixed(4)))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ bw_div(int_to_fixed(6), int_to_fixed(4)); -+ } else if (leq(results->vsr[i], int_to_fixed(2))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ int_to_fixed(2); -+ } else if (leq(results->vsr[i], int_to_fixed(3))) { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ int_to_fixed(3); -+ } else { -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i] = -+ int_to_fixed(4); -+ } -+ if (equ(results->line_buffer_prefetch[i], -+ int_to_fixed(1)) -+ || equ( -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i], -+ int_to_fixed(2)) -+ || equ( -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i], -+ int_to_fixed(4))) { -+ results->horizontal_blank_and_chunk_granularity_factor[i] = -+ int_to_fixed(1); -+ } else { -+ results->horizontal_blank_and_chunk_granularity_factor[i] = -+ bw_div(results->h_total[i], -+ (bw_div( -+ (add( -+ results->h_total[i], -+ bw_div( -+ (sub( -+ results->source_width_pixels[i], -+ dceip->chunk_width)), -+ results->hsr[i]))), -+ int_to_fixed(2)))); -+ } -+ results->request_bandwidth[i] = -+ bw_div( -+ mul( -+ bw_div( -+ mul( -+ bw_div( -+ mul( -+ bw_max( -+ results->lb_lines_in_per_line_out_in_beginning_of_frame[i], -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i]), -+ results->source_width_rounded_up_to_chunks[i]), -+ (bw_div( -+ results->h_total[i], -+ results->pixel_rate[i]))), -+ results->bytes_per_pixel[i]), -+ results->useful_bytes_per_request[i]), -+ results->lines_interleaved_in_mem_access[i]), -+ results->latency_hiding_lines[i]); -+ results->display_bandwidth[i] = mul( -+ results->request_bandwidth[i], -+ results->bytes_per_request[i]); -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] == def_display_write_back420_luma) { -+ results->data_buffer_size[i] = -+ dceip->display_write_back420_luma_mcifwr_buffer_size; -+ } else if (surface_type[i] -+ == def_display_write_back420_chroma) { -+ results->data_buffer_size[i] = -+ dceip->display_write_back420_chroma_mcifwr_buffer_size; -+ } else if (surface_type[i] == def_underlay420_luma) { -+ results->data_buffer_size[i] = -+ dceip->underlay_luma_dmif_size; -+ } else if (surface_type[i] == def_underlay420_chroma) { -+ results->data_buffer_size[i] = bw_div( -+ dceip->underlay_chroma_dmif_size, -+ int_to_fixed(2)); -+ } else if (surface_type[i] == def_underlay422 -+ || surface_type[i] == def_underlay444) { -+ if (results->orthogonal_rotation[i] == false) { -+ results->data_buffer_size[i] = -+ dceip->underlay_luma_dmif_size; -+ } else { -+ results->data_buffer_size[i] = -+ add( -+ dceip->underlay_luma_dmif_size, -+ dceip->underlay_chroma_dmif_size); -+ } -+ } else { -+ if (mode_data->number_of_displays == 1 -+ && equ(dceip->de_tiling_buffer, -+ int_to_fixed(0))) { -+ if (mode_data->d0_fbc_enable) { -+ results->data_buffer_size[i] = -+ mul( -+ dceip->max_dmif_buffer_allocated, -+ dceip->graphics_dmif_size); -+ } else { -+ results->data_buffer_size[i] = -+ mul( -+ mul( -+ max_chunks_non_fbc_mode, -+ pixels_per_chunk), -+ results->bytes_per_pixel[i]); -+ } -+ } else { -+ results->data_buffer_size[i] = -+ dceip->graphics_dmif_size; -+ } -+ } -+ if (surface_type[i] == def_display_write_back420_luma -+ || surface_type[i] -+ == def_display_write_back420_chroma) { -+ results->memory_chunk_size_in_bytes[i] = -+ int_to_fixed(1024); -+ results->pipe_chunk_size_in_bytes[i] = -+ int_to_fixed(1024); -+ } else { -+ results->memory_chunk_size_in_bytes[i] = -+ mul( -+ mul(dceip->chunk_width, -+ results->lines_interleaved_in_mem_access[i]), -+ results->bytes_per_pixel[i]); -+ results->pipe_chunk_size_in_bytes[i] = -+ mul( -+ mul(dceip->chunk_width, -+ dceip->lines_interleaved_into_lb), -+ results->bytes_per_pixel[i]); -+ } -+ } -+ } -+ results->min_dmif_size_in_time = int_to_fixed(9999); -+ results->min_mcifwr_size_in_time = int_to_fixed(9999); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ if (ltn( -+ bw_div( -+ bw_div( -+ mul( -+ results->data_buffer_size[i], -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]), -+ results->display_bandwidth[i]), -+ results->min_dmif_size_in_time)) { -+ results->min_dmif_size_in_time = -+ bw_div( -+ bw_div( -+ mul( -+ results->data_buffer_size[i], -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]), -+ results->display_bandwidth[i]); -+ } -+ } else { -+ if (ltn( -+ bw_div( -+ bw_div( -+ mul( -+ results->data_buffer_size[i], -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]), -+ results->display_bandwidth[i]), -+ results->min_mcifwr_size_in_time)) { -+ results->min_mcifwr_size_in_time = -+ bw_div( -+ bw_div( -+ mul( -+ results->data_buffer_size[i], -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]), -+ results->display_bandwidth[i]); -+ } -+ } -+ } -+ } -+ results->total_requests_for_dmif_size = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i] -+ && surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->total_requests_for_dmif_size = add( -+ results->total_requests_for_dmif_size, -+ bw_div(results->data_buffer_size[i], -+ results->useful_bytes_per_request[i])); -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma -+ && dceip->limit_excessive_outstanding_dmif_requests -+ && (mode_data->number_of_displays > 1 -+ || gtn( -+ results->total_requests_for_dmif_size, -+ dceip->dmif_request_buffer_size))) { -+ results->adjusted_data_buffer_size[i] = -+ bw_min(results->data_buffer_size[i], -+ bw_ceil( -+ mul( -+ results->min_dmif_size_in_time, -+ results->display_bandwidth[i]), -+ results->memory_chunk_size_in_bytes[i])); -+ } else { -+ results->adjusted_data_buffer_size[i] = -+ results->data_buffer_size[i]; -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if ((mode_data->number_of_displays == 1 -+ && equ(results->number_of_underlay_surfaces, -+ int_to_fixed(0)))) { -+ results->outstanding_chunk_request_limit[i] = -+ int_to_fixed(255); -+ } else { -+ results->outstanding_chunk_request_limit[i] = -+ bw_ceil( -+ bw_div( -+ results->adjusted_data_buffer_size[i], -+ results->pipe_chunk_size_in_bytes[i]), -+ int_to_fixed(1)); -+ } -+ } -+ } -+ if (mode_data->number_of_displays > 1 -+ || (neq(mode_data->graphics_rotation_angle, int_to_fixed(0)) -+ && neq(mode_data->graphics_rotation_angle, -+ int_to_fixed(180)))) { -+ results->peak_pte_request_to_eviction_ratio_limiting = -+ dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; -+ } else { -+ results->peak_pte_request_to_eviction_ratio_limiting = -+ dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i] -+ && results->scatter_gather_enable_for_pipe[i] == true) { -+ if (tiling_mode[i] == def_linear) { -+ results->useful_pte_per_pte_request = -+ int_to_fixed(8); -+ results->scatter_gather_page_width[i] = bw_div( -+ int_to_fixed(4096), -+ results->bytes_per_pixel[i]); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(1); -+ results->scatter_gather_pte_request_rows = -+ int_to_fixed(1); -+ results->scatter_gather_row_height = -+ dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode; -+ } else if (equ(results->rotation_angle[i], -+ int_to_fixed(0)) -+ || equ(results->rotation_angle[i], -+ int_to_fixed(180))) { -+ results->useful_pte_per_pte_request = -+ int_to_fixed(8); -+ if (equ(results->bytes_per_pixel[i], -+ int_to_fixed(4))) { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(32); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(32); -+ } else if (equ(results->bytes_per_pixel[i], -+ int_to_fixed(2))) { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(64); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(32); -+ } else { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(64); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(64); -+ } -+ results->scatter_gather_pte_request_rows = -+ dceip->scatter_gather_pte_request_rows_in_tiling_mode; -+ results->scatter_gather_row_height = -+ results->scatter_gather_page_height[i]; -+ } else { -+ results->useful_pte_per_pte_request = -+ int_to_fixed(1); -+ if (equ(results->bytes_per_pixel[i], -+ int_to_fixed(4))) { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(32); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(32); -+ } else if (equ(results->bytes_per_pixel[i], -+ int_to_fixed(2))) { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(32); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(64); -+ } else -+ // case else -+ { -+ results->scatter_gather_page_width[i] = -+ int_to_fixed(64); -+ results->scatter_gather_page_height[i] = -+ int_to_fixed(64); -+ } -+ results->scatter_gather_pte_request_rows = -+ dceip->scatter_gather_pte_request_rows_in_tiling_mode; -+ results->scatter_gather_row_height = -+ results->scatter_gather_page_height[i]; -+ } -+ results->pte_request_per_chunk[i] = bw_div( -+ bw_div(dceip->chunk_width, -+ results->scatter_gather_page_width[i]), -+ results->useful_pte_per_pte_request); -+ results->scatter_gather_pte_requests_in_row[i] = -+ bw_div( -+ mul(results->scatter_gather_row_height, -+ bw_ceil( -+ mul( -+ bw_div( -+ results->source_width_rounded_up_to_chunks[i], -+ dceip->chunk_width), -+ results->pte_request_per_chunk[i]), -+ int_to_fixed(1))), -+ results->scatter_gather_page_height[i]); -+ results->scatter_gather_pte_requests_in_vblank = mul( -+ results->scatter_gather_pte_request_rows, -+ results->scatter_gather_pte_requests_in_row[i]); -+ if (equ( -+ results->peak_pte_request_to_eviction_ratio_limiting, -+ int_to_fixed(0))) { -+ results->scatter_gather_pte_request_limit[i] = -+ results->scatter_gather_pte_requests_in_vblank; -+ } else { -+ results->scatter_gather_pte_request_limit[i] = -+ bw_max( -+ dceip->minimum_outstanding_pte_request_limit, -+ bw_min( -+ results->scatter_gather_pte_requests_in_vblank, -+ bw_ceil( -+ mul( -+ mul( -+ bw_div( -+ bw_ceil( -+ results->adjusted_data_buffer_size[i], -+ results->memory_chunk_size_in_bytes[i]), -+ results->memory_chunk_size_in_bytes[i]), -+ results->pte_request_per_chunk[i]), -+ results->peak_pte_request_to_eviction_ratio_limiting), -+ int_to_fixed( -+ 1)))); -+ } -+ } -+ } -+ results->inefficient_linear_pitch_in_bytes = mul( -+ mul(vbios->number_of_dram_banks, -+ vbios->number_of_dram_channels), int_to_fixed(256)); -+ if (mode_data->underlay_surface_type == yuv_420) { -+ results->inefficient_underlay_pitch_in_pixels = -+ results->inefficient_linear_pitch_in_bytes; -+ } else if (mode_data->underlay_surface_type == yuv_422) { -+ results->inefficient_underlay_pitch_in_pixels = bw_div( -+ results->inefficient_linear_pitch_in_bytes, -+ int_to_fixed(2)); -+ } else -+ // case else -+ { -+ results->inefficient_underlay_pitch_in_pixels = bw_div( -+ results->inefficient_linear_pitch_in_bytes, -+ int_to_fixed(4)); -+ } -+ if (mode_data->underlay_tiling_mode == linear -+ && vbios->scatter_gather_enable == true -+ && mode_data->underlay_pitch_in_pixels.value -+ % results->inefficient_underlay_pitch_in_pixels.value -+ == false) { -+ results->minimum_underlay_pitch_padding_recommended_for_efficiency = -+ int_to_fixed(256); -+ } else { -+ results->minimum_underlay_pitch_padding_recommended_for_efficiency = -+ int_to_fixed(0); -+ } -+ results->cursor_total_data = int_to_fixed(0); -+ results->cursor_total_request_groups = int_to_fixed(0); -+ results->scatter_gather_total_pte_requests = int_to_fixed(0); -+ results->scatter_gather_total_pte_request_groups = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->cursor_total_data = add( -+ results->cursor_total_data, -+ mul(results->cursor_width_pixels[i], -+ int_to_fixed(8))); -+ results->cursor_total_request_groups = add( -+ results->cursor_total_request_groups, -+ bw_ceil( -+ bw_div(results->cursor_width_pixels[i], -+ dceip->cursor_chunk_width), -+ int_to_fixed(1))); -+ if (results->scatter_gather_enable_for_pipe[i]) { -+ results->scatter_gather_total_pte_requests = -+ add( -+ results->scatter_gather_total_pte_requests, -+ results->scatter_gather_pte_request_limit[i]); -+ results->scatter_gather_total_pte_request_groups = -+ add( -+ results->scatter_gather_total_pte_request_groups, -+ bw_ceil( -+ bw_div( -+ results->scatter_gather_pte_request_limit[i], -+ bw_ceil( -+ results->pte_request_per_chunk[i], -+ int_to_fixed( -+ 1))), -+ int_to_fixed(1))); -+ } -+ } -+ } -+ results->tile_width_in_pixels = int_to_fixed(8); -+ results->dmif_total_number_of_data_request_page_close_open = -+ int_to_fixed(0); -+ results->mcifwr_total_number_of_data_request_page_close_open = -+ int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (results->scatter_gather_enable_for_pipe[i] == true -+ && tiling_mode[i] != def_linear) { -+ results->bytes_per_page_close_open = -+ mul( -+ results->lines_interleaved_in_mem_access[i], -+ bw_max( -+ mul( -+ mul( -+ mul( -+ results->bytes_per_pixel[i], -+ results->tile_width_in_pixels), -+ vbios->number_of_dram_banks), -+ vbios->number_of_dram_channels), -+ mul( -+ results->bytes_per_pixel[i], -+ results->scatter_gather_page_width[i]))); -+ } else if (results->scatter_gather_enable_for_pipe[i] -+ == true && tiling_mode[i] == def_linear -+ && (mul( -+ results->pitch_in_pixels_after_surface_type[i], -+ results->bytes_per_pixel[i])).value -+ % results->inefficient_linear_pitch_in_bytes.value -+ == false) { -+ results->bytes_per_page_close_open = -+ dceip->linear_mode_line_request_alternation_slice; -+ } else { -+ results->bytes_per_page_close_open = -+ results->memory_chunk_size_in_bytes[i]; -+ } -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->dmif_total_number_of_data_request_page_close_open = -+ add( -+ results->dmif_total_number_of_data_request_page_close_open, -+ bw_div( -+ bw_ceil( -+ results->adjusted_data_buffer_size[i], -+ results->memory_chunk_size_in_bytes[i]), -+ results->bytes_per_page_close_open)); -+ } else { -+ results->mcifwr_total_number_of_data_request_page_close_open = -+ add( -+ results->mcifwr_total_number_of_data_request_page_close_open, -+ bw_div( -+ bw_ceil( -+ results->adjusted_data_buffer_size[i], -+ results->memory_chunk_size_in_bytes[i]), -+ results->bytes_per_page_close_open)); -+ } -+ } -+ } -+ results->dmif_total_page_close_open_time = -+ bw_div( -+ mul( -+ (add( -+ add( -+ results->dmif_total_number_of_data_request_page_close_open, -+ results->scatter_gather_total_pte_request_groups), -+ results->cursor_total_request_groups)), -+ vbios->trc), int_to_fixed(1000)); -+ results->mcifwr_total_page_close_open_time = -+ bw_div( -+ mul( -+ results->mcifwr_total_number_of_data_request_page_close_open, -+ vbios->trc), int_to_fixed(1000)); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->adjusted_data_buffer_size_in_memory[i] = bw_div( -+ mul(results->adjusted_data_buffer_size[i], -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]); -+ } -+ } -+ results->total_requests_for_adjusted_dmif_size = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->total_requests_for_adjusted_dmif_size = -+ add( -+ results->total_requests_for_adjusted_dmif_size, -+ bw_div( -+ results->adjusted_data_buffer_size[i], -+ results->useful_bytes_per_request[i])); -+ } -+ } -+ } -+ if (equ(dceip->dcfclk_request_generation, int_to_fixed(1))) { -+ results->total_dmifmc_urgent_trips = int_to_fixed(1); -+ } else { -+ results->total_dmifmc_urgent_trips = -+ bw_ceil( -+ bw_div( -+ results->total_requests_for_adjusted_dmif_size, -+ (add(dceip->dmif_request_buffer_size, -+ mul( -+ vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel, -+ vbios->number_of_dram_channels)))), -+ int_to_fixed(1)); -+ } -+ results->total_dmifmc_urgent_latency = mul(vbios->dmifmc_urgent_latency, -+ results->total_dmifmc_urgent_trips); -+ results->total_display_reads_required_data = int_to_fixed(0); -+ results->total_display_reads_required_dram_access_data = int_to_fixed( -+ 0); -+ results->total_display_writes_required_data = int_to_fixed(0); -+ results->total_display_writes_required_dram_access_data = int_to_fixed( -+ 0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->display_reads_required_data = -+ results->adjusted_data_buffer_size_in_memory[i]; -+ results->display_reads_required_dram_access_data = -+ mul( -+ results->adjusted_data_buffer_size_in_memory[i], -+ bw_ceil( -+ bw_div( -+ vbios->dram_channel_width_in_bits, -+ results->bytes_per_request[i]), -+ int_to_fixed(1))); -+ if (results->access_one_channel_only[i]) { -+ results->display_reads_required_dram_access_data = -+ mul( -+ results->display_reads_required_dram_access_data, -+ vbios->number_of_dram_channels); -+ } -+ results->total_display_reads_required_data = -+ add( -+ results->total_display_reads_required_data, -+ results->display_reads_required_data); -+ results->total_display_reads_required_dram_access_data = -+ add( -+ results->total_display_reads_required_dram_access_data, -+ results->display_reads_required_dram_access_data); -+ } else { -+ results->total_display_writes_required_data = -+ add( -+ results->total_display_writes_required_data, -+ results->adjusted_data_buffer_size_in_memory[i]); -+ results->total_display_writes_required_dram_access_data = -+ add( -+ results->total_display_writes_required_dram_access_data, -+ mul( -+ results->adjusted_data_buffer_size_in_memory[i], -+ bw_ceil( -+ bw_div( -+ vbios->dram_channel_width_in_bits, -+ results->bytes_per_request[i]), -+ int_to_fixed( -+ 1)))); -+ } -+ } -+ } -+ results->total_display_reads_required_data = add( -+ add(results->total_display_reads_required_data, -+ results->cursor_total_data), -+ mul(results->scatter_gather_total_pte_requests, -+ int_to_fixed(64))); -+ results->total_display_reads_required_dram_access_data = add( -+ add(results->total_display_reads_required_dram_access_data, -+ results->cursor_total_data), -+ mul(results->scatter_gather_total_pte_requests, -+ int_to_fixed(64))); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (gtn(results->v_filter_init[i], int_to_fixed(4))) { -+ results->src_pixels_for_first_output_pixel[i] = -+ mul( -+ results->source_width_rounded_up_to_chunks[i], -+ int_to_fixed(4)); -+ } else { -+ if (gtn(results->v_filter_init[i], -+ int_to_fixed(2))) { -+ results->src_pixels_for_first_output_pixel[i] = -+ int_to_fixed(512); -+ } else { -+ results->src_pixels_for_first_output_pixel[i] = -+ int_to_fixed(0); -+ } -+ } -+ results->src_data_for_first_output_pixel[i] = -+ bw_div( -+ mul( -+ mul( -+ results->src_pixels_for_first_output_pixel[i], -+ results->bytes_per_pixel[i]), -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]); -+ results->src_pixels_for_last_output_pixel[i] = -+ mul( -+ results->source_width_rounded_up_to_chunks[i], -+ bw_max( -+ bw_ceil( -+ results->v_filter_init[i], -+ dceip->lines_interleaved_into_lb), -+ mul( -+ results->horizontal_blank_and_chunk_granularity_factor[i], -+ bw_ceil(results->vsr[i], -+ dceip->lines_interleaved_into_lb)))); -+ results->src_data_for_last_output_pixel[i] = -+ bw_div( -+ mul( -+ mul( -+ mul( -+ results->source_width_rounded_up_to_chunks[i], -+ bw_max( -+ bw_ceil( -+ results->v_filter_init[i], -+ dceip->lines_interleaved_into_lb), -+ results->lines_interleaved_in_mem_access[i])), -+ results->bytes_per_pixel[i]), -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]); -+ results->active_time[i] = -+ bw_div( -+ bw_div( -+ results->source_width_rounded_up_to_chunks[i], -+ results->hsr[i]), -+ results->pixel_rate[i]); -+ } -+ } -+ for (i = 0; i <= 2; i += 1) { -+ for (j = 0; j <= 2; j += 1) { -+ results->dmif_burst_time[i][j] = -+ bw_max3( -+ results->dmif_total_page_close_open_time, -+ bw_div( -+ results->total_display_reads_required_dram_access_data, -+ (mul( -+ bw_div( -+ mul(yclk[i], -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed( -+ 8)), -+ vbios->number_of_dram_channels))), -+ bw_div( -+ results->total_display_reads_required_data, -+ (mul(sclk[j], -+ vbios->data_return_bus_width)))); -+ if (mode_data->d1_display_write_back_dwb_enable -+ == true) { -+ results->mcifwr_burst_time[i][j] = -+ bw_max3( -+ results->mcifwr_total_page_close_open_time, -+ bw_div( -+ results->total_display_writes_required_dram_access_data, -+ (mul( -+ bw_div( -+ mul( -+ yclk[i], -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed( -+ 8)), -+ vbios->number_of_dram_channels))), -+ bw_div( -+ results->total_display_writes_required_data, -+ (mul(sclk[j], -+ vbios->data_return_bus_width)))); -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ for (j = 0; j <= 2; j += 1) { -+ for (k = 0; k <= 2; k += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] -+ != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->line_source_transfer_time[i][j][k] = -+ bw_max( -+ mul( -+ (add( -+ results->total_dmifmc_urgent_latency, -+ results->dmif_burst_time[j][k])), -+ bw_floor( -+ bw_div( -+ results->src_data_for_first_output_pixel[i], -+ results->adjusted_data_buffer_size_in_memory[i]), -+ int_to_fixed( -+ 1))), -+ sub( -+ mul( -+ (add( -+ results->total_dmifmc_urgent_latency, -+ results->dmif_burst_time[j][k])), -+ bw_floor( -+ bw_div( -+ results->src_data_for_last_output_pixel[i], -+ results->adjusted_data_buffer_size_in_memory[i]), -+ int_to_fixed( -+ 1))), -+ results->active_time[i])); -+ } else { -+ results->line_source_transfer_time[i][j][k] = -+ bw_max( -+ mul( -+ (add( -+ vbios->mcifwrmc_urgent_latency, -+ results->mcifwr_burst_time[j][k])), -+ bw_floor( -+ bw_div( -+ results->src_data_for_first_output_pixel[i], -+ results->adjusted_data_buffer_size_in_memory[i]), -+ int_to_fixed( -+ 1))), -+ sub( -+ mul( -+ (add( -+ vbios->mcifwrmc_urgent_latency, -+ results->mcifwr_burst_time[j][k])), -+ bw_floor( -+ bw_div( -+ results->src_data_for_last_output_pixel[i], -+ results->adjusted_data_buffer_size_in_memory[i]), -+ int_to_fixed( -+ 1))), -+ results->active_time[i])); -+ } -+ } -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (equ( -+ dceip->stutter_and_dram_clock_state_change_gated_before_cursor, -+ int_to_fixed(0)) -+ && gtn(results->cursor_width_pixels[i], -+ int_to_fixed(0))) { -+ if (ltn(results->vsr[i], int_to_fixed(2))) { -+ results->cursor_latency_hiding[i] = -+ bw_div( -+ bw_div( -+ mul( -+ (sub( -+ dceip->cursor_dcp_buffer_lines, -+ int_to_fixed( -+ 1))), -+ results->h_total[i]), -+ results->vsr[i]), -+ results->pixel_rate[i]); -+ } else { -+ results->cursor_latency_hiding[i] = -+ bw_div( -+ bw_div( -+ mul( -+ (sub( -+ dceip->cursor_dcp_buffer_lines, -+ int_to_fixed( -+ 3))), -+ results->h_total[i]), -+ results->vsr[i]), -+ results->pixel_rate[i]); -+ } -+ } else { -+ results->cursor_latency_hiding[i] = -+ int_to_fixed(9999); -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (dceip->graphics_lb_nodownscaling_multi_line_prefetching -+ == true -+ && (equ(results->vsr[i], int_to_fixed(1)) -+ || (leq(results->vsr[i], -+ frc_to_fixed(8, 10)) -+ && leq(results->v_taps[i], -+ int_to_fixed(2)) -+ && equ(results->lb_bpc[i], -+ int_to_fixed(8)))) -+ && surface_type[i] == def_graphics) { -+ results->minimum_latency_hiding[i] = -+ sub( -+ sub( -+ add( -+ bw_div( -+ mul( -+ bw_div( -+ (bw_div( -+ bw_div( -+ results->data_buffer_size[i], -+ results->bytes_per_pixel[i]), -+ results->source_width_pixels[i])), -+ results->vsr[i]), -+ results->h_total[i]), -+ results->pixel_rate[i]), -+ results->lb_partitions[i]), -+ int_to_fixed(1)), -+ results->total_dmifmc_urgent_latency); -+ } else { -+ results->minimum_latency_hiding[i] = -+ sub( -+ bw_div( -+ mul( -+ (add( -+ add( -+ results->line_buffer_prefetch[i], -+ int_to_fixed( -+ 1)), -+ bw_div( -+ bw_div( -+ bw_div( -+ results->data_buffer_size[i], -+ results->bytes_per_pixel[i]), -+ results->source_width_pixels[i]), -+ results->vsr[i]))), -+ results->h_total[i]), -+ results->pixel_rate[i]), -+ results->total_dmifmc_urgent_latency); -+ } -+ results->minimum_latency_hiding_with_cursor[i] = bw_min( -+ results->minimum_latency_hiding[i], -+ results->cursor_latency_hiding[i]); -+ } -+ } -+ for (i = 0; i <= 2; i += 1) { -+ for (j = 0; j <= 2; j += 1) { -+ results->blackout_duration_margin[i][j] = int_to_fixed( -+ 9999); -+ results->dispclk_required_for_blackout_duration[i][j] = -+ int_to_fixed(0); -+ results->dispclk_required_for_blackout_recovery[i][j] = -+ int_to_fixed(0); -+ for (k = 0; k <= maximum_number_of_surfaces - 1; k += -+ 1) { -+ if (results->enable[k] -+ && gtn(vbios->blackout_duration, -+ int_to_fixed(0))) { -+ if (surface_type[k] -+ != def_display_write_back420_luma -+ && surface_type[k] -+ != def_display_write_back420_chroma) { -+ results->blackout_duration_margin[i][j] = -+ bw_min( -+ results->blackout_duration_margin[i][j], -+ sub( -+ sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]), -+ results->line_source_transfer_time[k][i][j])); -+ results->dispclk_required_for_blackout_duration[i][j] = -+ bw_max3( -+ results->dispclk_required_for_blackout_duration[i][j], -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_first_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]))), -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_last_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (add( -+ sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]), -+ results->active_time[k])))); -+ if (leq( -+ vbios->maximum_blackout_recovery_time, -+ add( -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[i][j]))) { -+ results->dispclk_required_for_blackout_recovery[i][j] = -+ int_to_fixed( -+ 9999); -+ } else if (ltn( -+ results->adjusted_data_buffer_size[k], -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ add( -+ vbios->blackout_duration, -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2))), -+ results->dmif_burst_time[i][j]))))) { -+ results->dispclk_required_for_blackout_recovery[i][j] = -+ bw_max( -+ results->dispclk_required_for_blackout_recovery[i][j], -+ bw_div( -+ mul( -+ bw_div( -+ bw_div( -+ (sub( -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ vbios->blackout_duration, -+ vbios->maximum_blackout_recovery_time))), -+ results->adjusted_data_buffer_size[k])), -+ results->bytes_per_pixel[k]), -+ (sub( -+ sub( -+ vbios->maximum_blackout_recovery_time, -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2))), -+ results->dmif_burst_time[i][j]))), -+ results->latency_hiding_lines[k]), -+ results->lines_interleaved_in_mem_access[k])); -+ } -+ } else { -+ results->blackout_duration_margin[i][j] = -+ bw_min( -+ results->blackout_duration_margin[i][j], -+ sub( -+ sub( -+ sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]), -+ results->line_source_transfer_time[k][i][j])); -+ results->dispclk_required_for_blackout_duration[i][j] = -+ bw_max3( -+ results->dispclk_required_for_blackout_duration[i][j], -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_first_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (sub( -+ sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]))), -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_last_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (add( -+ sub( -+ sub( -+ sub( -+ results->minimum_latency_hiding_with_cursor[k], -+ vbios->blackout_duration), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]), -+ results->active_time[k])))); -+ if (ltn( -+ vbios->maximum_blackout_recovery_time, -+ add( -+ add( -+ mul( -+ vbios->mcifwrmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]))) { -+ results->dispclk_required_for_blackout_recovery[i][j] = -+ int_to_fixed( -+ 9999); -+ } else if (ltn( -+ results->adjusted_data_buffer_size[k], -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ add( -+ vbios->blackout_duration, -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2))), -+ results->dmif_burst_time[i][j]))))) { -+ results->dispclk_required_for_blackout_recovery[i][j] = -+ bw_max( -+ results->dispclk_required_for_blackout_recovery[i][j], -+ bw_div( -+ mul( -+ bw_div( -+ bw_div( -+ (sub( -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ vbios->blackout_duration, -+ vbios->maximum_blackout_recovery_time))), -+ results->adjusted_data_buffer_size[k])), -+ results->bytes_per_pixel[k]), -+ (sub( -+ vbios->maximum_blackout_recovery_time, -+ (add( -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[i][j]))))), -+ results->latency_hiding_lines[k]), -+ results->lines_interleaved_in_mem_access[k])); -+ } -+ } -+ } -+ } -+ } -+ } -+ if (gtn(results->blackout_duration_margin[high][high], int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[high][high], -+ vbios->high_voltage_max_dispclk)) { -+ results->cpup_state_change_enable = true; -+ if (ltn( -+ results->dispclk_required_for_blackout_recovery[high][high], -+ vbios->high_voltage_max_dispclk)) { -+ results->cpuc_state_change_enable = true; -+ } else { -+ results->cpuc_state_change_enable = false; -+ } -+ } else { -+ results->cpup_state_change_enable = false; -+ results->cpuc_state_change_enable = false; -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (mode_data->number_of_displays <= 1 -+ || mode_data->display_synchronization_enabled -+ == true) { -+ results->maximum_latency_hiding[i] = -+ int_to_fixed(450); -+ } else { -+ results->maximum_latency_hiding[i] = -+ add( -+ add( -+ results->minimum_latency_hiding[i], -+ bw_div( -+ mul( -+ bw_div( -+ int_to_fixed( -+ 1), -+ results->vsr[i]), -+ results->h_total[i]), -+ results->pixel_rate[i])), -+ mul(frc_to_fixed(1, 2), -+ results->total_dmifmc_urgent_latency)); -+ } -+ results->maximum_latency_hiding_with_cursor[i] = bw_min( -+ results->maximum_latency_hiding[i], -+ results->cursor_latency_hiding[i]); -+ } -+ } -+ for (i = 0; i <= 2; i += 1) { -+ for (j = 0; j <= 2; j += 1) { -+ results->dram_speed_change_margin[i][j] = int_to_fixed( -+ 9999); -+ results->dispclk_required_for_dram_speed_change[i][j] = -+ int_to_fixed(0); -+ for (k = 0; k <= maximum_number_of_surfaces - 1; k += -+ 1) { -+ if (results->enable[k]) { -+ if (surface_type[k] -+ != def_display_write_back420_luma -+ && surface_type[k] -+ != def_display_write_back420_chroma) { -+ results->dram_speed_change_margin[i][j] = -+ bw_min( -+ results->dram_speed_change_margin[i][j], -+ sub( -+ sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]), -+ results->line_source_transfer_time[k][i][j])); -+ results->dispclk_required_for_dram_speed_change[i][j] = -+ bw_max3( -+ results->dispclk_required_for_dram_speed_change[i][j], -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_first_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]))), -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_last_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (add( -+ sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]), -+ results->active_time[k])))); -+ } else { -+ results->dram_speed_change_margin[i][j] = -+ bw_min( -+ results->dram_speed_change_margin[i][j], -+ sub( -+ sub( -+ sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]), -+ results->line_source_transfer_time[k][i][j])); -+ results->dispclk_required_for_dram_speed_change[i][j] = -+ bw_max3( -+ results->dispclk_required_for_dram_speed_change[i][j], -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_first_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (sub( -+ sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]))), -+ bw_div( -+ bw_div( -+ mul( -+ results->src_pixels_for_last_output_pixel[k], -+ dceip->display_pipe_throughput_factor), -+ dceip->lb_write_pixels_per_dispclk), -+ (add( -+ sub( -+ sub( -+ sub( -+ results->maximum_latency_hiding_with_cursor[k], -+ vbios->nbp_state_change_latency), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[i][j]), -+ results->active_time[k])))); -+ } -+ } -+ } -+ } -+ } -+ if (gtn(results->dram_speed_change_margin[high][high], int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_dram_speed_change[high][high], -+ vbios->high_voltage_max_dispclk)) { -+ results->nbp_state_change_enable = true; -+ } else { -+ results->nbp_state_change_enable = false; -+ } -+ results->min_cursor_memory_interface_buffer_size_in_time = int_to_fixed( -+ 9999); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (gtn(results->cursor_width_pixels[i], -+ int_to_fixed(0))) { -+ results->min_cursor_memory_interface_buffer_size_in_time = -+ bw_min( -+ results->min_cursor_memory_interface_buffer_size_in_time, -+ bw_div( -+ mul( -+ bw_div( -+ bw_div( -+ dceip->cursor_memory_interface_buffer_pixels, -+ results->cursor_width_pixels[i]), -+ results->vsr[i]), -+ results->h_total[i]), -+ results->pixel_rate[i])); -+ } -+ } -+ } -+ results->min_read_buffer_size_in_time = bw_min( -+ results->min_cursor_memory_interface_buffer_size_in_time, -+ results->min_dmif_size_in_time); -+ results->display_reads_time_for_data_transfer = sub( -+ results->min_read_buffer_size_in_time, -+ results->total_dmifmc_urgent_latency); -+ results->display_writes_time_for_data_transfer = sub( -+ results->min_mcifwr_size_in_time, -+ vbios->mcifwrmc_urgent_latency); -+ results->dmif_required_dram_bandwidth = bw_div( -+ results->total_display_reads_required_dram_access_data, -+ results->display_reads_time_for_data_transfer); -+ results->mcifwr_required_dram_bandwidth = bw_div( -+ results->total_display_writes_required_dram_access_data, -+ results->display_writes_time_for_data_transfer); -+ results->required_dmifmc_urgent_latency_for_page_close_open = bw_div( -+ (sub(results->min_read_buffer_size_in_time, -+ results->dmif_total_page_close_open_time)), -+ results->total_dmifmc_urgent_trips); -+ results->required_mcifmcwr_urgent_latency = sub( -+ results->min_mcifwr_size_in_time, -+ results->mcifwr_total_page_close_open_time); -+ if (gtn(results->scatter_gather_total_pte_requests, -+ dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { -+ results->required_dram_bandwidth_gbyte_per_second = -+ int_to_fixed(9999); -+ yclk_message = -+ def_exceeded_allowed_outstanding_pte_req_queue_size; -+ y_clk_level = high; -+ results->dram_bandwidth = mul( -+ bw_div( -+ mul(vbios->high_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels); -+ } else if (gtn(vbios->dmifmc_urgent_latency, -+ results->required_dmifmc_urgent_latency_for_page_close_open) -+ || gtn(vbios->mcifwrmc_urgent_latency, -+ results->required_mcifmcwr_urgent_latency)) { -+ results->required_dram_bandwidth_gbyte_per_second = -+ int_to_fixed(9999); -+ yclk_message = def_exceeded_allowed_page_close_open; -+ y_clk_level = high; -+ results->dram_bandwidth = mul( -+ bw_div( -+ mul(vbios->high_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels); -+ } else { -+ results->required_dram_bandwidth_gbyte_per_second = bw_div( -+ bw_max(results->dmif_required_dram_bandwidth, -+ results->mcifwr_required_dram_bandwidth), -+ int_to_fixed(1000)); -+ if (ltn( -+ mul(results->required_dram_bandwidth_gbyte_per_second, -+ int_to_fixed(1000)), -+ mul( -+ bw_div( -+ mul(vbios->low_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels)) -+ && (results->cpup_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[low][high], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[low][high], -+ vbios->high_voltage_max_dispclk))) -+ && (results->cpuc_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[low][high], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[low][high], -+ vbios->high_voltage_max_dispclk) -+ && ltn( -+ results->dispclk_required_for_blackout_recovery[low][high], -+ vbios->high_voltage_max_dispclk))) -+ && gtn(results->dram_speed_change_margin[low][high], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_dram_speed_change[low][high], -+ vbios->high_voltage_max_dispclk)) { -+ yclk_message = def_low; -+ y_clk_level = low; -+ results->dram_bandwidth = -+ mul( -+ bw_div( -+ mul(vbios->low_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels); -+ } else if (ltn( -+ mul(results->required_dram_bandwidth_gbyte_per_second, -+ int_to_fixed(1000)), -+ mul( -+ bw_div( -+ mul(vbios->high_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels))) { -+ yclk_message = def_high; -+ y_clk_level = high; -+ results->dram_bandwidth = -+ mul( -+ bw_div( -+ mul(vbios->high_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels); -+ } else { -+ yclk_message = def_exceeded_allowed_maximum_bw; -+ y_clk_level = high; -+ results->dram_bandwidth = -+ mul( -+ bw_div( -+ mul(vbios->high_yclk, -+ vbios->dram_channel_width_in_bits), -+ int_to_fixed(8)), -+ vbios->number_of_dram_channels); -+ } -+ } -+ results->dmif_required_sclk = bw_div( -+ bw_div(results->total_display_reads_required_data, -+ results->display_reads_time_for_data_transfer), -+ vbios->data_return_bus_width); -+ results->mcifwr_required_sclk = bw_div( -+ bw_div(results->total_display_writes_required_data, -+ results->display_writes_time_for_data_transfer), -+ vbios->data_return_bus_width); -+ if (gtn(results->scatter_gather_total_pte_requests, -+ dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { -+ results->required_sclk = int_to_fixed(9999); -+ sclk_message = -+ def_exceeded_allowed_outstanding_pte_req_queue_size; -+ sclk_level = high; -+ } else if (gtn(vbios->dmifmc_urgent_latency, -+ results->required_dmifmc_urgent_latency_for_page_close_open) -+ || gtn(vbios->mcifwrmc_urgent_latency, -+ results->required_mcifmcwr_urgent_latency)) { -+ results->required_sclk = int_to_fixed(9999); -+ sclk_message = def_exceeded_allowed_page_close_open; -+ sclk_level = high; -+ } else { -+ results->required_sclk = bw_max(results->dmif_required_sclk, -+ results->mcifwr_required_sclk); -+ if (ltn(results->required_sclk, vbios->low_sclk) -+ && (results->cpup_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[y_clk_level][low], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[y_clk_level][low], -+ vbios->high_voltage_max_dispclk))) -+ && (results->cpuc_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[y_clk_level][low], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[y_clk_level][low], -+ vbios->high_voltage_max_dispclk) -+ && ltn( -+ results->dispclk_required_for_blackout_recovery[y_clk_level][low], -+ vbios->high_voltage_max_dispclk))) -+ && (results->nbp_state_change_enable == false -+ || (gtn( -+ results->dram_speed_change_margin[y_clk_level][low], -+ int_to_fixed(0)) -+ && leq( -+ results->dispclk_required_for_dram_speed_change[y_clk_level][low], -+ vbios->high_voltage_max_dispclk)))) { -+ sclk_message = def_low; -+ sclk_level = low; -+ } else if (ltn(results->required_sclk, vbios->mid_sclk) -+ && (results->cpup_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[y_clk_level][mid], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[y_clk_level][mid], -+ vbios->high_voltage_max_dispclk))) -+ && (results->cpuc_state_change_enable == false -+ || (gtn( -+ results->blackout_duration_margin[y_clk_level][mid], -+ int_to_fixed(0)) -+ && ltn( -+ results->dispclk_required_for_blackout_duration[y_clk_level][mid], -+ vbios->high_voltage_max_dispclk) -+ && ltn( -+ results->dispclk_required_for_blackout_recovery[y_clk_level][mid], -+ vbios->high_voltage_max_dispclk))) -+ && (results->nbp_state_change_enable == false -+ || (gtn( -+ results->dram_speed_change_margin[y_clk_level][mid], -+ int_to_fixed(0)) -+ && leq( -+ results->dispclk_required_for_dram_speed_change[y_clk_level][mid], -+ vbios->high_voltage_max_dispclk)))) { -+ sclk_message = def_mid; -+ sclk_level = mid; -+ } else if (ltn(results->required_sclk, vbios->high_sclk)) { -+ sclk_message = def_high; -+ sclk_level = high; -+ } else { -+ sclk_message = def_exceeded_allowed_maximum_sclk; -+ sclk_level = high; -+ } -+ } -+ results->downspread_factor = add( -+ bw_div(vbios->down_spread_percentage, int_to_fixed(100)), -+ int_to_fixed(1)); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] == def_graphics) { -+ if (equ(results->lb_bpc[i], int_to_fixed(6))) { -+ results->v_scaler_efficiency = -+ dceip->graphics_vscaler_efficiency6_bit_per_component; -+ } else if (equ(results->lb_bpc[i], -+ int_to_fixed(8))) { -+ results->v_scaler_efficiency = -+ dceip->graphics_vscaler_efficiency8_bit_per_component; -+ } else if (equ(results->lb_bpc[i], -+ int_to_fixed(10))) { -+ results->v_scaler_efficiency = -+ dceip->graphics_vscaler_efficiency10_bit_per_component; -+ } else { -+ results->v_scaler_efficiency = -+ dceip->graphics_vscaler_efficiency12_bit_per_component; -+ } -+ if (results->use_alpha[i] == true) { -+ results->v_scaler_efficiency = -+ bw_min( -+ results->v_scaler_efficiency, -+ dceip->alpha_vscaler_efficiency); -+ } -+ } else { -+ if (equ(results->lb_bpc[i], int_to_fixed(6))) { -+ results->v_scaler_efficiency = -+ dceip->underlay_vscaler_efficiency6_bit_per_component; -+ } else if (equ(results->lb_bpc[i], -+ int_to_fixed(8))) { -+ results->v_scaler_efficiency = -+ dceip->underlay_vscaler_efficiency8_bit_per_component; -+ } else if (equ(results->lb_bpc[i], -+ int_to_fixed(10))) { -+ results->v_scaler_efficiency = -+ dceip->underlay_vscaler_efficiency10_bit_per_component; -+ } else { -+ results->v_scaler_efficiency = -+ dceip->underlay_vscaler_efficiency12_bit_per_component; -+ } -+ } -+ if (dceip->pre_downscaler_enabled -+ && gtn(results->hsr[i], int_to_fixed(1))) { -+ results->scaler_limits_factor = -+ bw_max( -+ bw_div(results->v_taps[i], -+ results->v_scaler_efficiency), -+ bw_div( -+ results->source_width_rounded_up_to_chunks[i], -+ results->h_total[i])); -+ } else { -+ results->scaler_limits_factor = -+ bw_max3(int_to_fixed(1), -+ bw_ceil( -+ bw_div(results->h_taps[i], -+ int_to_fixed( -+ 4)), -+ int_to_fixed(1)), -+ mul(results->hsr[i], -+ bw_max( -+ bw_div( -+ results->v_taps[i], -+ results->v_scaler_efficiency), -+ int_to_fixed( -+ 1)))); -+ } -+ results->display_pipe_pixel_throughput = -+ bw_div( -+ bw_div( -+ mul( -+ bw_max( -+ results->lb_lines_in_per_line_out_in_beginning_of_frame[i], -+ mul( -+ results->lb_lines_in_per_line_out_in_middle_of_frame[i], -+ results->horizontal_blank_and_chunk_granularity_factor[i])), -+ results->source_width_rounded_up_to_chunks[i]), -+ (bw_div(results->h_total[i], -+ results->pixel_rate[i]))), -+ dceip->lb_write_pixels_per_dispclk); -+ results->dispclk_required_without_ramping[i] = -+ mul(results->downspread_factor, -+ bw_max( -+ mul(results->pixel_rate[i], -+ results->scaler_limits_factor), -+ mul( -+ dceip->display_pipe_throughput_factor, -+ results->display_pipe_pixel_throughput))); -+ results->dispclk_required_with_ramping[i] = -+ mul(dceip->dispclk_ramping_factor, -+ bw_max( -+ mul(results->pixel_rate[i], -+ results->scaler_limits_factor), -+ results->display_pipe_pixel_throughput)); -+ } -+ } -+ results->total_dispclk_required_with_ramping = int_to_fixed(0); -+ results->total_dispclk_required_without_ramping = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (ltn(results->total_dispclk_required_with_ramping, -+ results->dispclk_required_with_ramping[i])) { -+ results->total_dispclk_required_with_ramping = -+ results->dispclk_required_with_ramping[i]; -+ } -+ if (ltn(results->total_dispclk_required_without_ramping, -+ results->dispclk_required_without_ramping[i])) { -+ results->total_dispclk_required_without_ramping = -+ results->dispclk_required_without_ramping[i]; -+ } -+ } -+ } -+ results->total_read_request_bandwidth = int_to_fixed(0); -+ results->total_write_request_bandwidth = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->total_read_request_bandwidth = add( -+ results->total_read_request_bandwidth, -+ results->request_bandwidth[i]); -+ } else { -+ results->total_write_request_bandwidth = add( -+ results->total_write_request_bandwidth, -+ results->request_bandwidth[i]); -+ } -+ } -+ } -+ results->dispclk_required_for_total_read_request_bandwidth = bw_div( -+ mul(results->total_read_request_bandwidth, -+ dceip->dispclk_per_request), dceip->request_efficiency); -+ if (equ(dceip->dcfclk_request_generation, int_to_fixed(0))) { -+ results->total_dispclk_required_with_ramping_with_request_bandwidth = -+ bw_max(results->total_dispclk_required_with_ramping, -+ results->dispclk_required_for_total_read_request_bandwidth); -+ results->total_dispclk_required_without_ramping_with_request_bandwidth = -+ bw_max(results->total_dispclk_required_without_ramping, -+ results->dispclk_required_for_total_read_request_bandwidth); -+ } else { -+ results->total_dispclk_required_with_ramping_with_request_bandwidth = -+ results->total_dispclk_required_with_ramping; -+ results->total_dispclk_required_without_ramping_with_request_bandwidth = -+ results->total_dispclk_required_without_ramping; -+ } -+ if (results->cpuc_state_change_enable == true) { -+ results->total_dispclk_required_with_ramping_with_request_bandwidth = -+ bw_max3( -+ results->total_dispclk_required_with_ramping_with_request_bandwidth, -+ results->dispclk_required_for_blackout_duration[y_clk_level][sclk_level], -+ results->dispclk_required_for_blackout_recovery[y_clk_level][sclk_level]); -+ results->total_dispclk_required_without_ramping_with_request_bandwidth = -+ bw_max3( -+ results->total_dispclk_required_without_ramping_with_request_bandwidth, -+ results->dispclk_required_for_blackout_duration[y_clk_level][sclk_level], -+ results->dispclk_required_for_blackout_recovery[y_clk_level][sclk_level]); -+ } -+ if (results->cpup_state_change_enable == true) { -+ results->total_dispclk_required_with_ramping_with_request_bandwidth = -+ bw_max( -+ results->total_dispclk_required_with_ramping_with_request_bandwidth, -+ results->dispclk_required_for_blackout_duration[y_clk_level][sclk_level]); -+ results->total_dispclk_required_without_ramping_with_request_bandwidth = -+ bw_max( -+ results->total_dispclk_required_without_ramping_with_request_bandwidth, -+ results->dispclk_required_for_blackout_duration[y_clk_level][sclk_level]); -+ } -+ if (results->nbp_state_change_enable == true) { -+ results->total_dispclk_required_with_ramping_with_request_bandwidth = -+ bw_max( -+ results->total_dispclk_required_with_ramping_with_request_bandwidth, -+ results->dispclk_required_for_dram_speed_change[y_clk_level][sclk_level]); -+ results->total_dispclk_required_without_ramping_with_request_bandwidth = -+ bw_max( -+ results->total_dispclk_required_without_ramping_with_request_bandwidth, -+ results->dispclk_required_for_dram_speed_change[y_clk_level][sclk_level]); -+ } -+ if (ltn( -+ results->total_dispclk_required_with_ramping_with_request_bandwidth, -+ vbios->high_voltage_max_dispclk)) { -+ results->dispclk = -+ results->total_dispclk_required_with_ramping_with_request_bandwidth; -+ } else if (ltn( -+ results->total_dispclk_required_without_ramping_with_request_bandwidth, -+ vbios->high_voltage_max_dispclk)) { -+ results->dispclk = vbios->high_voltage_max_dispclk; -+ } else { -+ results->dispclk = -+ results->total_dispclk_required_without_ramping_with_request_bandwidth; -+ } -+ if (pipe_check == def_notok) { -+ voltage = def_na; -+ mode_background_color = def_na_color; -+ mode_font_color = def_vb_white; -+ } else if (mode_check == def_notok) { -+ voltage = def_notok; -+ mode_background_color = def_notok_color; -+ mode_font_color = def_vb_black; -+ } else if (yclk_message == def_low && sclk_message == def_low -+ && ltn(results->dispclk, vbios->low_voltage_max_dispclk)) { -+ voltage = def_low; -+ mode_background_color = def_low_color; -+ mode_font_color = def_vb_black; -+ } else if (yclk_message == def_low -+ && (sclk_message == def_low || sclk_message == def_mid) -+ && ltn(results->dispclk, vbios->mid_voltage_max_dispclk)) { -+ voltage = def_mid; -+ mode_background_color = def_mid_color; -+ mode_font_color = def_vb_black; -+ } else if ((yclk_message == def_low || yclk_message == def_high) -+ && (sclk_message == def_low || sclk_message == def_mid -+ || sclk_message == def_high) -+ && leq(results->dispclk, vbios->high_voltage_max_dispclk)) { -+ if (results->nbp_state_change_enable == true) { -+ voltage = def_high; -+ mode_background_color = def_high_color; -+ mode_font_color = def_vb_black; -+ } else { -+ voltage = def_high_no_nbp_state_change; -+ mode_background_color = -+ def_high_no_nbp_state_change_color; -+ mode_font_color = def_vb_black; -+ } -+ } else { -+ voltage = def_notok; -+ mode_background_color = def_notok_color; -+ mode_font_color = def_vb_black; -+ } -+ if (mode_background_color == def_na_color -+ || mode_background_color == def_notok_color) { -+ mode_pattern = def_xl_pattern_solid; -+ } else if (results->cpup_state_change_enable == false) { -+ mode_pattern = def_xl_pattern_checker; -+ } else if (results->cpuc_state_change_enable == false) { -+ mode_pattern = def_xl_pattern_light_horizontal; -+ } else { -+ mode_pattern = def_xl_pattern_solid; -+ } -+ results->blackout_recovery_time = int_to_fixed(0); -+ for (k = 0; k <= maximum_number_of_surfaces - 1; k += 1) { -+ if (results->enable[k] -+ && gtn(vbios->blackout_duration, int_to_fixed(0)) -+ && results->cpup_state_change_enable == true) { -+ if (surface_type[k] != def_display_write_back420_luma -+ && surface_type[k] -+ != def_display_write_back420_chroma) { -+ results->blackout_recovery_time = -+ bw_max(results->blackout_recovery_time, -+ add( -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[y_clk_level][sclk_level])); -+ if (ltn(results->adjusted_data_buffer_size[k], -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ add( -+ vbios->blackout_duration, -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2))), -+ results->dmif_burst_time[y_clk_level][sclk_level]))))) { -+ results->blackout_recovery_time = -+ bw_max( -+ results->blackout_recovery_time, -+ bw_div( -+ (sub( -+ add( -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ vbios->blackout_duration), -+ bw_div( -+ mul( -+ mul( -+ mul( -+ (add( -+ mul( -+ results->total_dmifmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[y_clk_level][sclk_level])), -+ results->dispclk), -+ results->bytes_per_pixel[k]), -+ results->lines_interleaved_in_mem_access[k]), -+ results->latency_hiding_lines[k])), -+ results->adjusted_data_buffer_size[k])), -+ (sub( -+ bw_div( -+ mul( -+ mul( -+ results->dispclk, -+ results->bytes_per_pixel[k]), -+ results->lines_interleaved_in_mem_access[k]), -+ results->latency_hiding_lines[k]), -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]))))); -+ } -+ } else { -+ results->blackout_recovery_time = -+ bw_max(results->blackout_recovery_time, -+ add( -+ mul( -+ vbios->mcifwrmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->mcifwr_burst_time[y_clk_level][sclk_level])); -+ if (ltn(results->adjusted_data_buffer_size[k], -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ (add( -+ add( -+ vbios->blackout_duration, -+ mul( -+ vbios->mcifwrmc_urgent_latency, -+ int_to_fixed( -+ 2))), -+ results->mcifwr_burst_time[y_clk_level][sclk_level]))))) { -+ results->blackout_recovery_time = -+ bw_max( -+ results->blackout_recovery_time, -+ bw_div( -+ (sub( -+ add( -+ mul( -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]), -+ vbios->blackout_duration), -+ bw_div( -+ mul( -+ mul( -+ mul( -+ (add( -+ add( -+ mul( -+ vbios->mcifwrmc_urgent_latency, -+ int_to_fixed( -+ 2)), -+ results->dmif_burst_time[i][j]), -+ results->mcifwr_burst_time[y_clk_level][sclk_level])), -+ results->dispclk), -+ results->bytes_per_pixel[k]), -+ results->lines_interleaved_in_mem_access[k]), -+ results->latency_hiding_lines[k])), -+ results->adjusted_data_buffer_size[k])), -+ (sub( -+ bw_div( -+ mul( -+ mul( -+ results->dispclk, -+ results->bytes_per_pixel[k]), -+ results->lines_interleaved_in_mem_access[k]), -+ results->latency_hiding_lines[k]), -+ bw_div( -+ mul( -+ results->display_bandwidth[k], -+ results->useful_bytes_per_request[k]), -+ results->bytes_per_request[k]))))); -+ } -+ } -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (surface_type[i] == def_display_write_back420_luma -+ || surface_type[i] -+ == def_display_write_back420_chroma) { -+ results->pixels_per_data_fifo_entry[i] = -+ int_to_fixed(16); -+ } else if (surface_type[i] == def_graphics) { -+ results->pixels_per_data_fifo_entry[i] = bw_div( -+ int_to_fixed(64), -+ results->bytes_per_pixel[i]); -+ } else if (results->orthogonal_rotation[i] == false) { -+ results->pixels_per_data_fifo_entry[i] = -+ int_to_fixed(16); -+ } else { -+ results->pixels_per_data_fifo_entry[i] = bw_div( -+ int_to_fixed(16), -+ results->bytes_per_pixel[i]); -+ } -+ } -+ } -+ results->min_pixels_per_data_fifo_entry = int_to_fixed(9999); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (gtn(results->min_pixels_per_data_fifo_entry, -+ results->pixels_per_data_fifo_entry[i])) { -+ results->min_pixels_per_data_fifo_entry = -+ results->pixels_per_data_fifo_entry[i]; -+ } -+ } -+ } -+ results->sclk_deep_sleep = bw_max( -+ bw_div(mul(results->dispclk, frc_to_fixed(115, 100)), -+ results->min_pixels_per_data_fifo_entry), -+ results->total_read_request_bandwidth); -+ results->chunk_request_time = int_to_fixed(0); -+ results->cursor_request_time = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->chunk_request_time = -+ add(results->chunk_request_time, -+ bw_div( -+ bw_div( -+ mul(pixels_per_chunk, -+ results->bytes_per_pixel[i]), -+ results->useful_bytes_per_request[i]), -+ bw_min(sclk[sclk_level], -+ bw_div(results->dispclk, -+ int_to_fixed( -+ 2))))); -+ } -+ } -+ results->cursor_request_time = (bw_div(results->cursor_total_data, -+ (mul(sclk[sclk_level], int_to_fixed(32))))); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->line_source_pixels_transfer_time = -+ bw_max( -+ bw_div( -+ bw_div( -+ results->src_pixels_for_first_output_pixel[i], -+ dceip->lb_write_pixels_per_dispclk), -+ (bw_div(results->dispclk, -+ dceip->display_pipe_throughput_factor))), -+ sub( -+ bw_div( -+ bw_div( -+ results->src_pixels_for_last_output_pixel[i], -+ dceip->lb_write_pixels_per_dispclk), -+ (bw_div(results->dispclk, -+ dceip->display_pipe_throughput_factor))), -+ results->active_time[i])); -+ if (surface_type[i] != def_display_write_back420_luma -+ && surface_type[i] -+ != def_display_write_back420_chroma) { -+ results->urgent_watermark[i] = -+ add( -+ add( -+ add( -+ add( -+ add( -+ results->total_dmifmc_urgent_latency, -+ results->dmif_burst_time[y_clk_level][sclk_level]), -+ bw_max( -+ results->line_source_pixels_transfer_time, -+ results->line_source_transfer_time[i][y_clk_level][sclk_level])), -+ vbios->blackout_duration), -+ results->chunk_request_time), -+ results->cursor_request_time); -+ results->stutter_exit_watermark[i] = -+ add( -+ sub( -+ vbios->stutter_self_refresh_exit_latency, -+ results->total_dmifmc_urgent_latency), -+ results->urgent_watermark[i]); -+ results->nbp_state_change_watermark[i] = -+ sub( -+ add( -+ sub( -+ vbios->nbp_state_change_latency, -+ results->total_dmifmc_urgent_latency), -+ results->urgent_watermark[i]), -+ vbios->blackout_duration); -+ } else { -+ results->urgent_watermark[i] = -+ add( -+ add( -+ add( -+ add( -+ add( -+ vbios->mcifwrmc_urgent_latency, -+ results->mcifwr_burst_time[y_clk_level][sclk_level]), -+ bw_max( -+ results->line_source_pixels_transfer_time, -+ results->line_source_transfer_time[i][y_clk_level][sclk_level])), -+ vbios->blackout_duration), -+ results->chunk_request_time), -+ results->cursor_request_time); -+ results->stutter_exit_watermark[i] = -+ int_to_fixed(0); -+ results->nbp_state_change_watermark[i] = -+ add( -+ sub( -+ add( -+ vbios->nbp_state_change_latency, -+ results->dmif_burst_time[y_clk_level][sclk_level]), -+ vbios->mcifwrmc_urgent_latency), -+ results->urgent_watermark[i]); -+ } -+ } -+ } -+ results->stutter_mode_enable = results->cpuc_state_change_enable; -+ if (mode_data->number_of_displays > 1) { -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (gtn(results->stutter_exit_watermark[i], -+ results->cursor_latency_hiding[i])) { -+ results->stutter_mode_enable = false; -+ } -+ } -+ } -+ } -+ results->dmifdram_access_efficiency = -+ bw_min( -+ bw_div( -+ bw_div( -+ results->total_display_reads_required_dram_access_data, -+ results->dram_bandwidth), -+ results->dmif_total_page_close_open_time), -+ int_to_fixed(1)); -+ if (gtn(results->total_display_writes_required_dram_access_data, -+ int_to_fixed(0))) { -+ results->mcifwrdram_access_efficiency = -+ bw_min( -+ bw_div( -+ bw_div( -+ results->total_display_writes_required_dram_access_data, -+ results->dram_bandwidth), -+ results->mcifwr_total_page_close_open_time), -+ int_to_fixed(1)); -+ } else { -+ results->mcifwrdram_access_efficiency = int_to_fixed(0); -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->average_bandwidth_no_compression[i] = -+ bw_div( -+ mul( -+ mul( -+ bw_div( -+ mul( -+ results->source_width_rounded_up_to_chunks[i], -+ results->bytes_per_pixel[i]), -+ (bw_div( -+ results->h_total[i], -+ results->pixel_rate[i]))), -+ results->vsr[i]), -+ results->bytes_per_request[i]), -+ results->useful_bytes_per_request[i]); -+ results->average_bandwidth[i] = bw_div( -+ results->average_bandwidth_no_compression[i], -+ results->compression_rate[i]); -+ } -+ } -+ results->total_average_bandwidth_no_compression = int_to_fixed(0); -+ results->total_average_bandwidth = int_to_fixed(0); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->total_average_bandwidth_no_compression = add( -+ results->total_average_bandwidth_no_compression, -+ results->average_bandwidth_no_compression[i]); -+ results->total_average_bandwidth = add( -+ results->total_average_bandwidth, -+ results->average_bandwidth[i]); -+ } -+ } -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->stutter_cycle_duration[i] = -+ sub( -+ mul( -+ bw_div( -+ bw_div( -+ mul( -+ bw_div( -+ bw_div( -+ results->adjusted_data_buffer_size[i], -+ results->bytes_per_pixel[i]), -+ results->source_width_rounded_up_to_chunks[i]), -+ results->h_total[i]), -+ results->vsr[i]), -+ results->pixel_rate[i]), -+ results->compression_rate[i]), -+ bw_max(int_to_fixed(0), -+ sub( -+ results->stutter_exit_watermark[i], -+ bw_div( -+ mul( -+ (add( -+ results->line_buffer_prefetch[i], -+ int_to_fixed( -+ 2))), -+ results->h_total[i]), -+ results->pixel_rate[i])))); -+ } -+ } -+ results->total_stutter_cycle_duration = int_to_fixed(9999); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ if (gtn(results->total_stutter_cycle_duration, -+ results->stutter_cycle_duration[i])) { -+ results->total_stutter_cycle_duration = -+ results->stutter_cycle_duration[i]; -+ } -+ } -+ } -+ results->stutter_burst_time = bw_div( -+ mul(results->total_stutter_cycle_duration, -+ results->total_average_bandwidth), -+ bw_min( -+ (mul(results->dram_bandwidth, -+ results->dmifdram_access_efficiency)), -+ mul(sclk[sclk_level], vbios->data_return_bus_width))); -+ results->time_in_self_refresh = sub( -+ sub(results->total_stutter_cycle_duration, -+ vbios->stutter_self_refresh_exit_latency), -+ results->stutter_burst_time); -+ if (mode_data->d1_display_write_back_dwb_enable == true) { -+ results->stutter_efficiency = int_to_fixed(0); -+ } else if (ltn(results->time_in_self_refresh, int_to_fixed(0))) { -+ results->stutter_efficiency = int_to_fixed(0); -+ } else { -+ results->stutter_efficiency = mul( -+ bw_div(results->time_in_self_refresh, -+ results->total_stutter_cycle_duration), -+ int_to_fixed(100)); -+ } -+ results->worst_number_of_trips_to_memory = int_to_fixed(1); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i] -+ && results->scatter_gather_enable_for_pipe[i] == true) { -+ results->number_of_trips_to_memory_for_getting_apte_row[i] = -+ bw_ceil( -+ bw_div( -+ results->scatter_gather_pte_requests_in_row[i], -+ results->scatter_gather_pte_request_limit[i]), -+ int_to_fixed(1)); -+ if (ltn(results->worst_number_of_trips_to_memory, -+ results->number_of_trips_to_memory_for_getting_apte_row[i])) { -+ results->worst_number_of_trips_to_memory = -+ results->number_of_trips_to_memory_for_getting_apte_row[i]; -+ } -+ } -+ } -+ results->immediate_flip_time = mul( -+ results->worst_number_of_trips_to_memory, -+ results->total_dmifmc_urgent_latency); -+ results->latency_for_non_dmif_clients = add( -+ results->total_dmifmc_urgent_latency, -+ results->dmif_burst_time[y_clk_level][sclk_level]); -+ if (mode_data->d1_display_write_back_dwb_enable == true) { -+ results->latency_for_non_mcifwr_clients = add( -+ vbios->mcifwrmc_urgent_latency, -+ dceip->mcifwr_all_surfaces_burst_time); -+ } else { -+ results->latency_for_non_mcifwr_clients = int_to_fixed(0); -+ } -+ results->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div( -+ (sub(results->min_read_buffer_size_in_time, -+ results->dmif_burst_time[high][high])), -+ results->total_dmifmc_urgent_trips); -+ results->nbp_state_dram_speed_change_margin = int_to_fixed(9999); -+ for (i = 0; i <= maximum_number_of_surfaces - 1; i += 1) { -+ if (results->enable[i]) { -+ results->nbp_state_dram_speed_change_margin = -+ bw_min( -+ results->nbp_state_dram_speed_change_margin, -+ sub( -+ results->maximum_latency_hiding_with_cursor[i], -+ results->nbp_state_change_watermark[i])); -+ } -+ } -+ for (i = 1; i <= 5; i += 1) { -+ results->display_reads_time_for_data_transfer_and_urgent_latency = -+ sub(results->min_read_buffer_size_in_time, -+ mul(results->total_dmifmc_urgent_trips, -+ int_to_fixed(i))); -+ if (pipe_check == def_ok -+ && (gtn( -+ results->display_reads_time_for_data_transfer_and_urgent_latency, -+ results->dmif_total_page_close_open_time))) { -+ results->dmif_required_sclk_for_urgent_latency[i] = -+ bw_div( -+ bw_div( -+ results->total_display_reads_required_data, -+ results->display_reads_time_for_data_transfer_and_urgent_latency), -+ vbios->data_return_bus_width); -+ } else { -+ results->dmif_required_sclk_for_urgent_latency[i] = -+ int_to_fixed(0); -+ } -+ } -+ -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+ -+void bw_calcs_init(struct bw_calcs_input_dceip *bw_dceip, -+ struct bw_calcs_input_vbios *bw_vbios) -+{ -+ struct bw_calcs_input_dceip dceip; -+ struct bw_calcs_input_vbios vbios; -+ -+ vbios.number_of_dram_channels = int_to_fixed(2); -+ vbios.dram_channel_width_in_bits = int_to_fixed(64); -+ vbios.number_of_dram_banks = int_to_fixed(8); -+ vbios.high_yclk = int_to_fixed(1600); -+ vbios.low_yclk = frc_to_fixed(66666, 100); -+ vbios.low_sclk = int_to_fixed(200); -+ vbios.mid_sclk = int_to_fixed(300); -+ vbios.high_sclk = frc_to_fixed(62609, 100); -+ vbios.low_voltage_max_dispclk = int_to_fixed(352); -+ vbios.mid_voltage_max_dispclk = int_to_fixed(467); -+ vbios.high_voltage_max_dispclk = int_to_fixed(643); -+ vbios.data_return_bus_width = int_to_fixed(32); -+ vbios.trc = int_to_fixed(50); -+ vbios.dmifmc_urgent_latency = int_to_fixed(4); -+ vbios.stutter_self_refresh_exit_latency = frc_to_fixed(153, 10); -+ vbios.nbp_state_change_latency = frc_to_fixed(19649, 1000); -+ vbios.mcifwrmc_urgent_latency = int_to_fixed(10); -+ vbios.scatter_gather_enable = true; -+ vbios.down_spread_percentage = frc_to_fixed(5, 10); -+ vbios.cursor_width = int_to_fixed(32); -+ vbios.average_compression_rate = int_to_fixed(4); -+ vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = -+ int_to_fixed(256); -+ vbios.blackout_duration = int_to_fixed(18); /* us */ -+ vbios.maximum_blackout_recovery_time = int_to_fixed(20); -+ dceip.dmif_request_buffer_size = int_to_fixed(768); -+ dceip.de_tiling_buffer = int_to_fixed(0); -+ dceip.dcfclk_request_generation = int_to_fixed(0); -+ dceip.lines_interleaved_into_lb = int_to_fixed(2); -+ dceip.chunk_width = int_to_fixed(256); -+ dceip.number_of_graphics_pipes = int_to_fixed(3); -+ dceip.number_of_underlay_pipes = int_to_fixed(1); -+ dceip.display_write_back_supported = false; -+ dceip.argb_compression_support = false; -+ dceip.underlay_vscaler_efficiency6_bit_per_component = frc_to_fixed( -+ 35556, 10000); -+ dceip.underlay_vscaler_efficiency8_bit_per_component = frc_to_fixed( -+ 34286, 10000); -+ dceip.underlay_vscaler_efficiency10_bit_per_component = frc_to_fixed(32, -+ 10); -+ dceip.underlay_vscaler_efficiency12_bit_per_component = int_to_fixed(3); -+ dceip.graphics_vscaler_efficiency6_bit_per_component = frc_to_fixed(35, -+ 10); -+ dceip.graphics_vscaler_efficiency8_bit_per_component = frc_to_fixed( -+ 34286, 10000); -+ dceip.graphics_vscaler_efficiency10_bit_per_component = frc_to_fixed(32, -+ 10); -+ dceip.graphics_vscaler_efficiency12_bit_per_component = int_to_fixed(3); -+ dceip.alpha_vscaler_efficiency = int_to_fixed(3); -+ dceip.max_dmif_buffer_allocated = int_to_fixed(2); -+ dceip.graphics_dmif_size = int_to_fixed(12288); -+ dceip.underlay_luma_dmif_size = int_to_fixed(19456); -+ dceip.underlay_chroma_dmif_size = int_to_fixed(23552); -+ dceip.pre_downscaler_enabled = true; -+ dceip.underlay_downscale_prefetch_enabled = true; -+ dceip.lb_write_pixels_per_dispclk = int_to_fixed(1); -+ dceip.lb_size_per_component444 = int_to_fixed(82176); -+ dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; -+ dceip.stutter_and_dram_clock_state_change_gated_before_cursor = -+ int_to_fixed(0); -+ dceip.underlay420_luma_lb_size_per_component = int_to_fixed(82176); -+ dceip.underlay420_chroma_lb_size_per_component = int_to_fixed(164352); -+ dceip.underlay422_lb_size_per_component = int_to_fixed(82176); -+ dceip.cursor_chunk_width = int_to_fixed(64); -+ dceip.cursor_dcp_buffer_lines = int_to_fixed(4); -+ dceip.cursor_memory_interface_buffer_pixels = int_to_fixed(64); -+ dceip.underlay_maximum_width_efficient_for_tiling = int_to_fixed(1920); -+ dceip.underlay_maximum_height_efficient_for_tiling = int_to_fixed(1080); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = -+ frc_to_fixed(3, 10); -+ dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = -+ int_to_fixed(25); -+ dceip.minimum_outstanding_pte_request_limit = int_to_fixed(2); -+ dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = -+ int_to_fixed(128); -+ dceip.limit_excessive_outstanding_dmif_requests = true; -+ dceip.linear_mode_line_request_alternation_slice = int_to_fixed(64); -+ dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = -+ int_to_fixed(32); -+ dceip.display_write_back420_luma_mcifwr_buffer_size = int_to_fixed( -+ 12288); -+ dceip.display_write_back420_chroma_mcifwr_buffer_size = int_to_fixed( -+ 8192); -+ dceip.request_efficiency = frc_to_fixed(8, 10); -+ dceip.dispclk_per_request = int_to_fixed(2); -+ dceip.dispclk_ramping_factor = frc_to_fixed(11, 10); -+ dceip.display_pipe_throughput_factor = frc_to_fixed(105, 100); -+ dceip.scatter_gather_pte_request_rows_in_tiling_mode = int_to_fixed(2); -+ dceip.mcifwr_all_surfaces_burst_time = int_to_fixed(0); /* todo: this is a bug*/ -+ -+ *bw_dceip = dceip; -+ *bw_vbios = vbios; -+} -+ -+/** -+ * Return: -+ * true - Display(s) configuration supported. -+ * In this case 'calcs_output' contains data for HW programming -+ * false - Display(s) configuration not supported (not enough bandwidth). -+ */ -+ -+bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_input_dceip *dceip, -+ const struct bw_calcs_input_vbios *vbios, -+ const struct bw_calcs_input_mode_data *mode_data, -+ struct bw_calcs_output *calcs_output) -+{ -+ struct bw_results_internal *bw_results_internal = dc_service_alloc( -+ ctx, sizeof(struct bw_results_internal)); -+ struct bw_calcs_input_mode_data_internal *bw_data_internal = -+ dc_service_alloc( -+ ctx, sizeof(struct bw_calcs_input_mode_data_internal)); -+ switch (mode_data->number_of_displays) { -+ case (3): -+ bw_data_internal->d2_htotal = int_to_fixed( -+ mode_data->displays_data[2].h_total); -+ bw_data_internal->d2_pixel_rate = -+ mode_data->displays_data[2].pixel_rate; -+ bw_data_internal->d2_graphics_src_width = int_to_fixed( -+ mode_data->displays_data[2].graphics_src_width); -+ bw_data_internal->d2_graphics_src_height = int_to_fixed( -+ mode_data->displays_data[2].graphics_src_height); -+ bw_data_internal->d2_graphics_scale_ratio = -+ mode_data->displays_data[2].graphics_scale_ratio; -+ bw_data_internal->d2_graphics_stereo_mode = -+ mode_data->displays_data[2].graphics_stereo_mode; -+ case (2): -+ bw_data_internal->d1_display_write_back_dwb_enable = false; -+ bw_data_internal->d1_underlay_mode = ul_none; -+ bw_data_internal->d1_underlay_scale_ratio = int_to_fixed(0); -+ bw_data_internal->d1_htotal = int_to_fixed( -+ mode_data->displays_data[1].h_total); -+ bw_data_internal->d1_pixel_rate = -+ mode_data->displays_data[1].pixel_rate; -+ bw_data_internal->d1_graphics_src_width = int_to_fixed( -+ mode_data->displays_data[1].graphics_src_width); -+ bw_data_internal->d1_graphics_src_height = int_to_fixed( -+ mode_data->displays_data[1].graphics_src_height); -+ bw_data_internal->d1_graphics_scale_ratio = -+ mode_data->displays_data[1].graphics_scale_ratio; -+ bw_data_internal->d1_graphics_stereo_mode = -+ mode_data->displays_data[1].graphics_stereo_mode; -+ -+ case (1): -+ bw_data_internal->d0_fbc_enable = -+ mode_data->displays_data[0].fbc_enable; -+ bw_data_internal->d0_lpt_enable = -+ mode_data->displays_data[0].lpt_enable; -+ bw_data_internal->d0_underlay_mode = -+ mode_data->displays_data[0].underlay_mode; -+ bw_data_internal->d0_underlay_scale_ratio = int_to_fixed(0); -+ bw_data_internal->d0_htotal = int_to_fixed( -+ mode_data->displays_data[0].h_total); -+ bw_data_internal->d0_pixel_rate = -+ mode_data->displays_data[0].pixel_rate; -+ bw_data_internal->d0_graphics_src_width = int_to_fixed( -+ mode_data->displays_data[0].graphics_src_width); -+ bw_data_internal->d0_graphics_src_height = int_to_fixed( -+ mode_data->displays_data[0].graphics_src_height); -+ bw_data_internal->d0_graphics_scale_ratio = -+ mode_data->displays_data[0].graphics_scale_ratio; -+ bw_data_internal->d0_graphics_stereo_mode = -+ mode_data->displays_data[0].graphics_stereo_mode; -+ -+ default: -+ /* data for all displays */ -+ bw_data_internal->number_of_displays = -+ mode_data->number_of_displays; -+ bw_data_internal->graphics_rotation_angle = int_to_fixed( -+ mode_data->displays_data[0].graphics_rotation_angle); -+ bw_data_internal->underlay_rotation_angle = int_to_fixed( -+ mode_data->displays_data[0].underlay_rotation_angle); -+ bw_data_internal->underlay_surface_type = -+ mode_data->displays_data[0].underlay_surface_type; -+ bw_data_internal->panning_and_bezel_adjustment = -+ mode_data->displays_data[0].panning_and_bezel_adjustment; -+ bw_data_internal->graphics_tiling_mode = -+ mode_data->displays_data[0].graphics_tiling_mode; -+ bw_data_internal->graphics_interlace_mode = -+ mode_data->displays_data[0].graphics_interlace_mode; -+ bw_data_internal->graphics_bytes_per_pixel = int_to_fixed( -+ mode_data->displays_data[0].graphics_bytes_per_pixel); -+ bw_data_internal->graphics_htaps = int_to_fixed( -+ mode_data->displays_data[0].graphics_h_taps); -+ bw_data_internal->graphics_vtaps = int_to_fixed( -+ mode_data->displays_data[0].graphics_v_taps); -+ bw_data_internal->graphics_lb_bpc = int_to_fixed( -+ mode_data->displays_data[0].graphics_lb_bpc); -+ bw_data_internal->underlay_lb_bpc = int_to_fixed( -+ mode_data->displays_data[0].underlay_lb_bpc); -+ bw_data_internal->underlay_tiling_mode = -+ mode_data->displays_data[0].underlay_tiling_mode; -+ bw_data_internal->underlay_htaps = int_to_fixed( -+ mode_data->displays_data[0].underlay_h_taps); -+ bw_data_internal->underlay_vtaps = int_to_fixed( -+ mode_data->displays_data[0].underlay_v_taps); -+ bw_data_internal->underlay_src_width = int_to_fixed( -+ mode_data->displays_data[0].underlay_src_width); -+ bw_data_internal->underlay_src_height = int_to_fixed( -+ mode_data->displays_data[0].underlay_src_height); -+ bw_data_internal->underlay_pitch_in_pixels = int_to_fixed( -+ mode_data->displays_data[0].underlay_pitch_in_pixels); -+ bw_data_internal->underlay_stereo_mode = -+ mode_data->displays_data[0].underlay_stereo_mode; -+ bw_data_internal->display_synchronization_enabled = -+ mode_data->display_synchronization_enabled; -+ } -+ -+ if (bw_data_internal->number_of_displays != 0) { -+ struct bw_fixed high_sclk = vbios->high_sclk; -+ struct bw_fixed low_sclk = vbios->low_sclk; -+ struct bw_fixed high_yclk = vbios->high_yclk; -+ struct bw_fixed low_yclk = vbios->low_yclk; -+ -+ ((struct bw_calcs_input_vbios *)vbios)->low_yclk = low_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->high_yclk = low_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->low_sclk = low_sclk; -+ ((struct bw_calcs_input_vbios *)vbios)->mid_sclk = low_sclk; -+ ((struct bw_calcs_input_vbios *)vbios)->high_sclk = low_sclk; -+ calculate_bandwidth(dceip, vbios, bw_data_internal, -+ bw_results_internal); -+ -+ /* units: nanosecond, 16bit storage. */ -+ calcs_output->nbp_state_change_watermark[0].b_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->nbp_state_change_watermark[1].b_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->nbp_state_change_watermark[2].b_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ calcs_output->stutter_exit_watermark[0].b_mark = -+ mul(bw_results_internal->stutter_exit_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->stutter_exit_watermark[1].b_mark = -+ mul(bw_results_internal->stutter_exit_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->stutter_exit_watermark[2].b_mark = -+ mul(bw_results_internal->stutter_exit_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ calcs_output->urgent_watermark[0].b_mark = -+ mul(bw_results_internal->urgent_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->urgent_watermark[1].b_mark = -+ mul(bw_results_internal->urgent_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->urgent_watermark[2].b_mark = -+ mul(bw_results_internal->urgent_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ ((struct bw_calcs_input_vbios *)vbios)->low_yclk = high_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->high_yclk = high_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->low_sclk = high_sclk; -+ ((struct bw_calcs_input_vbios *)vbios)->mid_sclk = high_sclk; -+ ((struct bw_calcs_input_vbios *)vbios)->high_sclk = high_sclk; -+ -+ calculate_bandwidth(dceip, vbios, bw_data_internal, -+ bw_results_internal); -+ -+ calcs_output->nbp_state_change_watermark[0].a_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->nbp_state_change_watermark[1].a_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->nbp_state_change_watermark[2].a_mark = -+ mul(bw_results_internal->nbp_state_change_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ calcs_output->stutter_exit_watermark[0].a_mark = -+ mul(bw_results_internal->stutter_exit_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->stutter_exit_watermark[1].a_mark = -+ mul(bw_results_internal->stutter_exit_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->stutter_exit_watermark[2].a_mark = -+ mul(bw_results_internal->stutter_exit_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ calcs_output->urgent_watermark[0].a_mark = -+ mul(bw_results_internal->urgent_watermark[4], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->urgent_watermark[1].a_mark = -+ mul(bw_results_internal->urgent_watermark[5], -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->urgent_watermark[2].a_mark = -+ mul(bw_results_internal->urgent_watermark[6], -+ int_to_fixed(1000)).value >> 24; -+ -+ calcs_output->nbp_state_change_enable = -+ bw_results_internal->nbp_state_change_enable; -+ calcs_output->cpuc_state_change_enable = -+ bw_results_internal->cpuc_state_change_enable; -+ calcs_output->cpup_state_change_enable = -+ bw_results_internal->cpup_state_change_enable; -+ calcs_output->stutter_mode_enable = -+ bw_results_internal->stutter_mode_enable; -+ calcs_output->dispclk = -+ mul(bw_results_internal->dispclk, -+ int_to_fixed(1000)).value >> 24; -+ calcs_output->required_sclk = -+ mul(bw_results_internal->required_sclk, -+ int_to_fixed(1000)).value >> 24; -+ -+ ((struct bw_calcs_input_vbios *)vbios)->low_yclk = low_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->high_yclk = high_yclk; -+ ((struct bw_calcs_input_vbios *)vbios)->low_sclk = low_sclk; -+ ((struct bw_calcs_input_vbios *)vbios)->mid_sclk = high_sclk; -+ ((struct bw_calcs_input_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 = 0; -+ calcs_output->required_sclk = 0; -+ } -+ -+ dc_service_free(ctx, bw_data_internal); -+ dc_service_free(ctx, bw_results_internal); -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c -new file mode 100644 -index 0000000..6bad7c6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c -@@ -0,0 +1,278 @@ -+/* -+ * 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 "dc_services.h" -+#include "bw_fixed.h" -+ -+ -+#define BITS_PER_FRACTIONAL_PART 24 -+ -+#define MIN_I32 \ -+ (long long)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART))) -+ -+#define MAX_I32 \ -+ (long long)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1) -+ -+#define MIN_I64 \ -+ (long long)(-(1LL << 63)) -+ -+#define MAX_I64 \ -+ (long long)((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 unsigned long long abs_i64(long long arg) -+{ -+ if (arg >= 0) -+ return (unsigned long long)(arg); -+ else -+ return (unsigned long long)(-arg); -+} -+ -+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -+{ -+ return bw_min(bw_min(v1, v2), v3); -+} -+ -+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -+{ -+ return bw_max(bw_max(v1, v2), v3); -+} -+ -+struct bw_fixed int_to_fixed(long long value) -+{ -+ struct bw_fixed res; -+ ASSERT(value < MAX_I32 && value > MIN_I32); -+ res.value = value << BITS_PER_FRACTIONAL_PART; -+ return res; -+} -+ -+struct bw_fixed frc_to_fixed(long long numerator, long long denominator) -+{ -+ struct bw_fixed res; -+ bool arg1_negative = numerator < 0; -+ bool arg2_negative = denominator < 0; -+ unsigned long long arg1_value; -+ unsigned long long arg2_value; -+ unsigned long long remainder; -+ -+ /* determine integer part */ -+ unsigned long long res_value; -+ -+ ASSERT(denominator != 0); -+ -+ arg1_value = abs_i64(numerator); -+ arg2_value = abs_i64(denominator); -+ remainder = arg1_value % arg2_value; -+ res_value = arg1_value / arg2_value; -+ -+ ASSERT(res_value <= MAX_I32); -+ -+ /* determine fractional part */ -+ { -+ unsigned int 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 */ -+ { -+ unsigned long long summand = (remainder << 1) >= arg2_value; -+ -+ ASSERT(res_value <= MAX_I64 - summand); -+ -+ res_value += summand; -+ } -+ -+ res.value = (signed long long)(res_value); -+ -+ if (arg1_negative ^ arg2_negative) -+ res.value = -res.value; -+ return res; -+} -+ -+struct bw_fixed bw_min(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return (arg1.value <= arg2.value) ? arg1 : arg2; -+} -+ -+struct bw_fixed bw_max(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return (arg2.value <= arg1.value) ? arg1 : arg2; -+} -+ -+struct bw_fixed bw_floor(const struct bw_fixed arg, const struct bw_fixed significance) -+{ -+ struct bw_fixed result; -+ signed long long multiplicand = 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_ceil(const struct bw_fixed arg, const struct bw_fixed significance) -+{ -+ struct bw_fixed result; -+ result.value = arg.value + arg.value % abs_i64(significance.value); -+ if (result.value < significance.value) -+ result.value = significance.value; -+ return result; -+} -+ -+struct bw_fixed 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 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 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; -+ -+ unsigned long long arg1_value = abs_i64(arg1.value); -+ unsigned long long arg2_value = abs_i64(arg2.value); -+ -+ unsigned long long arg1_int = GET_INTEGER_PART(arg1_value); -+ unsigned long long arg2_int = GET_INTEGER_PART(arg2_value); -+ -+ unsigned long long arg1_fra = GET_FRACTIONAL_PART(arg1_value); -+ unsigned long long arg2_fra = GET_FRACTIONAL_PART(arg2_value); -+ -+ unsigned long long 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 <= (unsigned long long)(MAX_I64 - res.value)); -+ -+ res.value += tmp; -+ -+ tmp = arg2_int * arg1_fra; -+ -+ ASSERT(tmp <= (unsigned long long)(MAX_I64 - res.value)); -+ -+ res.value += tmp; -+ -+ tmp = arg1_fra * arg2_fra; -+ -+ tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + -+ (tmp >= (unsigned long long)(frc_to_fixed(1, 2).value)); -+ -+ ASSERT(tmp <= (unsigned long long)(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 = frc_to_fixed(arg1.value, arg2.value); -+ return res; -+} -+ -+struct bw_fixed fixed31_32_to_bw_fixed(long long 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 equ(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value == arg2.value; -+} -+ -+bool neq(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value != arg2.value; -+} -+ -+bool leq(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value <= arg2.value; -+} -+ -+bool geq(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value >= arg2.value; -+} -+ -+bool ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value < arg2.value; -+} -+ -+bool gtn(const struct bw_fixed arg1, const struct bw_fixed arg2) -+{ -+ return arg1.value > arg2.value; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c -new file mode 100644 -index 0000000..f8ee65e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c -@@ -0,0 +1,1992 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/fixed31_32.h" -+ -+#include "scaler_filter.h" -+ -+enum { -+ DOWN_DB_SCALES = 8, -+ DOWN_DB_POINTS = 11, -+ -+ UP_DB_SCALES = 1, -+ UP_DB_POINTS = 7, -+ -+ MIN_SHARPNESS = -50, -+ MAX_SHARPNESS = 50, -+ -+ CONST_DIVIDER = 10000000, -+ -+ MAX_HOR_DOWNSCALE = 1666000, /* 1:6 */ -+ MAX_VER_DOWNSCALE = 1666000, /* 1:6 */ -+ -+ MAX_HOR_UPSCALE = 160000000, /* 16:1 */ -+ MAX_VER_UPSCALE = 160000000, /* 16:1 */ -+ -+ THRESHOLDRATIOLOW = 8000000, /* 0.8 */ -+ THRESHOLDRATIOUP = 10000000, /* 1.0 */ -+ -+ DOWN_DB_FUZZY = -120411996, /* -12.041200 */ -+ DOWN_DB_FLAT = -60205998, /* -6.020600 */ -+ DOWN_DB_SHARP = -10000000, /* -1.000000 */ -+ -+ UP_DB_FUZZY = -60205998, /* -6.020600 */ -+ UP_DB_FLAT = 0, -+ UP_DB_SHARP = 60205998 /* 6.020600 */ -+}; -+ -+static inline struct fixed31_32 max_hor_downscale(void) -+{ -+ return dal_fixed31_32_from_fraction(MAX_HOR_DOWNSCALE, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 max_ver_downscale(void) -+{ -+ return dal_fixed31_32_from_fraction(MAX_VER_DOWNSCALE, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 max_hor_upscale(void) -+{ -+ return dal_fixed31_32_from_fraction(MAX_HOR_UPSCALE, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 max_ver_upscale(void) -+{ -+ return dal_fixed31_32_from_fraction(MAX_VER_UPSCALE, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 threshold_ratio_low(void) -+{ -+ return dal_fixed31_32_from_fraction(THRESHOLDRATIOLOW, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 threshold_ratio_up(void) -+{ -+ return dal_fixed31_32_from_fraction(THRESHOLDRATIOUP, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 down_db_fuzzy(void) -+{ -+ return dal_fixed31_32_from_fraction(DOWN_DB_FUZZY, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 down_db_flat(void) -+{ -+ return dal_fixed31_32_from_fraction(DOWN_DB_FLAT, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 down_db_sharp(void) -+{ -+ return dal_fixed31_32_from_fraction(DOWN_DB_SHARP, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 up_db_fuzzy(void) -+{ -+ return dal_fixed31_32_from_fraction(UP_DB_FUZZY, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 up_db_flat(void) -+{ -+ return dal_fixed31_32_from_fraction(UP_DB_FLAT, CONST_DIVIDER); -+} -+ -+static inline struct fixed31_32 up_db_sharp(void) -+{ -+ return dal_fixed31_32_from_fraction(UP_DB_SHARP, CONST_DIVIDER); -+} -+ -+static const int32_t -+ downscaling_db_table[][DOWN_DB_SCALES + 1][DOWN_DB_POINTS] = { -+ /* 3 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 14302719, 14302719, 14302719, -+ 10000000, 99999, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14302339, 14302339, 14302339, -+ 10000000, 4452010, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14302760, 14302760, 14302760, -+ 10000000, 7826979, 5258399, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14302819, 14302819, 14302819, -+ 10000000, 8669400, 7414469, -+ 4422729, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14302730, 14302730, 12791190, -+ 10000000, 9045640, 8180170, -+ 6477950, 4599249, 2019010, -+ 99999, 99999 -+ }, -+ { -+ 14302699, 14302699, 12067849, -+ 10000000, 9236029, 8541280, -+ 7252740, 6021010, 4820120, -+ 3511950, 1769340 -+ }, -+ { -+ 14302710, 14302710, 11783510, -+ 10000000, 9325690, 8704419, -+ 7595670, 6583020, 5652850, -+ 4749999, 3847680 -+ }, -+ { -+ 14302920, 14302920, 11709250, -+ 10000000, 9345560, 8754609, -+ 7692559, 6738259, 5878239, -+ 5057529, 4264070 -+ } -+ }, -+ /* 4 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 14308999, 14308999, 14308999, -+ 10000000, 99999, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14308999, 14308999, 14308999, -+ 10000000, 6311039, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14308999, 14308999, 14308999, -+ 10000000, 8526669, 6832849, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14308999, 14308999, 12110630, -+ 10000000, 9117940, 8230940, -+ 6320130, 3719770, 99999, -+ 99999, 99999 -+ }, -+ { -+ 14308999, 14308999, 11474980, -+ 10000000, 9370139, 8771979, -+ 7601270, 6440780, 5249999, -+ 3887520, 2039040 -+ }, -+ { -+ 14308999, 13084859, 11179579, -+ 10000000, 9495180, 9016919, -+ 8134520, 7311699, 6560329, -+ 5845720, 5155519 -+ }, -+ { -+ 14308999, 12576600, 11048669, -+ 10000000, 9550499, 9132360, -+ 8368729, 7679399, 7073119, -+ 6520900, 6015530 -+ }, -+ { -+ 14308999, 12448530, 11007410, -+ 10000000, 9566799, 9165279, -+ 8435800, 7785279, 7215780, -+ 6701470, 6240640 -+ } -+ }, -+ /* 5 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 8971139, 8971139, 8971139, -+ 10000000, 99999, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 9466379, 9466379, 9466379, -+ 10000000, 5648760, 3834280, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 15000000, 15000000, 14550110, -+ 10000000, 7121120, 5994579, -+ 4314630, 2606149, 99999, -+ 99999, 99999 -+ }, -+ { -+ 15000000, 15000000, 13047469, -+ 10000000, 8368809, 7343569, -+ 5970299, 4924620, 4029389, -+ 3171139, 2276369 -+ }, -+ { -+ 15000000, 14157199, 11897679, -+ 10000000, 9166659, 8444600, -+ 7287240, 6374719, 5615460, -+ 4949580, 4350199 -+ }, -+ { -+ 15000000, 12877819, 11224579, -+ 10000000, 9488620, 9016109, -+ 8203780, 7500000, 6883730, -+ 6326839, 5818459 -+ }, -+ { -+ 14733040, 12233200, 10939040, -+ 10000000, 9608929, 9250000, -+ 8623390, 8076940, 7606369, -+ 7177749, 6785169 -+ }, -+ { -+ 14627330, 12046170, 10862360, -+ 10000000, 9639260, 9312710, -+ 8737679, 8242470, 7815709, -+ 7432209, 7082970 -+ } -+ }, -+ /* 6 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 8231559, 8231559, 8231559, -+ 10000000, 99999, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 8353310, 8353310, 8353310, -+ 10000000, 5504879, 4310710, -+ 870359, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 8643479, 8643479, 8643479, -+ 10000000, 6483510, 5768150, -+ 4630779, 3580690, 2501940, -+ 1015309, 99999 -+ }, -+ { -+ 15000000, 15000000, 13493930, -+ 10000000, 7516040, 6802409, -+ 5824409, 5080109, 4454280, -+ 3896749, 3386510 -+ }, -+ { -+ 15000000, 14055930, 12321079, -+ 10000000, 8872389, 8090410, -+ 7035570, 6281229, 5676810, -+ 5165010, 4717260 -+ }, -+ { -+ 15000000, 12915290, 11311399, -+ 10000000, 9460610, 8988440, -+ 8202149, 7548679, 6999999, -+ 6510639, 6065719 -+ }, -+ { -+ 14310129, 12140829, 10901659, -+ 10000000, 9635019, 9307180, -+ 8740929, 8263260, 7858849, -+ 7499330, 7170130 -+ }, -+ { -+ 13815449, 11911309, 10801299, -+ 10000000, 9669629, 9380580, -+ 8878319, 8452050, 8097199, -+ 7785030, 7504299 -+ } -+ }, -+ /* 7 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 10616660, 10616660, 10616660, -+ 10000000, 2646020, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 10099999, 10099999, 10099999, -+ 10000000, 4936839, 4112670, -+ 2729740, 896539, 99999, -+ 99999, 99999 -+ }, -+ { -+ 8345860, 8345860, 8345860, -+ 10000000, 6034079, 5371739, -+ 4466759, 3763799, 3155870, -+ 2588019, 2026730 -+ }, -+ { -+ 9298499, 9298499, 13768420, -+ 10000000, 7174239, 6524270, -+ 5670250, 5052099, 4549089, -+ 4115279, 3722150 -+ }, -+ { -+ 15000000, 14116940, 12563209, -+ 10000000, 8542140, 7782419, -+ 6865050, 6239479, 5758860, -+ 5351870, 4992800 -+ }, -+ { -+ 15000000, 12913750, 11306079, -+ 10000000, 9452580, 8969209, -+ 8168810, 7538409, 7029479, -+ 6603180, 6227809 -+ }, -+ { -+ 14390859, 11862809, 10757420, -+ 10000000, 9688709, 9404249, -+ 8904439, 8472480, 8099079, -+ 7765330, 7459110 -+ }, -+ { -+ 13752900, 11554559, 10637769, -+ 10000000, 9736120, 9499999, -+ 9079759, 8718389, 8408790, -+ 8134469, 7886120 -+ } -+ }, -+ /* 8 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 11277090, 11277090, 11277090, -+ 10000000, 2949059, 99999, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 11196039, 11196039, 11196039, -+ 10000000, 4627540, 4018869, -+ 3018769, 2000000, 250770, -+ 99999, 99999 -+ }, -+ { -+ 10878369, 10878369, 10878369, -+ 10000000, 5657230, 5118110, -+ 4372630, 3809120, 3337709, -+ 2919510, 2535369 -+ }, -+ { -+ 9090089, 9090089, 13961290, -+ 10000000, 6929969, 6334999, -+ 5569829, 5019649, 4584150, -+ 4208610, 3876540 -+ }, -+ { -+ 15000000, 14173229, 12732659, -+ 10000000, 8267070, 7575380, -+ 6764540, 6218209, 5803539, -+ 5454990, 5146239 -+ }, -+ { -+ 15000000, 12928279, 11292259, -+ 10000000, 9447429, 8954229, -+ 8141599, 7516989, 7039459, -+ 6649519, 6316819 -+ }, -+ { -+ 14661350, 11638879, 10665880, -+ 10000000, 9722669, 9464690, -+ 9013469, 8613470, 8266339, -+ 7949870, 7663450 -+ }, -+ { -+ 13861900, 11311980, 10543940, -+ 10000000, 9772019, 9565100, -+ 9198870, 8881340, 8609200, -+ 8365769, 8147500 -+ } -+ }, -+ /* 9 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { 10099999, 10099999, 10099999, -+ 10000000, 2939159, 1526470, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 11726609, 11726609, 11726609, -+ 10000000, 4329420, 3805609, -+ 3030480, 2363760, 1732099, -+ 980139, 99999 -+ }, -+ { -+ 10949269, 10949269, 10949269, -+ 10000000, 5452589, 4946640, -+ 4277969, 3790729, 3392640, -+ 3048950, 2750000 -+ }, -+ { -+ 8830279, 8830279, 14084529, -+ 10000000, 6743149, 6182519, -+ 5482980, 5000000, 4622060, -+ 4303340, 4022600 -+ }, -+ { -+ 9709150, 14111399, 12800760, -+ 10000000, 7989749, 7445629, -+ 6741260, 6241980, 5857459, -+ 5534989, 5255370 -+ }, -+ { -+ 15000000, 12830289, 11489900, -+ 10000000, 9302089, 8767340, -+ 8025540, 7500000, 7100800, -+ 6768149, 6481850 -+ }, -+ { -+ 14873609, 11576000, 10650579, -+ 10000000, 9731360, 9483649, -+ 9054650, 8680559, 8358049, -+ 8066400, 7802420 -+ }, -+ { -+ 12981410, 11185950, 10491620, -+ 10000000, 9795730, 9611030, -+ 9286710, 9007279, 8768100, -+ 8553469, 8361340 -+ } -+ }, -+ /* 10 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 8993279, 8993279, 8993279, -+ 10000000, 2921360, 1905619, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 9064850, 9064850, 9064850, -+ 10000000, 4095619, 3655839, -+ 3021000, 2500000, 2031680, -+ 1566990, 1055440 -+ }, -+ { -+ 11043460, 11043460, 11043460, -+ 10000000, 5287479, 4816150, -+ 4208439, 3769229, 3418970, -+ 3117449, 2850320 -+ }, -+ { -+ 8651900, 8651900, 14169909, -+ 10000000, 6596950, 6071490, -+ 5423219, 4980779, 4644620, -+ 4362219, 4114899 -+ }, -+ { -+ 9246050, 14055370, 12832759, -+ 10000000, 7831320, 7369570, -+ 6731680, 6262450, 5897690, -+ 5592269, 5328789 -+ }, -+ { -+ 15000000, 12770450, 11642129, -+ 10000000, 9120929, 8601920, -+ 7946630, 7490440, 7140589, -+ 6847490, 6593719 -+ }, -+ { -+ 14062479, 11541219, 10644329, -+ 10000000, 9736120, 9495139, -+ 9080520, 8724340, 8419489, -+ 8146359, 7899820 -+ }, -+ { -+ 12507469, 11102950, 10457479, -+ 10000000, 9811149, 9641249, -+ 9344969, 9090980, 8875219, -+ 8684499, 8513180 -+ } -+ }, -+ /* 11 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 10099509, 10099509, 10099509, -+ 10000000, 2788810, 2054850, -+ 99999, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 8872069, 8872069, 8872069, -+ 10000000, 3929649, 3522840, -+ 2963230, 2527720, 2157579, -+ 1823610, 1500000 -+ }, -+ { -+ 10099999, 10099999, 10099999, -+ 10000000, 5155599, 4712319, -+ 4154500, 3759450, 3448629, -+ 3183139, 2948490 -+ }, -+ { -+ 10511649, 10511649, 14216580, -+ 10000000, 6445930, 5988820, -+ 5401239, 4988409, 4673399, -+ 4410479, 4181599 -+ }, -+ { -+ 9170889, 14003310, 12949769, -+ 10000000, 7684900, 7250000, -+ 6670129, 6255810, 5934680, -+ 5664110, 5427970 -+ }, -+ { -+ 15000000, 12763030, 11734730, -+ 10000000, 8958870, 8478559, -+ 7893459, 7489529, 7179200, -+ 6917790, 6688359 -+ }, -+ { -+ 14634610, 11491880, 10619130, -+ 10000000, 9744859, 9509819, -+ 9102900, 8760340, 8463050, -+ 8202620, 7968729 -+ }, -+ { -+ 12415319, 10980290, 10405089, -+ 10000000, 9831910, 9680110, -+ 9413710, 9184579, 8987190, -+ 8813819, 8655819 -+ } -+ }, -+ /* 12 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 10832400, 10832400, 10832400, -+ 10000000, 2700819, 2115820, -+ 750000, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 10747549, 10747549, 10747549, -+ 10000000, 3781630, 3415020, -+ 2914879, 2537429, 2221180, -+ 1943199, 1688420 -+ }, -+ { -+ 11630790, 11630790, 11630790, -+ 10000000, 5047429, 4631519, -+ 4113860, 3750000, 3469760, -+ 3229379, 3016360 -+ }, -+ { -+ 10780229, 10780229, 10780229, -+ 10000000, 6340010, 5935009, -+ 5387600, 4995940, 4695929, -+ 4446829, 4231610 -+ }, -+ { -+ 9055669, 13968739, 13037070, -+ 10000000, 7556660, 7149490, -+ 6625509, 6250000, 5958870, -+ 5713790, 5500869 -+ }, -+ { -+ 14614900, 12760740, 11806739, -+ 10000000, 8824530, 8388419, -+ 7857400, 7489010, 7206150, -+ 6968010, 6759889 -+ }, -+ { -+ 14894100, 11451840, 10598870, -+ 10000000, 9750000, 9521099, -+ 9122239, 8784019, 8494700, -+ 8243309, 8018680 -+ }, -+ { -+ 12298769, 10886880, 10367530, -+ 10000000, 9846829, 9708030, -+ 9464049, 9252949, 9072539, -+ 8910980, 8766649 -+ } -+ }, -+ /* 13 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 10099999, 10099999, 10099999, -+ 10000000, 2574490, 2099110, -+ 1194889, 99999, 99999, -+ 99999, 99999 -+ }, -+ { -+ 10099999, 10099999, 10099999, -+ 10000000, 3679780, 3332070, -+ 2869139, 2530030, 2251899, -+ 2010450, 1793050 -+ }, -+ { -+ 9306690, 9306690, 9306690, -+ 10000000, 4964010, 4573009, -+ 4082309, 3742089, 3481810, -+ 3262990, 3070969 -+ }, -+ { -+ 10099999, 10099999, 10099999, -+ 10000000, 6217889, 5843269, -+ 5353810, 5000000, 4730190, -+ 4499999, 4301390 -+ }, -+ { -+ 8819990, 13964320, 13098440, -+ 10000000, 7454770, 7075160, -+ 6591439, 6250000, 5983970, -+ 5760229, 5564339 -+ }, -+ { -+ 14432849, 12727780, 11847709, -+ 10000000, 8695709, 8322049, -+ 7842620, 7500000, 7234820, -+ 7010849, 6814730 -+ }, -+ { -+ 15000000, 11440130, 10620100, -+ 10000000, 9742270, 9508739, -+ 9110010, 8782560, 8510140, -+ 8276290, 8069980 -+ }, -+ { -+ 12039999, 10825289, 10341939, -+ 10000000, 9858080, 9729740, -+ 9505100, 9310669, 9144560, -+ 8996559, 8862569 -+ } -+ }, -+ /* 14 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 9289590, 9289590, 9289590, -+ 10000000, 2485270, 2084970, -+ 1362659, 250000, 99999, -+ 99999, 99999 -+ }, -+ { -+ 9484500, 9484500, 9484500, -+ 10000000, 3593840, 3263100, -+ 2833609, 2519409, 2267650, -+ 2050379, 1856749 -+ }, -+ { -+ 9237130, 9237130, 9237130, -+ 10000000, 4898909, 4527629, -+ 4057880, 3734529, 3490320, -+ 3287230, 3111050 -+ }, -+ { -+ 9543399, 9543399, 9543399, -+ 10000000, 6110230, 5772359, -+ 5328080, 5007240, 4757330, -+ 4545379, 4359109 -+ }, -+ { -+ 9032660, 9032660, 9032660, -+ 10000000, 7373520, 7016940, -+ 6565740, 6250000, 6002650, -+ 5794939, 5610830 -+ }, -+ { -+ 14351329, 12697319, 11875350, -+ 10000000, 8606730, 8275989, -+ 7833449, 7510430, 7257339, -+ 7043970, 6857690 -+ }, -+ { -+ 13286800, 11436090, 10643019, -+ 10000000, 9729470, 9491149, -+ 9096930, 8778640, 8519319, -+ 8299450, 8104829 -+ }, -+ { -+ 11838380, 10778709, 10322740, -+ 10000000, 9866499, 9746059, -+ 9535790, 9354810, 9200339, -+ 9063839, 8940430 -+ } -+ }, -+ /* 15 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 9193199, 9193199, 9193199, -+ 10000000, 2400999, 2042409, -+ 1450179, 789309, 99999, -+ 99999, 99999 -+ }, -+ { -+ 10755189, 10755189, 10755189, -+ 10000000, 3532319, 3212479, -+ 2803660, 2510200, 2278629, -+ 2078720, 1899970 -+ }, -+ { -+ 8732669, 8732669, 8732669, -+ 10000000, 4821290, 4483030, -+ 4045079, 3737959, 3505080, -+ 3311960, 3143329 -+ }, -+ { -+ 9450280, 9450280, 9450280, -+ 10000000, 6040880, 5718960, -+ 5302609, 5004199, 4771710, -+ 4575310, 4404180 -+ }, -+ { -+ 10520930, 10520930, 10520930, -+ 10000000, 7298259, 6975160, -+ 6552690, 6250000, 6018469, -+ 5822089, 5648869 -+ }, -+ { -+ 14320160, 12683949, 11917040, -+ 10000000, 8541300, 8228710, -+ 7812070, 7509459, 7272909, -+ 7072560, 6895729 -+ }, -+ { -+ 15000000, 11434819, 10650700, -+ 10000000, 9723110, 9480339, -+ 9083300, 8771640, 8524850, -+ 8317480, 8135899 -+ }, -+ { -+ 11750520, 10722860, 10299190, -+ 10000000, 9875990, 9763770, -+ 9567070, 9397709, 9252669, -+ 9124029, 9008929 -+ } -+ }, -+ /* 16 tap downscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, -+ 0, -10000000, -20000000, -+ -40000000, -60209999, -80000000, -+ -100000000, -120410003 -+ }, -+ { -+ 10612260, 10612260, 10612260, -+ 10000000, 2308720, 1999289, -+ 1495770, 1009820, 315460, -+ 99999, 99999 -+ }, -+ { -+ 9394969, 9394969, 9394969, -+ 10000000, 3462660, 3162190, -+ 2780120, 2508420, 2295179, -+ 2109449, 1943989 -+ }, -+ { -+ 10609409, 10609409, 10609409, -+ 10000000, 4749999, 4447000, -+ 4039109, 3746300, 3522360, -+ 3336620, 3177059 -+ }, -+ { -+ 9435039, 9435039, 9435039, -+ 10000000, 5978109, 5675160, -+ 5282300, 5000000, 4782429, -+ 4598149, 4438050 -+ }, -+ { -+ 10592620, 10592620, 10592620, -+ 10000000, 7244589, 6940630, -+ 6537730, 6250000, 6027920, -+ 5842260, 5680159 -+ }, -+ { -+ 14282959, 12678509, 11963449, -+ 10000000, 8484349, 8181620, -+ 7785459, 7500000, 7281309, -+ 7095699, 6932809 -+ }, -+ { -+ 15000000, 11434919, 10673819, -+ 10000000, 9708179, 9456859, -+ 9060000, 8760929, 8529940, -+ 8338279, 8172209 -+ }, -+ { -+ 11690390, 10668220, 10277210, -+ 10000000, 9884750, 9780330, -+ 9597110, 9439319, 9304260, -+ 9183580, 9075019 -+ } -+ } -+}; -+ -+static const int32_t upscaling_db_table[][UP_DB_SCALES+1][UP_DB_POINTS] = { -+ /* 3 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 14302920, 14302920, 11709250, -+ 10000000, -+ 8754609, 7692559, 6738259 -+ } -+ }, -+ /* 4 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 14308999, 12448530, 11007410, -+ 10000000, 9165279, 8435800, -+ 7785279 -+ } -+ }, -+ /* 5 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 14627330, 12046170, 10862360, -+ 10000000, -+ 9312710, 8737679, 8242470 -+ } -+ }, -+ /* 6 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 13815449, 11911309, 10801299, -+ 10000000, -+ 9380580, 8878319, 8452050 -+ } -+ }, -+ /* 7 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 13752900, 11554559, 10637769, -+ 10000000, -+ 9499999, 9079759, 8718389 -+ } -+ }, -+ /* 8 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 13861900, 11311980, 10543940, -+ 10000000, -+ 9565100, 9198870, 8881340 -+ } -+ }, -+ /* 9 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 12981410, 11185950, 10491620, -+ 10000000, -+ 9611030, 9286710, 9007279 -+ } -+ }, -+ /* 10 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 12507469, 11102950, 10457479, -+ 10000000, -+ 9641249, 9344969, 9090980 -+ } -+ }, -+ /* 11 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 12415319, 10980290, 10405089, -+ 10000000, -+ 9680110, 9413710, 9184579 -+ } -+ }, -+ /* 12 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 12298769, 10886880, 10367530, -+ 10000000, -+ 9708030, 9464049, 9252949 -+ } -+ }, -+ /* 13 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 12039999, 10825289, 10341939, -+ 10000000, -+ 9729740, 9505100, 9310669 -+ } -+ }, -+ /* 14 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 11838380, 10778709, 10322740, -+ 10000000, -+ 9746059, 9535790, 9354810 -+ } -+ }, -+ /* 15 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 11750520, 10722860, 10299190, -+ 10000000, -+ 9763770, 9567070, 9397709 -+ } -+ }, -+ /* 16 tap upscaling */ -+ { -+ { -+ 60209999, 40000000, 20000000, 0, -+ -20000000, -40000000, -60209999 -+ }, -+ { -+ 11690390, 10668220, 10277210, -+ 10000000, -+ 9780330, 9597110, 9439319 -+ } -+ } -+}; -+ -+static bool allocate_3d_storage( -+ struct dc_context *ctx, -+ struct fixed31_32 ****ptr, -+ int32_t numberof_tables, -+ int32_t numberof_rows, -+ int32_t numberof_columns) -+{ -+ int32_t indexof_table = 0; -+ int32_t indexof_row = 0; -+ -+ struct fixed31_32 ***tables = dc_service_alloc( -+ ctx, -+ numberof_tables * sizeof(struct fixed31_32 **)); -+ -+ if (!tables) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (indexof_table != numberof_tables) { -+ struct fixed31_32 **rows = dc_service_alloc( -+ ctx, -+ numberof_rows * sizeof(struct fixed31_32 *)); -+ -+ if (!rows) { -+ BREAK_TO_DEBUGGER(); -+ --indexof_table; -+ goto failure; -+ } -+ -+ tables[indexof_table] = rows; -+ -+ while (indexof_row != numberof_rows) { -+ struct fixed31_32 *columns = dc_service_alloc( -+ ctx, -+ numberof_columns * sizeof(struct fixed31_32)); -+ -+ if (!columns) { -+ BREAK_TO_DEBUGGER(); -+ --indexof_row; -+ goto failure; -+ } -+ -+ rows[indexof_row] = columns; -+ -+ ++indexof_row; -+ } -+ -+ indexof_row = 0; -+ -+ ++indexof_table; -+ } -+ -+ *ptr = tables; -+ -+ return true; -+ -+failure: -+ -+ while (indexof_table >= 0) { -+ while (indexof_row >= 0) { -+ dc_service_free(ctx, tables[indexof_table][indexof_row]); -+ -+ --indexof_row; -+ } -+ -+ indexof_row = numberof_rows - 1; -+ -+ dc_service_free(ctx, tables[indexof_table]); -+ -+ --indexof_table; -+ } -+ -+ dc_service_free(ctx, tables); -+ -+ return false; -+} -+ -+static void destroy_3d_storage( -+ struct dc_context *ctx, -+ struct fixed31_32 ****ptr, -+ uint32_t numberof_tables, -+ uint32_t numberof_rows) -+{ -+ struct fixed31_32 ***tables = *ptr; -+ -+ uint32_t indexof_table = 0; -+ -+ if (!tables) -+ return; -+ -+ while (indexof_table != numberof_tables) { -+ uint32_t indexof_row = 0; -+ -+ while (indexof_row != numberof_rows) { -+ dc_service_free( -+ ctx, tables[indexof_table][indexof_row]); -+ -+ ++indexof_row; -+ }; -+ -+ dc_service_free(ctx, tables[indexof_table]); -+ -+ ++indexof_table; -+ }; -+ -+ dc_service_free(ctx, tables); -+ -+ *ptr = NULL; -+} -+ -+static bool create_downscaling_table( -+ struct scaler_filter *filter) -+{ -+ const int32_t numberof_tables = -+ ARRAY_SIZE(downscaling_db_table); -+ const int32_t numberof_rows = -+ ARRAY_SIZE(downscaling_db_table[0]); -+ const int32_t numberof_columns = -+ ARRAY_SIZE(downscaling_db_table[0][0]); -+ -+ int32_t indexof_table = 0; -+ -+ if (!allocate_3d_storage(filter->ctx, &filter->downscaling_table, -+ numberof_tables, numberof_rows, numberof_columns)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (indexof_table != numberof_tables) { -+ struct fixed31_32 **table = -+ filter->downscaling_table[indexof_table]; -+ -+ int32_t indexof_row = 0; -+ -+ while (indexof_row != numberof_rows) { -+ struct fixed31_32 *row = table[indexof_row]; -+ -+ int32_t indexof_column = 0; -+ -+ while (indexof_column != numberof_columns) { -+ row[indexof_column] = -+dal_fixed31_32_from_fraction( -+ downscaling_db_table[indexof_table][indexof_row][indexof_column], -+ CONST_DIVIDER); -+ -+ ++indexof_column; -+ } -+ -+ ++indexof_row; -+ } -+ -+ ++indexof_table; -+ } -+ -+ return true; -+} -+ -+static inline void destroy_downscaling_table( -+ struct scaler_filter *filter) -+{ -+ destroy_3d_storage( -+ filter->ctx, -+ &filter->downscaling_table, -+ ARRAY_SIZE(downscaling_db_table), -+ ARRAY_SIZE(downscaling_db_table[0])); -+} -+ -+static bool create_upscaling_table( -+ struct scaler_filter *filter) -+{ -+ const int32_t numberof_tables = -+ ARRAY_SIZE(upscaling_db_table); -+ const int32_t numberof_rows = -+ ARRAY_SIZE(upscaling_db_table[0]); -+ const int32_t numberof_columns = -+ ARRAY_SIZE(upscaling_db_table[0][0]); -+ -+ int32_t indexof_table = 0; -+ -+ if (!allocate_3d_storage(filter->ctx, &filter->upscaling_table, -+ numberof_tables, numberof_rows, numberof_columns)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (indexof_table != numberof_tables) { -+ struct fixed31_32 **table = -+ filter->upscaling_table[indexof_table]; -+ -+ int32_t indexof_row = 0; -+ -+ while (indexof_row != numberof_rows) { -+ struct fixed31_32 *row = table[indexof_row]; -+ -+ int32_t indexof_column = 0; -+ -+ while (indexof_column != numberof_columns) { -+ row[indexof_column] = -+dal_fixed31_32_from_fraction( -+ upscaling_db_table[indexof_table][indexof_row][indexof_column], -+ CONST_DIVIDER); -+ -+ ++indexof_column; -+ } -+ -+ ++indexof_row; -+ } -+ -+ ++indexof_table; -+ } -+ -+ return true; -+} -+ -+static inline void destroy_upscaling_table( -+ struct scaler_filter *filter) -+{ -+ destroy_3d_storage( -+ filter->ctx, -+ &filter->upscaling_table, -+ ARRAY_SIZE(upscaling_db_table), -+ ARRAY_SIZE(upscaling_db_table[0])); -+} -+ -+static bool same_filter_required( -+ struct scaler_filter *filter, -+ const struct scaler_filter_params *params, -+ uint32_t src_size, -+ uint32_t dst_size) -+{ -+ if (!filter->src_size) -+ return false; -+ if (!filter->dst_size) -+ return false; -+ if (filter->src_size != src_size) -+ return false; -+ if (filter->dst_size != dst_size) -+ return false; -+ if (filter->params.taps != params->taps) -+ return false; -+ if (filter->params.phases != params->phases) -+ return false; -+ if (filter->params.sharpness != params->sharpness) -+ return false; -+ -+ return true; -+} -+ -+/* -+ * @brief -+ * (scale_max - scale_min) -+ * result = scale_min + (value - value_min) * ----------------------- -+ * (value_max - value_min) -+ */ -+ -+static struct fixed31_32 interpolate( -+ struct fixed31_32 value, -+ struct fixed31_32 value_min, -+ struct fixed31_32 value_max, -+ struct fixed31_32 scale_min, -+ struct fixed31_32 scale_max) -+{ -+ return dal_fixed31_32_add( -+ scale_min, -+ dal_fixed31_32_div( -+ dal_fixed31_32_mul( -+ dal_fixed31_32_sub( -+ value, -+ value_min), -+ dal_fixed31_32_sub( -+ scale_max, -+ scale_min)), -+ dal_fixed31_32_sub( -+ value_max, -+ value_min))); -+} -+ -+static bool map_sharpness( -+ struct scaler_filter *filter, -+ const struct scaler_filter_params *params, -+ uint32_t src_size, -+ uint32_t dst_size, -+ struct fixed31_32 *attenuation, -+ struct fixed31_32 *decibels_at_nyquist) -+{ -+ struct fixed31_32 ratio = dal_fixed31_32_from_fraction( -+ dst_size, -+ src_size); -+ -+ const struct fixed31_32 sharp_flat = -+ dal_fixed31_32_from_fraction(MIN_SHARPNESS + MAX_SHARPNESS, 2); -+ -+ struct fixed31_32 sharp_max = -+ dal_fixed31_32_from_int(MAX_SHARPNESS); -+ struct fixed31_32 sharp_min = -+ dal_fixed31_32_from_int(MIN_SHARPNESS); -+ -+ uint32_t index = params->taps - 3; -+ -+ struct fixed31_32 ratio_low; -+ struct fixed31_32 ratio_up; -+ -+ struct fixed31_32 db_min; -+ struct fixed31_32 db_flat; -+ struct fixed31_32 db_max; -+ struct fixed31_32 db_value; -+ -+ uint32_t i0; -+ uint32_t i1; -+ uint32_t row0; -+ uint32_t row1; -+ -+ int32_t sharp = params->sharpness; -+ -+ if (sharp < MIN_SHARPNESS) -+ sharp = MIN_SHARPNESS; -+ else if (sharp > MAX_SHARPNESS) -+ sharp = MAX_SHARPNESS; -+ -+ if (params->flags.bits.HORIZONTAL) { -+ if (dal_fixed31_32_lt(ratio, max_hor_downscale())) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } else if (dal_fixed31_32_lt( -+ max_hor_upscale(), ratio)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ } else { -+ if (dal_fixed31_32_lt(ratio, max_ver_downscale())) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } else if (dal_fixed31_32_lt( -+ max_ver_upscale(), ratio)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ } -+ -+ if (dst_size >= src_size) { -+ if (sharp < 0) { -+ db_max = up_db_flat(); -+ db_min = up_db_fuzzy(); -+ -+ sharp_max = sharp_flat; -+ } else { -+ db_max = up_db_sharp(); -+ db_min = up_db_flat(); -+ -+ sharp_min = sharp_flat; -+ } -+ -+ db_value = interpolate( -+ dal_fixed31_32_from_int(sharp), -+ sharp_min, sharp_max, -+ db_min, db_max); -+ -+ i0 = 0; -+ -+ while (dal_fixed31_32_lt( -+ db_value, filter->upscaling_table[index][0][i0]) && -+ (i0 < UP_DB_POINTS - 1)) -+ ++i0; -+ -+ i1 = i0 + 1; -+ -+ if (i0 == UP_DB_POINTS - 1) -+ i1 = i0--; -+ -+ sharp_max = filter->upscaling_table[index][1][i0]; -+ sharp_min = filter->upscaling_table[index][1][i1]; -+ -+ db_max = filter->upscaling_table[index][0][i0]; -+ db_min = filter->upscaling_table[index][0][i1]; -+ -+ *attenuation = interpolate( -+ db_value, -+ db_max, db_min, -+ sharp_max, sharp_min); -+ -+ *decibels_at_nyquist = db_value; -+ -+ return true; -+ } else if ((5 * dst_size) < (src_size << 2)) { -+ if (sharp < 0) { -+ db_max = down_db_flat(); -+ db_min = down_db_fuzzy(); -+ -+ sharp_max = sharp_flat; -+ } else { -+ db_max = down_db_sharp(); -+ db_min = down_db_flat(); -+ -+ sharp_min = sharp_flat; -+ } -+ -+ db_value = interpolate( -+ dal_fixed31_32_from_int(sharp), -+ sharp_min, sharp_max, -+ db_min, db_max); -+ } else { -+ struct fixed31_32 db_value_min = -+ filter->downscaling_table[index][0][0]; -+ -+ struct fixed31_32 db_value_max = -+ filter->downscaling_table[index][0][DOWN_DB_POINTS - 1]; -+ -+ db_min = interpolate( -+ ratio, -+ threshold_ratio_low(), threshold_ratio_up(), -+ down_db_fuzzy(), up_db_fuzzy()); -+ -+ db_flat = interpolate( -+ ratio, -+ threshold_ratio_low(), threshold_ratio_up(), -+ down_db_flat(), up_db_flat()); -+ -+ db_max = interpolate( -+ ratio, -+ threshold_ratio_low(), threshold_ratio_up(), -+ down_db_sharp(), up_db_sharp()); -+ -+ if (sharp < 0) { -+ db_max = db_flat; -+ -+ db_value = interpolate( -+ dal_fixed31_32_from_int(sharp), -+ sharp_min, dal_fixed31_32_zero, -+ db_min, db_max); -+ } else { -+ db_min = db_flat; -+ -+ db_value = interpolate( -+ dal_fixed31_32_from_int(sharp), -+ dal_fixed31_32_zero, sharp_max, -+ db_min, db_max); -+ } -+ -+ if (dal_fixed31_32_lt(db_value_min, db_value)) -+ db_value = db_value_min; -+ else if (dal_fixed31_32_lt(db_value, db_value_max)) -+ db_value = db_value_max; -+ } -+ -+ i1 = 0; -+ -+ while (dal_fixed31_32_lt(db_value, -+ filter->downscaling_table[index][0][i1]) && -+ (i1 < DOWN_DB_POINTS - 1)) -+ ++i1; -+ -+ if (i1 == 0) -+ i0 = i1++; -+ else -+ i0 = i1 - 1; -+ -+ row0 = dal_fixed31_32_round( -+ dal_fixed31_32_mul_int(ratio, DOWN_DB_SCALES)); -+ -+ if (dal_fixed31_32_lt( -+ dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES), ratio)) { -+ row1 = row0 + 1; -+ -+ if (row1 > DOWN_DB_SCALES) { -+ row1 = DOWN_DB_SCALES; -+ row0 = row1 - 1; -+ } -+ } else { -+ row1 = row0--; -+ -+ if (row0 < 1) { -+ row0 = 1; -+ row1 = 2; -+ } -+ } -+ -+ ratio_low = dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES); -+ ratio_up = dal_fixed31_32_from_fraction(row1, DOWN_DB_SCALES); -+ -+ sharp_max = interpolate( -+ ratio, -+ ratio_low, ratio_up, -+ filter->downscaling_table[index][row0][i0], -+ filter->downscaling_table[index][row1][i0]); -+ -+ sharp_min = interpolate( -+ ratio, -+ ratio_low, ratio_up, -+ filter->downscaling_table[index][row0][i1], -+ filter->downscaling_table[index][row1][i1]); -+ -+ db_max = filter->downscaling_table[index][0][i0]; -+ db_min = filter->downscaling_table[index][0][i1]; -+ -+ *attenuation = interpolate( -+ db_value, -+ db_max, db_min, -+ sharp_max, sharp_min); -+ -+ *decibels_at_nyquist = db_value; -+ -+ return true; -+} -+ -+static inline struct fixed31_32 lanczos( -+ struct fixed31_32 x, -+ struct fixed31_32 a2) -+{ -+ return dal_fixed31_32_mul( -+ dal_fixed31_32_sinc(x), -+ dal_fixed31_32_sinc( -+ dal_fixed31_32_mul(x, a2))); -+} -+ -+static bool generate_filter( -+ struct scaler_filter *filter, -+ const struct scaler_filter_params *params, -+ struct fixed31_32 attenuation, -+ struct fixed31_32 *ringing) -+{ -+ uint32_t n = params->phases * params->taps; -+ -+ uint32_t coefficients_quantity = n; -+ uint32_t coefficients_sum_quantity = params->phases; -+ -+ uint32_t i; -+ uint32_t i_limit; -+ uint32_t j; -+ uint32_t m; -+ -+ struct fixed31_32 attenby2; -+ -+ struct fixed31_32 a_max = dal_fixed31_32_zero; -+ struct fixed31_32 a_min = dal_fixed31_32_zero; -+ -+ if (filter->coefficients_quantity < coefficients_quantity) { -+ if (filter->coefficients) { -+ dc_service_free(filter->ctx, filter->coefficients); -+ -+ filter->coefficients = NULL; -+ filter->coefficients_quantity = 0; -+ } -+ -+ filter->coefficients = dc_service_alloc( -+ filter->ctx, -+ coefficients_quantity * sizeof(struct fixed31_32)); -+ -+ if (!filter->coefficients) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ filter->coefficients_quantity = coefficients_quantity; -+ } -+ -+ i = 0; -+ -+ while (i != filter->coefficients_quantity) { -+ filter->coefficients[i] = dal_fixed31_32_zero; -+ -+ ++i; -+ } -+ -+ if (filter->coefficients_sum_quantity < coefficients_sum_quantity) { -+ if (filter->coefficients_sum) { -+ dc_service_free(filter->ctx, filter->coefficients_sum); -+ -+ filter->coefficients_sum = NULL; -+ filter->coefficients_sum_quantity = 0; -+ } -+ -+ filter->coefficients_sum = dc_service_alloc( -+ filter->ctx, -+ coefficients_sum_quantity * sizeof(struct fixed31_32)); -+ -+ if (!filter->coefficients_sum) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ filter->coefficients_sum_quantity = coefficients_sum_quantity; -+ } -+ -+ i = 0; -+ -+ while (i != filter->coefficients_sum_quantity) { -+ filter->coefficients_sum[i] = dal_fixed31_32_zero; -+ -+ ++i; -+ } -+ -+ m = 0; -+ -+ attenby2 = dal_fixed31_32_div_int( -+ dal_fixed31_32_mul_int(attenuation, params->taps), 2); -+ -+ i = 1; -+ -+ while (i <= params->taps) { -+ j = 0; -+ -+ while (j != params->phases) { -+ struct fixed31_32 x = dal_fixed31_32_mul( -+ dal_fixed31_32_pi, -+ dal_fixed31_32_from_fraction( -+ (int64_t)(m << 1) - n, n)); -+ -+ uint32_t index = -+ (params->taps - i) * params->phases + j; -+ -+ filter->coefficients[index] = lanczos(x, attenby2); -+ -+ ++m; -+ -+ ++j; -+ } -+ -+ ++i; -+ } -+ -+ i = 0; -+ -+ while (i != params->phases) { -+ filter->coefficients_sum[i] = dal_fixed31_32_zero; -+ -+ m = i; -+ -+ j = 0; -+ -+ while (j != params->taps) { -+ filter->coefficients_sum[i] = -+ dal_fixed31_32_add( -+ filter->coefficients_sum[i], -+ filter->coefficients[m]); -+ -+ m += params->phases; -+ -+ ++j; -+ } -+ -+ ++i; -+ } -+ -+ i = 0; -+ -+ while (i != params->phases) { -+ m = i; -+ -+ j = 0; -+ -+ while (j != params->taps) { -+ filter->coefficients[m] = -+ dal_fixed31_32_div( -+ filter->coefficients[m], -+ filter->coefficients_sum[i]); -+ -+ m += params->phases; -+ -+ ++j; -+ } -+ -+ ++i; -+ } -+ -+ i = 0; -+ i_limit = (params->phases >> 1) + 1; -+ -+ while (i != i_limit) { -+ m = i; -+ -+ j = 0; -+ -+ while (j != params->taps) { -+ struct fixed31_32 tmp = filter->coefficients[m]; -+ -+ filter->filter[i * params->taps + j] = tmp; -+ -+ if (dal_fixed31_32_lt( -+ tmp, dal_fixed31_32_zero) && -+ dal_fixed31_32_lt(tmp, a_min)) -+ a_min = tmp; -+ else if (dal_fixed31_32_lt( -+ dal_fixed31_32_zero, tmp) && -+ dal_fixed31_32_lt(a_max, tmp)) -+ a_max = tmp; -+ -+ m += params->phases; -+ -+ ++j; -+ } -+ -+ ++i; -+ } -+ -+ if (dal_fixed31_32_eq(a_min, dal_fixed31_32_zero)) -+ *ringing = dal_fixed31_32_from_int(100); -+ else -+ *ringing = dal_fixed31_32_min( -+ dal_fixed31_32_abs( -+ dal_fixed31_32_div(a_max, a_min)), -+ dal_fixed31_32_from_int(100)); -+ -+ return true; -+} -+ -+static bool construct_scaler_filter( -+ struct dc_context *ctx, -+ struct scaler_filter *filter) -+{ -+ filter->src_size = 0; -+ filter->dst_size = 0; -+ filter->filter = NULL; -+ filter->integer_filter = NULL; -+ filter->filter_size_allocated = 0; -+ filter->filter_size_effective = 0; -+ filter->coefficients = NULL; -+ filter->coefficients_quantity = 0; -+ filter->coefficients_sum = NULL; -+ filter->coefficients_sum_quantity = 0; -+ filter->downscaling_table = NULL; -+ filter->upscaling_table = NULL; -+ filter->ctx = ctx; -+ -+ if (!create_downscaling_table(filter)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!create_upscaling_table(filter)) { -+ BREAK_TO_DEBUGGER(); -+ destroy_downscaling_table(filter); -+ return false; -+ } -+ -+ return true; -+} -+ -+static void destruct_scaler_filter( -+ struct scaler_filter *filter) -+{ -+ if (filter->coefficients_sum) -+ dc_service_free(filter->ctx, filter->coefficients_sum); -+ -+ if (filter->coefficients) -+ dc_service_free(filter->ctx, filter->coefficients); -+ -+ if (filter->integer_filter) -+ dc_service_free(filter->ctx, filter->integer_filter); -+ -+ if (filter->filter) -+ dc_service_free(filter->ctx, filter->filter); -+ -+ destroy_upscaling_table(filter); -+ -+ destroy_downscaling_table(filter); -+} -+ -+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx) -+{ -+ struct scaler_filter *filter = -+ dc_service_alloc(ctx, sizeof(struct scaler_filter)); -+ -+ if (!filter) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (construct_scaler_filter(ctx, filter)) -+ return filter; -+ -+ BREAK_TO_DEBUGGER(); -+ -+ dc_service_free(ctx, filter); -+ -+ return NULL; -+} -+ -+bool dal_scaler_filter_generate( -+ struct scaler_filter *filter, -+ const struct scaler_filter_params *params, -+ uint32_t src_size, -+ uint32_t dst_size) -+{ -+ uint32_t filter_size_required; -+ -+ struct fixed31_32 attenuation; -+ struct fixed31_32 decibels_at_nyquist; -+ struct fixed31_32 ringing; -+ -+ if (!params) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if ((params->taps < 3) || (params->taps > 16)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!src_size || !dst_size) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (same_filter_required(filter, params, src_size, dst_size)) -+ return true; -+ -+ filter_size_required = -+ params->taps * ((params->phases >> 1) + 1); -+ -+ if (filter_size_required > filter->filter_size_allocated) { -+ if (filter->filter) { -+ dc_service_free(filter->ctx, filter->filter); -+ -+ filter->filter = 0; -+ filter->filter_size_allocated = 0; -+ } -+ -+ filter->filter = dc_service_alloc( -+ filter->ctx, -+ filter_size_required * sizeof(struct fixed31_32)); -+ -+ if (!filter->filter) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (filter->integer_filter) { -+ dc_service_free(filter->ctx, filter->integer_filter); -+ -+ filter->integer_filter = 0; -+ } -+ -+ filter->integer_filter = dc_service_alloc( -+ filter->ctx, -+ filter_size_required * sizeof(uint32_t)); -+ -+ if (!filter->integer_filter) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ filter->filter_size_allocated = filter_size_required; -+ } -+ -+ filter->filter_size_effective = filter_size_required; -+ -+ if (!map_sharpness(filter, params, src_size, dst_size, -+ &attenuation, &decibels_at_nyquist)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!generate_filter(filter, params, attenuation, &ringing)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ filter->params = *params; -+ filter->src_size = src_size; -+ filter->dst_size = dst_size; -+ -+ return true; -+} -+ -+const struct fixed31_32 *dal_scaler_filter_get( -+ const struct scaler_filter *filter, -+ uint32_t **data, -+ uint32_t *number) -+{ -+ if (!number) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (!data) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ *number = filter->filter_size_effective; -+ *data = filter->integer_filter; -+ -+ return filter->filter; -+} -+ -+void dal_scaler_filter_destroy( -+ struct scaler_filter **filter) -+{ -+ if (!filter || !*filter) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ destruct_scaler_filter(*filter); -+ -+ dc_service_free((*filter)->ctx, *filter); -+ -+ *filter = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h -new file mode 100644 -index 0000000..668691d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h -@@ -0,0 +1,74 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_SCALER_FILTER_H__ -+#define __DAL_SCALER_FILTER_H__ -+ -+struct scaler_filter_params { -+ uint32_t taps; /* 3...16 */ -+ uint32_t phases; -+ int32_t sharpness; /* -50...50 */ -+ union { -+ struct { -+ uint32_t HORIZONTAL:1; -+ uint32_t RESERVED:31; -+ } bits; -+ uint32_t value; -+ } flags; -+}; -+ -+struct q31_32; -+ -+struct scaler_filter { -+ struct scaler_filter_params params; -+ uint32_t src_size; -+ uint32_t dst_size; -+ struct fixed31_32 *filter; -+ uint32_t *integer_filter; -+ uint32_t filter_size_allocated; -+ uint32_t filter_size_effective; -+ struct fixed31_32 *coefficients; -+ uint32_t coefficients_quantity; -+ struct fixed31_32 *coefficients_sum; -+ uint32_t coefficients_sum_quantity; -+ struct fixed31_32 ***downscaling_table; -+ struct fixed31_32 ***upscaling_table; -+ struct dc_context *ctx; -+}; -+ -+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx); -+void dal_scaler_filter_destroy(struct scaler_filter **ptr); -+ -+bool dal_scaler_filter_generate( -+ struct scaler_filter *filter, -+ const struct scaler_filter_params *params, -+ uint32_t src_size, -+ uint32_t dst_size); -+ -+const struct fixed31_32 *dal_scaler_filter_get( -+ const struct scaler_filter *filter, -+ uint32_t **data, -+ uint32_t *number); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/connector/Makefile b/drivers/gpu/drm/amd/dal/dc/connector/Makefile -new file mode 100644 -index 0000000..ebd4115 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/connector/Makefile -@@ -0,0 +1,10 @@ -+# -+# Makefile for the 'connector' sub-component of DAL. -+# It provides the control and status of HW connectors blocks. -+ -+ -+CONNECTOR = connector_base.o connector_signals.o -+ -+AMD_DAL_CONNECTOR = $(addprefix $(AMDDALPATH)/dc/connector/,$(CONNECTOR)) -+ -+AMD_DAL_FILES += $(AMD_DAL_CONNECTOR) -diff --git a/drivers/gpu/drm/amd/dal/dc/connector/connector.h b/drivers/gpu/drm/amd/dal/dc/connector/connector.h -new file mode 100644 -index 0000000..7d6057b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/connector/connector.h -@@ -0,0 +1,39 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_CONNECTOR_H__ -+#define __DAL_CONNECTOR_H__ -+ -+#include "include/connector_interface.h" -+ -+extern const uint32_t number_of_default_signals; -+extern const uint32_t number_of_signals; -+ -+/* Indexed by enum connector_id */ -+extern const struct connector_signals default_signals[]; -+/* Indexed by enum connector_id */ -+extern const struct connector_signals supported_signals[]; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/connector/connector_base.c b/drivers/gpu/drm/amd/dal/dc/connector/connector_base.c -new file mode 100644 -index 0000000..34005fd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/connector/connector_base.c -@@ -0,0 +1,421 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "connector.h" -+#include "include/irq_interface.h" -+#include "include/ddc_interface.h" -+#include "include/connector_interface.h" -+ -+struct connector { -+ struct graphics_object_id id; -+ uint32_t input_signals; -+ uint32_t output_signals; -+ struct adapter_service *as; -+ struct connector_feature_support features; -+ struct connector_signals default_signals; -+ struct dc_context *ctx; -+}; -+ -+static bool connector_construct( -+ struct connector *connector, -+ struct dc_context *ctx, -+ struct adapter_service *as, -+ struct graphics_object_id go_id) -+{ -+ bool hw_ddc_polling = false; -+ struct ddc *ddc; -+ struct irq *hpd; -+ enum connector_id connector_id; -+ uint32_t signals_vector = 0; -+ uint32_t signals_num = 0; -+ uint32_t i; -+ -+ if (!as) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ connector->as = as; -+ connector->id = go_id; -+ connector->features.ddc_line = CHANNEL_ID_UNKNOWN; -+ connector->features.hpd_line = HPD_SOURCEID_UNKNOWN; -+ connector->ctx = ctx; -+ -+ ddc = dal_adapter_service_obtain_ddc(as, connector->id); -+ hpd = dal_adapter_service_obtain_hpd_irq(as, connector->id); -+ -+ connector_id = dal_graphics_object_id_get_connector_id(go_id); -+ -+ /* Initialize DDC line */ -+ if (ddc) { -+ switch (dal_ddc_get_line(ddc)) { -+ case GPIO_DDC_LINE_DDC1: -+ connector->features.ddc_line = CHANNEL_ID_DDC1; -+ break; -+ case GPIO_DDC_LINE_DDC2: -+ connector->features.ddc_line = CHANNEL_ID_DDC2; -+ break; -+ case GPIO_DDC_LINE_DDC3: -+ connector->features.ddc_line = CHANNEL_ID_DDC3; -+ break; -+ case GPIO_DDC_LINE_DDC4: -+ connector->features.ddc_line = CHANNEL_ID_DDC4; -+ break; -+ case GPIO_DDC_LINE_DDC5: -+ connector->features.ddc_line = CHANNEL_ID_DDC5; -+ break; -+ case GPIO_DDC_LINE_DDC6: -+ connector->features.ddc_line = CHANNEL_ID_DDC6; -+ break; -+ case GPIO_DDC_LINE_DDC_VGA: -+ connector->features.ddc_line = CHANNEL_ID_DDC_VGA; -+ break; -+ case GPIO_DDC_LINE_I2C_PAD: -+ connector->features.ddc_line = CHANNEL_ID_I2C_PAD; -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ break; -+ } -+ -+ /* Initialize HW DDC polling support -+ * On DCE6.0 only DDC lines support HW polling (I2cPad does not) -+ */ -+ -+ if (dal_adapter_service_is_feature_supported( -+ FEATURE_ENABLE_HW_EDID_POLLING)) { -+ switch (dal_ddc_get_line(ddc)) { -+ case GPIO_DDC_LINE_DDC1: -+ case GPIO_DDC_LINE_DDC2: -+ case GPIO_DDC_LINE_DDC3: -+ case GPIO_DDC_LINE_DDC4: -+ case GPIO_DDC_LINE_DDC5: -+ case GPIO_DDC_LINE_DDC6: -+ case GPIO_DDC_LINE_DDC_VGA: -+ hw_ddc_polling = true; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ dal_adapter_service_release_ddc(as, ddc); -+ } -+ -+ /* Initialize HPD line */ -+ if (hpd) { -+ switch (dal_irq_get_source(hpd)) { -+ case DC_IRQ_SOURCE_HPD1: -+ connector->features.hpd_line = HPD_SOURCEID1; -+ break; -+ case DC_IRQ_SOURCE_HPD2: -+ connector->features.hpd_line = HPD_SOURCEID2; -+ break; -+ case DC_IRQ_SOURCE_HPD3: -+ connector->features.hpd_line = HPD_SOURCEID3; -+ break; -+ case DC_IRQ_SOURCE_HPD4: -+ connector->features.hpd_line = HPD_SOURCEID4; -+ break; -+ case DC_IRQ_SOURCE_HPD5: -+ connector->features.hpd_line = HPD_SOURCEID5; -+ break; -+ case DC_IRQ_SOURCE_HPD6: -+ connector->features.hpd_line = HPD_SOURCEID6; -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ break; -+ } -+ -+ dal_adapter_service_release_irq(as, hpd); -+ } -+ -+ if ((uint32_t)connector_id >= number_of_default_signals && -+ (uint32_t)connector_id >= number_of_signals) -+ return false; -+ -+ /* Initialize default signals */ -+ connector->default_signals = default_signals[connector_id]; -+ -+ /* Fill supported signals */ -+ signals_num = supported_signals[connector_id].number_of_signals; -+ for (i = 0; i < signals_num; i++) -+ signals_vector |= supported_signals[connector_id].signal[i]; -+ -+ /* Connector supports same set for input and output signals */ -+ connector->input_signals = signals_vector; -+ connector->output_signals = signals_vector; -+ -+ switch (connector_id) { -+ case CONNECTOR_ID_VGA: -+ if (hw_ddc_polling -+ && connector->features.ddc_line != CHANNEL_ID_UNKNOWN) -+ connector->features.HW_DDC_POLLING = true; -+ break; -+ case CONNECTOR_ID_SINGLE_LINK_DVII: -+ case CONNECTOR_ID_DUAL_LINK_DVII: -+ if (connector->features.hpd_line != HPD_SOURCEID_UNKNOWN) -+ connector->features.HPD_FILTERING = true; -+ if (hw_ddc_polling -+ && connector->features.ddc_line != CHANNEL_ID_UNKNOWN) -+ connector->features.HW_DDC_POLLING = true; -+ break; -+ case CONNECTOR_ID_SINGLE_LINK_DVID: -+ case CONNECTOR_ID_DUAL_LINK_DVID: -+ case CONNECTOR_ID_HDMI_TYPE_A: -+ case CONNECTOR_ID_LVDS: -+ case CONNECTOR_ID_DISPLAY_PORT: -+ case CONNECTOR_ID_EDP: -+ if (connector->features.hpd_line != HPD_SOURCEID_UNKNOWN) -+ connector->features.HPD_FILTERING = true; -+ break; -+ default: -+ connector->features.HPD_FILTERING = false; -+ connector->features.HW_DDC_POLLING = false; -+ break; -+ } -+ -+ return true; -+} -+ -+struct connector *dal_connector_create( -+ struct dc_context *ctx, -+ struct adapter_service *as, -+ struct graphics_object_id go_id) -+{ -+ struct connector *connector = NULL; -+ -+ connector = dc_service_alloc(ctx, sizeof(struct connector)); -+ -+ if (!connector) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (connector_construct(connector, ctx, as, go_id)) -+ return connector; -+ -+ BREAK_TO_DEBUGGER(); -+ -+ dc_service_free(ctx, connector); -+ -+ return NULL; -+} -+ -+void dal_connector_destroy(struct connector **connector) -+{ -+ if (!connector || !*connector) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ dc_service_free((*connector)->ctx, *connector); -+ -+ *connector = NULL; -+} -+ -+uint32_t dal_connector_enumerate_output_signals( -+ const struct connector *connector) -+{ -+ return connector->output_signals; -+} -+ -+uint32_t dal_connector_enumerate_input_signals( -+ const struct connector *connector) -+{ -+ return connector->input_signals; -+} -+ -+struct connector_signals dal_connector_get_default_signals( -+ const struct connector *connector) -+{ -+ return connector->default_signals; -+} -+ -+const struct graphics_object_id dal_connector_get_graphics_object_id( -+ const struct connector *connector) -+{ -+ return connector->id; -+} -+ -+/* -+ * 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 -+ */ -+bool dal_connector_program_hpd_filter( -+ const struct connector *connector, -+ const uint32_t delay_on_connect_in_ms, -+ const uint32_t delay_on_disconnect_in_ms) -+{ -+ bool result = false; -+ -+ struct irq *hpd; -+ -+ /* Verify feature is supported */ -+ -+ if (!connector->features.HPD_FILTERING) -+ return result; -+ -+ /* Obtain HPD handle */ -+ -+ hpd = dal_adapter_service_obtain_hpd_irq( -+ connector->as, connector->id); -+ -+ if (!hpd) -+ return result; -+ -+ /* Setup HPD filtering */ -+ -+ if (GPIO_RESULT_OK == dal_irq_open(hpd)) { -+ struct gpio_hpd_config config; -+ -+ config.delay_on_connect = delay_on_connect_in_ms; -+ config.delay_on_disconnect = delay_on_disconnect_in_ms; -+ -+ dal_irq_setup_hpd_filter(hpd, &config); -+ -+ dal_irq_close(hpd); -+ -+ result = true; -+ } else { -+ ASSERT_CRITICAL(false); -+ } -+ -+ /* Release HPD handle */ -+ -+ dal_adapter_service_release_irq(connector->as, hpd); -+ -+ return result; -+} -+ -+/* -+ * Function: setup_ddc_polling -+ * -+ * @brief -+ * Enables/Disables HW polling on associated DDC line -+ * -+ * @param [in] ddc_config: Specifies polling mode -+ * -+ * @return -+ * true on success, false otherwise -+ */ -+static bool setup_ddc_polling( -+ const struct connector *connector, -+ enum gpio_ddc_config_type ddc_config) -+{ -+ bool result = false; -+ -+ struct ddc *ddc; -+ -+ /* Verify feature is supported */ -+ -+ if (!connector->features.HW_DDC_POLLING) -+ return result; -+ -+ /* Obtain DDC handle */ -+ -+ ddc = dal_adapter_service_obtain_ddc( -+ connector->as, connector->id); -+ -+ if (!ddc) { -+ BREAK_TO_DEBUGGER(); -+ return result; -+ } -+ -+ /* Setup DDC polling */ -+ -+ if (GPIO_RESULT_OK == dal_ddc_open(ddc, GPIO_MODE_HARDWARE, -+ GPIO_DDC_CONFIG_TYPE_MODE_I2C)) { -+ dal_ddc_set_config(ddc, ddc_config); -+ -+ dal_ddc_close(ddc); -+ -+ result = true; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ } -+ -+ /* Release DDC handle */ -+ -+ dal_adapter_service_release_ddc(connector->as, ddc); -+ -+ return result; -+} -+ -+/* -+ * Function: enable_ddc_polling -+ * -+ * @brief -+ * Enables HW polling on associated DDC line -+ * -+ * @param [in] is_poll_for_connect: Specifies polling mode -+ * -+ * @return -+ * true on success, false otherwise -+ */ -+bool dal_connector_enable_ddc_polling( -+ const struct connector *connector, -+ const bool is_poll_for_connect) -+{ -+ enum gpio_ddc_config_type ddc_config = is_poll_for_connect ? -+ GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT : -+ GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT; -+ -+ return setup_ddc_polling(connector, ddc_config); -+} -+ -+/* -+ * Function: disable_ddc_polling -+ * -+ * @brief -+ * Disables HW polling on associated DDC line -+ * -+ * @return -+ * true on success, false otherwise -+ */ -+bool dal_connector_disable_ddc_polling(const struct connector *connector) -+{ -+ return setup_ddc_polling(connector, -+ GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING); -+} -+ -+void dal_connector_get_features( -+ const struct connector *con, -+ struct connector_feature_support *cfs) -+{ -+ dc_service_memmove(cfs, &con->features, -+ sizeof(struct connector_feature_support)); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/connector/connector_signals.c b/drivers/gpu/drm/amd/dal/dc/connector/connector_signals.c -new file mode 100644 -index 0000000..d1a289d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/connector/connector_signals.c -@@ -0,0 +1,204 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "connector.h" -+ -+static const enum signal_type signals_none[] = { -+ SIGNAL_TYPE_NONE -+}; -+ -+static const enum signal_type signals_single_link_dvii[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type signals_dual_link_dvii[] = { -+ SIGNAL_TYPE_DVI_DUAL_LINK, -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type signals_single_link_dvid[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK -+}; -+ -+static const enum signal_type signals_dual_link_dvid[] = { -+ SIGNAL_TYPE_DVI_DUAL_LINK, -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+}; -+ -+static const enum signal_type signals_vga[] = { -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type signals_hdmi_type_a[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_HDMI_TYPE_A -+}; -+ -+static const enum signal_type signals_lvds[] = { -+ SIGNAL_TYPE_LVDS -+}; -+ -+static const enum signal_type signals_pcie[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_HDMI_TYPE_A, -+ SIGNAL_TYPE_DISPLAY_PORT -+}; -+ -+static const enum signal_type signals_hardcode_dvi[] = { -+ SIGNAL_TYPE_NONE -+}; -+ -+static const enum signal_type signals_displayport[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_HDMI_TYPE_A, -+ SIGNAL_TYPE_DISPLAY_PORT, -+ SIGNAL_TYPE_DISPLAY_PORT_MST -+}; -+ -+static const enum signal_type signals_edp[] = { -+ SIGNAL_TYPE_EDP -+}; -+ -+static const enum signal_type signals_wireless[] = { -+ SIGNAL_TYPE_WIRELESS -+}; -+ -+static const enum signal_type signals_miracast[] = { -+ SIGNAL_TYPE_WIRELESS -+}; -+ -+static const enum signal_type default_signals_none[] = { -+ SIGNAL_TYPE_NONE -+}; -+ -+static const enum signal_type default_signals_single_link_dvii[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK, -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type default_signals_dual_link_dvii[] = { -+ SIGNAL_TYPE_DVI_DUAL_LINK, -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type default_signals_single_link_dvid[] = { -+ SIGNAL_TYPE_DVI_SINGLE_LINK -+}; -+ -+static const enum signal_type default_signals_dual_link_dvid[] = { -+ SIGNAL_TYPE_DVI_DUAL_LINK, -+}; -+ -+static const enum signal_type default_signals_vga[] = { -+ SIGNAL_TYPE_RGB -+}; -+ -+static const enum signal_type default_signals_hdmi_type_a[] = { -+ SIGNAL_TYPE_HDMI_TYPE_A -+}; -+ -+static const enum signal_type default_signals_lvds[] = { -+ SIGNAL_TYPE_LVDS -+}; -+ -+static const enum signal_type default_signals_pcie[] = { -+ SIGNAL_TYPE_DISPLAY_PORT -+}; -+ -+static const enum signal_type default_signals_hardcode_dvi[] = { -+ SIGNAL_TYPE_NONE -+}; -+ -+static const enum signal_type default_signals_displayport[] = { -+ SIGNAL_TYPE_DISPLAY_PORT -+}; -+ -+static const enum signal_type default_signals_edp[] = { -+ SIGNAL_TYPE_EDP -+}; -+ -+static const enum signal_type default_signals_wireless[] = { -+ SIGNAL_TYPE_WIRELESS -+}; -+ -+static const enum signal_type default_signals_miracast[] = { -+ SIGNAL_TYPE_WIRELESS -+}; -+ -+/* -+ * Signal arrays -+ */ -+ -+#define SIGNALS_ARRAY_ELEM(a) {a, ARRAY_SIZE(a)} -+ -+/* Indexed by enum connector_id */ -+const struct connector_signals default_signals[] = { -+ SIGNALS_ARRAY_ELEM(default_signals_none), -+ SIGNALS_ARRAY_ELEM(default_signals_single_link_dvii), -+ SIGNALS_ARRAY_ELEM(default_signals_dual_link_dvii), -+ SIGNALS_ARRAY_ELEM(default_signals_single_link_dvid), -+ SIGNALS_ARRAY_ELEM(default_signals_dual_link_dvid), -+ SIGNALS_ARRAY_ELEM(default_signals_vga), -+ SIGNALS_ARRAY_ELEM(default_signals_hdmi_type_a), -+ SIGNALS_ARRAY_ELEM(default_signals_none), -+ SIGNALS_ARRAY_ELEM(default_signals_lvds), -+ SIGNALS_ARRAY_ELEM(default_signals_pcie), -+ SIGNALS_ARRAY_ELEM(default_signals_hardcode_dvi), -+ SIGNALS_ARRAY_ELEM(default_signals_displayport), -+ SIGNALS_ARRAY_ELEM(default_signals_edp), -+ /* MXM dummy connector */ -+ SIGNALS_ARRAY_ELEM(default_signals_none), -+ SIGNALS_ARRAY_ELEM(default_signals_wireless), -+ SIGNALS_ARRAY_ELEM(default_signals_miracast) -+}; -+ -+const uint32_t number_of_default_signals = ARRAY_SIZE(default_signals); -+ -+/* Indexed by enum connector_id */ -+const struct connector_signals supported_signals[] = { -+ SIGNALS_ARRAY_ELEM(signals_none), -+ SIGNALS_ARRAY_ELEM(signals_single_link_dvii), -+ SIGNALS_ARRAY_ELEM(signals_dual_link_dvii), -+ SIGNALS_ARRAY_ELEM(signals_single_link_dvid), -+ SIGNALS_ARRAY_ELEM(signals_dual_link_dvid), -+ SIGNALS_ARRAY_ELEM(signals_vga), -+ SIGNALS_ARRAY_ELEM(signals_hdmi_type_a), -+ SIGNALS_ARRAY_ELEM(signals_none), -+ SIGNALS_ARRAY_ELEM(signals_lvds), -+ SIGNALS_ARRAY_ELEM(signals_pcie), -+ SIGNALS_ARRAY_ELEM(signals_hardcode_dvi), -+ SIGNALS_ARRAY_ELEM(signals_displayport), -+ SIGNALS_ARRAY_ELEM(signals_edp), -+ /* MXM dummy connector */ -+ SIGNALS_ARRAY_ELEM(signals_none), -+ SIGNALS_ARRAY_ELEM(signals_wireless), -+ SIGNALS_ARRAY_ELEM(signals_miracast) -+}; -+ -+const uint32_t number_of_signals = ARRAY_SIZE(supported_signals); -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c -new file mode 100644 -index 0000000..e13ce4e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c -@@ -0,0 +1,849 @@ -+/* -+ * 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 "dc_services.h" -+ -+#include "dc.h" -+ -+#include "core_status.h" -+#include "core_types.h" -+#include "hw_sequencer.h" -+ -+#include "resource.h" -+ -+#include "adapter_service_interface.h" -+#include "clock_source_interface.h" -+ -+#include "include/irq_service_interface.h" -+#include "bandwidth_calcs.h" -+#include "include/irq_service_interface.h" -+ -+#include "link_hwss.h" -+ -+/******************************************************************************* -+ * Private structures -+ ******************************************************************************/ -+ -+struct dc_target_sync_report { -+ uint32_t h_count; -+ uint32_t v_count; -+}; -+ -+struct dc_sync_report { -+ uint32_t targets_num; -+ struct dc_target_sync_report trg_reports[MAX_TARGET_NUM]; -+}; -+ -+/******************************************************************************* -+ * Private functions -+ ******************************************************************************/ -+static void destroy_links(struct dc *dc) -+{ -+ uint32_t i; -+ -+ for (i = 0; i < dc->link_count; i++) { -+ -+ if (NULL != dc->links[i]) -+ link_destroy(&dc->links[i]); -+ } -+} -+ -+ -+static bool create_links(struct dc *dc, const struct dc_init_data *init_params) -+{ -+ int i; -+ int connectors_num; -+ -+ dc->link_count = 0; -+ -+ connectors_num = dal_bios_parser_get_connectors_number( -+ dal_adapter_service_get_bios_parser( -+ init_params->adapter_srv)); -+ -+ if (0 == connectors_num || connectors_num > ENUM_ID_COUNT) { -+ dal_error("DC: Invalid number of connectors!\n"); -+ return false; -+ } -+ -+ dal_output_to_console("%s: connectors_num:%d\n", __func__, -+ connectors_num); -+ -+ dc->links = dc_service_alloc( -+ init_params->ctx, connectors_num * sizeof(struct core_link *)); -+ -+ if (NULL == dc->links) { -+ dal_error("DC: failed to allocate 'links' storage!\n"); -+ goto allocate_dc_links_storage_fail; -+ } -+ -+ for (i = 0; i < connectors_num; i++) { -+ struct link_init_data link_init_params = {0}; -+ struct core_link *link; -+ -+ link_init_params.ctx = init_params->ctx; -+ link_init_params.adapter_srv = init_params->adapter_srv; -+ link_init_params.connector_index = i; -+ link_init_params.link_index = dc->link_count; -+ link_init_params.dc = dc; -+ link = link_create(&link_init_params); -+ -+ if (link) { -+ dc->links[dc->link_count] = link; -+ link->dc = dc; -+ ++dc->link_count; -+ } -+ else { -+ dal_error("DC: failed to create link!\n"); -+ } -+ } -+ -+ if (!dc->link_count) { -+ dal_error("DC: no 'links' were created!\n"); -+ goto allocate_dc_links_storage_fail; -+ } -+ -+ return true; -+ -+allocate_dc_links_storage_fail: -+ return false; -+} -+ -+static void init_hw(struct dc *dc) -+{ -+ int i; -+ struct bios_parser *bp; -+ struct transform *xfm; -+ -+ bp = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv); -+ for(i = 0; i < dc->res_pool.controller_count; i++) { -+ xfm = dc->res_pool.transforms[i]; -+ -+ dc->hwss.enable_display_power_gating( -+ dc->ctx, i, bp, -+ PIPE_GATING_CONTROL_INIT); -+ dc->hwss.enable_display_power_gating( -+ dc->ctx, i, bp, -+ PIPE_GATING_CONTROL_DISABLE); -+ -+ dc->hwss.transform_power_up(xfm); -+ dc->hwss.enable_display_pipe_clock_gating( -+ dc->ctx, -+ true); -+ } -+ -+ dc->hwss.clock_gating_power_up(dc->ctx, false); -+ dal_bios_parser_power_up(bp); -+ /***************************************/ -+ -+ for (i = 0; i < dc->link_count; i++) { -+ /****************************************/ -+ /* Power up AND update implementation according to the -+ * required signal (which may be different from the -+ * default signal on connector). */ -+ struct core_link *link = dc->links[i]; -+ if (dc->hwss.encoder_power_up(link->link_enc) != ENCODER_RESULT_OK) { -+ dal_error("Failed link encoder power up!\n"); -+ return; -+ } -+ } -+ -+ dal_bios_parser_set_scratch_acc_mode_change(bp); -+ -+ for(i = 0; i < dc->res_pool.controller_count; i++) { -+ struct timing_generator *tg = dc->res_pool.timing_generators[i]; -+ -+ dc->hwss.disable_vga(tg); -+ -+ /* Blank controller using driver code instead of -+ * command table. */ -+ dc->hwss.disable_memory_requests(tg); -+ } -+ -+ for(i = 0; i < dc->res_pool.audio_count; i++) { -+ struct audio *audio = dc->res_pool.audios[i]; -+ -+ if (dal_audio_power_up(audio) != AUDIO_RESULT_OK) -+ dal_error("Failed audio power up!\n"); -+ } -+ -+} -+ -+static struct adapter_service *create_as( -+ struct dc_init_data *dc_init_data, -+ const struct dal_init_data *init) -+{ -+ struct adapter_service *as = NULL; -+ struct as_init_data init_data; -+ -+ dc_service_memset(&init_data, 0, sizeof(init_data)); -+ -+ init_data.ctx = dc_init_data->ctx; -+ -+ /* BIOS parser init data */ -+ init_data.bp_init_data.ctx = dc_init_data->ctx; -+ init_data.bp_init_data.bios = init->asic_id.atombios_base_address; -+ -+ /* HW init data */ -+ init_data.hw_init_data.chip_id = init->asic_id.chip_id; -+ init_data.hw_init_data.chip_family = init->asic_id.chip_family; -+ init_data.hw_init_data.pci_revision_id = init->asic_id.pci_revision_id; -+ init_data.hw_init_data.fake_paths_num = init->asic_id.fake_paths_num; -+ init_data.hw_init_data.feature_flags = init->asic_id.feature_flags; -+ init_data.hw_init_data.hw_internal_rev = init->asic_id.hw_internal_rev; -+ init_data.hw_init_data.runtime_flags = init->asic_id.runtime_flags; -+ init_data.hw_init_data.vram_width = init->asic_id.vram_width; -+ init_data.hw_init_data.vram_type = init->asic_id.vram_type; -+ -+ /* bdf is BUS,DEVICE,FUNCTION*/ -+ init_data.bdf_info = init->bdf_info; -+ -+ init_data.display_param = &init->display_param; -+ -+ as = dal_adapter_service_create(&init_data); -+ -+ return as; -+} -+ -+static void bw_calcs_data_update_from_pplib(struct dc *dc) -+{ -+ struct dal_system_clock_range clk_range = { 0 }; -+ -+ dc_service_get_system_clocks_range(dc->ctx, &clk_range); -+ -+ /* on CZ Gardenia from PPLib we get: -+ * clk_range.max_mclk:80000 -+ * clk_range.min_mclk:80000 -+ * clk_range.max_sclk:80000 -+ * clk_range.min_sclk:30000 */ -+ -+ /* The values for calcs are stored in units of MHz, so for example -+ * 80000 will be stored as 800. */ -+ dc->bw_vbios.high_sclk = frc_to_fixed(clk_range.max_sclk, 100); -+ dc->bw_vbios.low_sclk = frc_to_fixed(clk_range.min_sclk, 100); -+ -+ dc->bw_vbios.high_yclk = frc_to_fixed(clk_range.max_mclk, 100); -+ dc->bw_vbios.low_yclk = frc_to_fixed(clk_range.min_mclk, 100); -+} -+ -+static bool construct(struct dc *dc, const struct dal_init_data *init_params) -+{ -+ struct dal_logger *logger; -+ /* Tempory code -+ * TODO: replace dal_init_data with dc_init_data when dal is removed -+ */ -+ struct dc_init_data dc_init_data = {0}; -+ -+ /* Create dc context */ -+ /* A temp dc context is used only to allocate the memory for actual -+ * dc context */ -+ struct dc_context ctx = {0}; -+ ctx.cgs_device = init_params->cgs_device; -+ ctx.dc = dc; -+ -+ dc_init_data.ctx = dc_service_alloc(&ctx, sizeof(*dc_init_data.ctx)); -+ if (!dc_init_data.ctx) { -+ dal_error("%s: failed to create ctx\n", __func__); -+ goto ctx_fail; -+ } -+ dc_init_data.ctx->driver_context = init_params->driver; -+ dc_init_data.ctx->cgs_device = init_params->cgs_device; -+ dc_init_data.ctx->dc = dc; -+ -+ /* Create logger */ -+ logger = dal_logger_create(dc_init_data.ctx); -+ -+ if (!logger) { -+ /* can *not* call logger. call base driver 'print error' */ -+ dal_error("%s: failed to create Logger!\n", __func__); -+ goto logger_fail; -+ } -+ dc_init_data.ctx->logger = logger; -+ -+ /* Create adapter service */ -+ dc_init_data.adapter_srv = create_as(&dc_init_data, init_params); -+ -+ if (!dc_init_data.adapter_srv) { -+ dal_error("%s: create_as() failed!\n", __func__); -+ goto as_fail; -+ } -+ -+ /* Initialize HW controlled by Adapter Service */ -+ if (false == dal_adapter_service_initialize_hw_data( -+ dc_init_data.adapter_srv)) { -+ dal_error("%s: dal_adapter_service_initialize_hw_data()"\ -+ " failed!\n", __func__); -+ /* Note that AS exist, so have to destroy it.*/ -+ goto as_fail; -+ } -+ -+ dc->ctx = dc_init_data.ctx; -+ -+ /* Create hardware sequencer */ -+ if (!dc_construct_hw_sequencer(dc_init_data.adapter_srv, dc)) -+ goto hwss_fail; -+ -+ -+ /* TODO: create all the sub-objects of DC. */ -+ if (false == create_links(dc, &dc_init_data)) -+ goto create_links_fail; -+ -+ if (!dc->hwss.construct_resource_pool( -+ dc_init_data.adapter_srv, -+ dc, -+ &dc->res_pool)) -+ goto construct_resource_fail; -+ -+ -+ bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios); -+ -+ bw_calcs_data_update_from_pplib(dc); -+ -+ return true; -+ -+ /**** error handling here ****/ -+construct_resource_fail: -+create_links_fail: -+as_fail: -+ dal_logger_destroy(&dc_init_data.ctx->logger); -+logger_fail: -+hwss_fail: -+ dc_service_free(&ctx, dc_init_data.ctx); -+ctx_fail: -+ return false; -+} -+ -+static void destruct(struct dc *dc) -+{ -+ destroy_links(dc); -+ dc_service_free(dc->ctx, dc->links); -+ dc->hwss.destruct_resource_pool(&dc->res_pool); -+ dal_logger_destroy(&dc->ctx->logger); -+ dc_service_free(dc->ctx, dc->ctx); -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+ -+struct dc *dc_create(const struct dal_init_data *init_params) -+ { -+ struct dc_context ctx = { -+ .driver_context = init_params->driver, -+ .cgs_device = init_params->cgs_device -+ }; -+ struct dc *dc = dc_service_alloc(&ctx, sizeof(*dc)); -+ -+ if (NULL == dc) -+ goto alloc_fail; -+ -+ ctx.dc = dc; -+ if (false == construct(dc, init_params)) -+ goto construct_fail; -+ -+ /*TODO: separate HW and SW initialization*/ -+ init_hw(dc); -+ -+ return dc; -+ -+construct_fail: -+ dc_service_free(&ctx, dc); -+ -+alloc_fail: -+ return NULL; -+} -+ -+void dc_destroy(struct dc **dc) -+{ -+ destruct(*dc); -+ dc_service_free((*dc)->ctx, *dc); -+ *dc = NULL; -+} -+ -+bool dc_validate_resources( -+ const struct dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count) -+{ -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ struct validate_context *context; -+ -+ context = dc_service_alloc(dc->ctx, sizeof(struct validate_context)); -+ if(context == NULL) -+ goto context_alloc_fail; -+ -+ result = dc->hwss.validate_with_context(dc, set, set_count, context); -+ -+ dc_service_free(dc->ctx, context); -+context_alloc_fail: -+ -+ return (result == DC_OK); -+ -+} -+ -+static void program_timing_sync( -+ struct dc_context *dc_ctx, -+ struct validate_context *ctx) -+{ -+ uint8_t i; -+ uint8_t j; -+ uint8_t group_size = 0; -+ uint8_t tg_count = ctx->res_ctx.pool.controller_count; -+ struct timing_generator *tg_set[3]; -+ -+ for (i = 0; i < tg_count; i++) { -+ if (!ctx->res_ctx.controller_ctx[i].stream) -+ continue; -+ -+ tg_set[0] = ctx->res_ctx.pool.timing_generators[i]; -+ group_size = 1; -+ -+ /* Add tg to the set, search rest of the tg's for ones with -+ * same timing, add all tgs with same timing to the group -+ */ -+ for (j = i + 1; j < tg_count; j++) { -+ if (!ctx->res_ctx.controller_ctx[j].stream) -+ continue; -+ -+ if (is_same_timing( -+ &ctx->res_ctx.controller_ctx[j].stream->public -+ .timing, -+ &ctx->res_ctx.controller_ctx[i].stream->public -+ .timing)) { -+ tg_set[group_size] = -+ ctx->res_ctx.pool.timing_generators[j]; -+ group_size++; -+ } -+ } -+ -+ /* Right now we limit to one timing sync group so if one is -+ * found we break. A group has to be more than one tg.*/ -+ if (group_size > 1) -+ break; -+ } -+ -+ if(group_size > 1) { -+ dc_ctx->dc->hwss.enable_timing_synchronization(dc_ctx, group_size, tg_set); -+ } -+} -+ -+static bool targets_changed( -+ struct dc *dc, -+ struct dc_target *targets[], -+ uint8_t target_count) -+{ -+ uint8_t i; -+ -+ if (target_count != dc->current_context.target_count) -+ return true; -+ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ if (&dc->current_context.targets[i]->public != targets[i]) -+ return true; -+ } -+ -+ return false; -+} -+ -+static void pplib_post_set_mode( -+ struct dc *dc, -+ const struct validate_context *context) -+{ -+ struct dc_pp_display_configuration pp_display_cfg = { 0 }; -+ -+ 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; -+ -+ /* TODO: get cpu_pstate_separation_time from BW Calcs. */ -+ pp_display_cfg.cpu_pstate_separation_time = 0; -+ -+ dc_service_pp_post_dce_clock_change(dc->ctx, &pp_display_cfg); -+} -+ -+bool dc_commit_targets( -+ struct dc *dc, -+ struct dc_target *targets[], -+ uint8_t target_count) -+{ -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ struct validate_context *context; -+ struct dc_validation_set set[4]; -+ uint8_t i; -+ -+ if (false == targets_changed(dc, targets, target_count)) -+ return DC_OK; -+ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_INTERFACE_TRACE, -+ LOG_MINOR_COMPONENT_DC, -+ "%s: %d targets", -+ __func__, -+ target_count); -+ -+ for (i = 0; i < target_count; i++) { -+ struct dc_target *target = targets[i]; -+ -+ dc_target_log(target, -+ dc->ctx->logger, -+ LOG_MAJOR_INTERFACE_TRACE, -+ LOG_MINOR_COMPONENT_DC); -+ -+ set[i].target = targets[i]; -+ set[i].surface_count = 0; -+ -+ } -+ -+ context = dc_service_alloc(dc->ctx, sizeof(struct validate_context)); -+ if (context == NULL) -+ goto context_alloc_fail; -+ -+ result = dc->hwss.validate_with_context(dc, set, target_count, context); -+ if (result != DC_OK){ -+ BREAK_TO_DEBUGGER(); -+ goto fail; -+ } -+ -+ if (!dal_adapter_service_is_in_accelerated_mode( -+ dc->res_pool.adapter_srv)) { -+ dc->hwss.enable_accelerated_mode(context); -+ } -+ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ /*TODO: optimize this to happen only when necessary*/ -+ dc_target_disable_memory_requests( -+ &dc->current_context.targets[i]->public); -+ } -+ -+ if (result == DC_OK) { -+ dc->hwss.reset_hw_ctx(dc, context, target_count); -+ -+ if (context->target_count > 0) -+ result = dc->hwss.apply_ctx_to_hw(dc, context); -+ } -+ -+ for (i = 0; i < context->target_count; i++) { -+ struct dc_target *dc_target = &context->targets[i]->public; -+ if (context->targets[i]->status.surface_count > 0) -+ dc_target_enable_memory_requests(dc_target); -+ } -+ -+ /* Release old targets */ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ dc_target_release( -+ &dc->current_context.targets[i]->public); -+ dc->current_context.targets[i] = NULL; -+ } -+ /* Retain new targets*/ -+ for (i = 0; i < context->target_count; i++) { -+ dc_target_retain(&context->targets[i]->public); -+ } -+ -+ dc->current_context = *context; -+ -+ program_timing_sync(dc->ctx, context); -+ -+ pplib_post_set_mode(dc, context); -+ -+ /* TODO: disable unused plls*/ -+fail: -+ dc_service_free(dc->ctx, context); -+ -+context_alloc_fail: -+ return (result == DC_OK); -+} -+ -+uint8_t dc_get_current_target_count(const struct dc *dc) -+{ -+ return dc->current_context.target_count; -+} -+ -+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i) -+{ -+ if (i < dc->current_context.target_count) -+ return &dc->current_context.targets[i]->public; -+ return NULL; -+} -+ -+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) -+{ -+ return &dc->links[link_index]->public; -+} -+ -+const struct graphics_object_id dc_get_link_id_at_index( -+ struct dc *dc, uint32_t link_index) -+{ -+ return dc->links[link_index]->link_id; -+} -+ -+const struct ddc_service *dc_get_ddc_at_index( -+ struct dc *dc, uint32_t link_index) -+{ -+ return dc->links[link_index]->ddc; -+} -+ -+const enum dc_irq_source dc_get_hpd_irq_source_at_index( -+ struct dc *dc, uint32_t link_index) -+{ -+ return dc->links[link_index]->public.irq_source_hpd; -+} -+ -+const struct audio **dc_get_audios(struct dc *dc) -+{ -+ return (const struct audio **)dc->res_pool.audios; -+} -+ -+void dc_get_caps(const struct dc *dc, struct dc_caps *caps) -+{ -+ caps->max_targets = dal_min(dc->res_pool.controller_count, dc->link_count); -+ caps->max_links = dc->link_count; -+ caps->max_audios = dc->res_pool.audio_count; -+} -+ -+void dc_flip_surface_addrs(struct dc* dc, -+ const struct dc_surface *const surfaces[], -+ struct dc_flip_addrs flip_addrs[], -+ uint32_t count) -+{ -+ uint8_t i; -+ for (i = 0; i < count; i++) { -+ struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); -+ /* -+ * TODO figure out a good way to keep track of address. Until -+ * then we'll have to awkwardly bypass the "const" surface. -+ */ -+ surface->public.address = flip_addrs[i].address; -+ dc->hwss.update_plane_address( -+ surface, -+ DC_TARGET_TO_CORE(surface->status.dc_target)); -+ } -+} -+ -+enum dc_irq_source dc_interrupt_to_irq_source( -+ struct dc *dc, -+ uint32_t src_id, -+ uint32_t ext_id) -+{ -+ return dal_irq_service_to_irq_source(dc->res_pool.irqs, src_id, ext_id); -+} -+ -+ -+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) -+{ -+ dal_irq_service_set(dc->res_pool.irqs, src, enable); -+} -+ -+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) -+{ -+ dal_irq_service_ack(dc->res_pool.irqs, src); -+} -+ -+const struct dc_target *dc_get_target_on_irq_source( -+ const struct dc *dc, -+ enum dc_irq_source src) -+{ -+ uint8_t i, j; -+ uint8_t crtc_idx; -+ -+ switch (src) { -+ case DC_IRQ_SOURCE_VUPDATE1: -+ case DC_IRQ_SOURCE_VUPDATE2: -+ case DC_IRQ_SOURCE_VUPDATE3: -+ case DC_IRQ_SOURCE_VUPDATE4: -+ case DC_IRQ_SOURCE_VUPDATE5: -+ case DC_IRQ_SOURCE_VUPDATE6: -+ crtc_idx = src - DC_IRQ_SOURCE_VUPDATE1; -+ break; -+ case DC_IRQ_SOURCE_PFLIP1: -+ case DC_IRQ_SOURCE_PFLIP2: -+ case DC_IRQ_SOURCE_PFLIP3: -+ case DC_IRQ_SOURCE_PFLIP4: -+ case DC_IRQ_SOURCE_PFLIP5: -+ case DC_IRQ_SOURCE_PFLIP6: -+ case DC_IRQ_SOURCE_PFLIP_UNDERLAY0: -+ crtc_idx = src - DC_IRQ_SOURCE_PFLIP1; -+ break; -+ default: -+ dal_error("%s: invalid irq source: %d\n!",__func__, src); -+ goto fail; -+ } -+ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ const struct core_target *target = -+ dc->current_context.targets[i]; -+ -+ if (NULL == target) { -+ dal_error("%s: 'dc_target' is NULL for irq source: %d\n!", -+ __func__, src); -+ continue; -+ } -+ -+ for (j = 0; j < target->stream_count; j++) { -+ const uint8_t controller_idx = -+ target->streams[j]->controller_idx; -+ if (controller_idx == crtc_idx) -+ return &target->public; -+ } -+ } -+fail: -+ return NULL; -+} -+ -+void dc_set_power_state( -+ struct dc *dc, -+ enum dc_acpi_cm_power_state power_state, -+ enum dc_video_power_state video_power_state) -+{ -+ dc->previous_power_state = dc->current_power_state; -+ dc->current_power_state = video_power_state; -+ -+ switch (power_state) { -+ case DC_ACPI_CM_POWER_STATE_D0: -+ init_hw(dc); -+ break; -+ default: -+ /* NULL means "reset/release all DC targets" */ -+ dc_commit_targets(dc, NULL, 0); -+ -+ dc->hwss.power_down(&dc->current_context); -+ break; -+ } -+ -+} -+ -+void dc_resume(const struct dc *dc) -+{ -+ uint32_t i; -+ -+ for (i = 0; i < dc->link_count; i++) -+ core_link_resume(dc->links[i]); -+} -+ -+void dc_print_sync_report( -+ const struct dc *dc) -+{ -+ uint32_t i; -+ const struct core_target *core_target; -+ struct dc_context *dc_ctx = dc->ctx; -+ struct dc_target_sync_report *target_sync_report; -+ struct dc_sync_report sync_report = { 0 }; -+ -+ if (dc->current_context.target_count > MAX_TARGET_NUM) { -+ DC_ERROR("Target count: %d > %d!\n", -+ dc->current_context.target_count, -+ MAX_TARGET_NUM); -+ return; -+ } -+ -+ sync_report.targets_num = dc->current_context.target_count; -+ -+ /* Step 1: get data for sync validation */ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ -+ core_target = dc->current_context.targets[i]; -+ target_sync_report = &sync_report.trg_reports[i]; -+ -+ dc->hwss.get_crtc_positions( -+ core_target->streams[0]->tg, -+ &target_sync_report->h_count, -+ &target_sync_report->v_count); -+ -+ DC_SYNC_INFO("GSL:target[%d]: h: %d\t v: %d\n", -+ i, -+ target_sync_report->h_count, -+ target_sync_report->v_count); -+ } -+ -+ /* Step 2: validate that display pipes are synchronized (based on -+ * data from Step 1). */ -+} -+ -+bool dc_read_dpcd( -+ struct dc *dc, -+ uint32_t link_index, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t size) -+{ -+ struct core_link *link = -+ DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index)); -+ enum dc_status r = core_link_read_dpcd(link, address, data, size); -+ -+ return r == DC_OK; -+} -+ -+bool dc_write_dpcd( -+ struct dc *dc, -+ uint32_t link_index, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t size) -+{ -+ struct core_link *link = -+ DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index)); -+ enum dc_status r = core_link_write_dpcd(link, address, data, size); -+ -+ return r == DC_OK; -+} -+ -+bool dc_link_add_sink( -+ struct dc_link *link, -+ struct dc_sink *sink) -+{ -+ if (link->sink_count >= MAX_SINKS_PER_LINK) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ link->sink[link->sink_count] = sink; -+ link->sink_count++; -+ -+ return true; -+} -+ -+ -+void dc_link_remove_sink(struct dc_link *link, const struct dc_sink *sink) -+{ -+ int i; -+ -+ if (!link->sink_count) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ for (i = 0; i < link->sink_count; i++) { -+ if (link->sink[i] == sink) { -+ dc_sink_release(sink); -+ link->sink[i] = NULL; -+ link->sink_count--; -+ return; -+ } -+ } -+ -+ BREAK_TO_DEBUGGER(); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c -new file mode 100644 -index 0000000..b9e6ffd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c -@@ -0,0 +1,49 @@ -+/* -+ * 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 "dc_services.h" -+#include "core_types.h" -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/dce110_hw_sequencer.h" -+#endif -+ -+bool dc_construct_hw_sequencer( -+ struct adapter_service *adapter_serv, -+ struct dc *dc) -+{ -+ enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv); -+ -+ switch (dce_ver) -+ { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ return dce110_hw_sequencer_construct(dc); -+#endif -+ default: -+ break; -+ } -+ -+ return false; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c -new file mode 100644 -index 0000000..a0a131e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c -@@ -0,0 +1,1081 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_services.h" -+#include "dc_helpers.h" -+#include "dc.h" -+#include "core_dc.h" -+#include "adapter_service_interface.h" -+#include "grph_object_id.h" -+#include "connector_interface.h" -+#include "gpio_service_interface.h" -+#include "ddc_service_interface.h" -+#include "core_status.h" -+#include "dc_link_dp.h" -+#include "link_hwss.h" -+#include "stream_encoder_types.h" -+#include "link_encoder_types.h" -+#include "hw_sequencer.h" -+ -+ -+#define LINK_INFO(...) \ -+ dal_logger_write(dc_ctx->logger, \ -+ LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_HOTPLUG, \ -+ __VA_ARGS__) -+ -+/******************************************************************************* -+ * Private structures -+ ******************************************************************************/ -+ -+ -+/******************************************************************************* -+ * Private functions -+ ******************************************************************************/ -+static void destruct(struct core_link *link) -+{ -+ if (link->connector) -+ dal_connector_destroy(&link->connector); -+ -+ if (link->ddc) -+ dal_ddc_service_destroy(&link->ddc); -+ -+ if(link->link_enc) -+ link->ctx->dc->hwss.encoder_destroy(&link->link_enc); -+} -+ -+static bool detect_sink(struct core_link *link) -+{ -+ uint32_t is_hpd_high = 0; -+ struct irq *hpd_pin; -+ -+ /* todo: may need to lock gpio access */ -+ hpd_pin = dal_adapter_service_obtain_hpd_irq( -+ link->adapter_srv, -+ link->link_id); -+ if (hpd_pin == NULL) -+ goto hpd_gpio_failure; -+ -+ dal_irq_open(hpd_pin); -+ dal_irq_get_value(hpd_pin, &is_hpd_high); -+ dal_irq_close(hpd_pin); -+ dal_adapter_service_release_irq( -+ link->adapter_srv, -+ hpd_pin); -+ -+ if (is_hpd_high) { -+ link->public.type = dc_connection_single; -+ /* TODO: need to do the actual detection */ -+ } else { -+ link->public.type = dc_connection_none; -+ } -+ -+ return true; -+ -+hpd_gpio_failure: -+ return false; -+} -+ -+ -+enum ddc_transaction_type get_ddc_transaction_type( -+ enum signal_type sink_signal) -+{ -+ enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; -+ -+ -+ switch (sink_signal) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_LVDS: -+ case SIGNAL_TYPE_RGB: -+ transaction_type = DDC_TRANSACTION_TYPE_I2C; -+ break; -+ -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_EDP: -+ transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; -+ break; -+ -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ /* MST does not use I2COverAux, but there is the -+ * SPECIAL use case for "immediate dwnstrm device -+ * access" (EPR#370830). */ -+ transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; -+ break; -+ -+ default: -+ break; -+ } -+ -+ -+ return transaction_type; -+} -+ -+static enum signal_type get_basic_signal_type( -+ struct graphics_object_id encoder, -+ struct graphics_object_id downstream) -+{ -+ if (downstream.type == OBJECT_TYPE_CONNECTOR) { -+ switch (downstream.id) { -+ case CONNECTOR_ID_SINGLE_LINK_DVII: -+ switch (encoder.id) { -+ case ENCODER_ID_INTERNAL_DAC1: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC1: -+ case ENCODER_ID_INTERNAL_DAC2: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC2: -+ return SIGNAL_TYPE_RGB; -+ default: -+ return SIGNAL_TYPE_DVI_SINGLE_LINK; -+ } -+ break; -+ case CONNECTOR_ID_DUAL_LINK_DVII: -+ { -+ switch (encoder.id) { -+ case ENCODER_ID_INTERNAL_DAC1: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC1: -+ case ENCODER_ID_INTERNAL_DAC2: -+ case ENCODER_ID_INTERNAL_KLDSCP_DAC2: -+ return SIGNAL_TYPE_RGB; -+ default: -+ return SIGNAL_TYPE_DVI_DUAL_LINK; -+ } -+ } -+ break; -+ case CONNECTOR_ID_SINGLE_LINK_DVID: -+ return SIGNAL_TYPE_DVI_SINGLE_LINK; -+ case CONNECTOR_ID_DUAL_LINK_DVID: -+ return SIGNAL_TYPE_DVI_DUAL_LINK; -+ case CONNECTOR_ID_VGA: -+ return SIGNAL_TYPE_RGB; -+ case CONNECTOR_ID_HDMI_TYPE_A: -+ return SIGNAL_TYPE_HDMI_TYPE_A; -+ case CONNECTOR_ID_LVDS: -+ return SIGNAL_TYPE_LVDS; -+ case CONNECTOR_ID_DISPLAY_PORT: -+ return SIGNAL_TYPE_DISPLAY_PORT; -+ case CONNECTOR_ID_EDP: -+ return SIGNAL_TYPE_EDP; -+ default: -+ return SIGNAL_TYPE_NONE; -+ } -+ } else if (downstream.type == OBJECT_TYPE_ENCODER) { -+ switch (downstream.id) { -+ case ENCODER_ID_EXTERNAL_NUTMEG: -+ case ENCODER_ID_EXTERNAL_TRAVIS: -+ return SIGNAL_TYPE_DISPLAY_PORT; -+ default: -+ return SIGNAL_TYPE_NONE; -+ } -+ } -+ -+ return SIGNAL_TYPE_NONE; -+} -+ -+/* -+ * @brief -+ * Check whether there is a dongle on DP connector -+ */ -+static bool is_dp_sink_present(struct core_link *link) -+{ -+ enum gpio_result gpio_result; -+ uint32_t clock_pin = 0; -+ uint32_t data_pin = 0; -+ -+ struct ddc *ddc; -+ -+ enum connector_id connector_id = -+ dal_graphics_object_id_get_connector_id(link->link_id); -+ -+ bool present = -+ ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || -+ (connector_id == CONNECTOR_ID_EDP)); -+ -+ ddc = dal_adapter_service_obtain_ddc(link->adapter_srv, link->link_id); -+ -+ if (!ddc) -+ return present; -+ -+ /* Open GPIO and set it to I2C mode */ -+ /* Note: this GpioMode_Input will be converted -+ * to GpioConfigType_I2cAuxDualMode in GPIO component, -+ * which indicates we need additional delay */ -+ -+ if (GPIO_RESULT_OK != dal_ddc_open( -+ ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) { -+ dal_adapter_service_release_ddc(link->adapter_srv, ddc); -+ -+ return present; -+ } -+ -+ /* Read GPIO: DP sink is present if both clock and data pins are zero */ -+ /* [anaumov] in DAL2, there was no check for GPIO failure */ -+ -+ gpio_result = dal_ddc_get_clock(ddc, &clock_pin); -+ ASSERT(gpio_result == GPIO_RESULT_OK); -+ -+ if (gpio_result == GPIO_RESULT_OK) -+ if (link->link_enc->features.flags.bits. -+ DP_SINK_DETECT_POLL_DATA_PIN) -+ gpio_result = dal_ddc_get_data(ddc, &data_pin); -+ -+ present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin); -+ -+ dal_ddc_close(ddc); -+ -+ dal_adapter_service_release_ddc(link->adapter_srv, ddc); -+ -+ return present; -+} -+ -+/* -+ * @brief -+ * Detect output sink type -+ */ -+static enum signal_type link_detect_sink(struct core_link *link) -+{ -+ enum signal_type result = get_basic_signal_type( -+ link->link_enc->id, link->link_id); -+ -+ /* Internal digital encoder will detect only dongles -+ * that require digital signal */ -+ -+ /* Detection mechanism is different -+ * for different native connectors. -+ * LVDS connector supports only LVDS signal; -+ * PCIE is a bus slot, the actual connector needs to be detected first; -+ * eDP connector supports only eDP signal; -+ * HDMI should check straps for audio */ -+ -+ /* PCIE detects the actual connector on add-on board */ -+ -+ if (link->link_id.id == CONNECTOR_ID_PCIE) { -+ /* ZAZTODO implement PCIE add-on card detection */ -+ } -+ -+ switch (link->link_id.id) { -+ case CONNECTOR_ID_HDMI_TYPE_A: { -+ /* check audio support: -+ * if native HDMI is not supported, switch to DVI */ -+ union audio_support audio_support = -+ dal_adapter_service_get_audio_support( -+ link->adapter_srv); -+ -+ if (!audio_support.bits.HDMI_AUDIO_NATIVE) -+ if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A) -+ result = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ } -+ break; -+ case CONNECTOR_ID_DISPLAY_PORT: { -+ -+ /* Check whether DP signal detected: if not - -+ * we assume signal is DVI; it could be corrected -+ * to HDMI after dongle detection */ -+ if (!is_dp_sink_present(link)) -+ result = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ return result; -+} -+ -+static enum signal_type decide_signal_from_strap_and_dongle_type( -+ enum display_dongle_type dongle_type, -+ union audio_support *audio_support) -+{ -+ enum signal_type signal = SIGNAL_TYPE_NONE; -+ -+ switch (dongle_type) { -+ case DISPLAY_DONGLE_DP_HDMI_DONGLE: -+ if (audio_support->bits.HDMI_AUDIO_ON_DONGLE) -+ signal = SIGNAL_TYPE_HDMI_TYPE_A; -+ else -+ signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ case DISPLAY_DONGLE_DP_DVI_DONGLE: -+ signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE: -+ if (audio_support->bits.HDMI_AUDIO_NATIVE) -+ signal = SIGNAL_TYPE_HDMI_TYPE_A; -+ else -+ signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ default: -+ signal = SIGNAL_TYPE_NONE; -+ break; -+ } -+ -+ return signal; -+} -+ -+static enum signal_type dp_passive_dongle_detection( -+ struct ddc_service *ddc, -+ struct display_sink_capability *sink_cap, -+ union audio_support *audio_support) -+{ -+ /* TODO:These 2 functions should be protected for upstreaming purposes -+ * in case hackers want to save 10 cents hdmi license fee -+ */ -+ dal_ddc_service_i2c_query_dp_dual_mode_adaptor( -+ ddc, sink_cap); -+ return decide_signal_from_strap_and_dongle_type( -+ sink_cap->dongle_type, -+ audio_support); -+} -+ -+static bool is_dp_active_dongle(enum display_dongle_type dongle_type) -+{ -+ return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER || -+ dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER || -+ dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER); -+} -+ -+/* TODO: To beretired because this call is wrong with -+ * pluging in of active-dongle without display*/ -+static void link_unplug(struct core_link *link) -+{ -+ int i; -+ -+ for (i = 0; i < link->public.sink_count; i++) -+ dc_link_remove_sink(&link->public, link->public.sink[i]); -+} -+ -+static enum dc_edid_status read_edid(struct core_link *link) -+{ -+ uint32_t edid_retry = 3; -+ enum dc_edid_status edid_status; -+ const struct dc_sink *dc_sink = link->public.sink[0]; -+ struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); -+ -+ if (link->public.sink[0]->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "MST EDID read is not done here!\n"); -+ return EDID_BAD_INPUT; -+ } -+ -+ /* 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 = dc_helpers_parse_edid_caps( -+ link->ctx, -+ &sink->public.dc_edid, -+ &sink->public.edid_caps); -+ --edid_retry; -+ if (edid_status == EDID_BAD_CHECKSUM) -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "Bad EDID checksum, retry remain: %d\n", -+ edid_retry); -+ } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); -+ -+ return edid_status; -+} -+ -+void dc_link_detect(const struct dc_link *dc_link) -+{ -+ struct core_link *link = DC_LINK_TO_LINK(dc_link); -+ struct sink_init_data sink_init_data = { 0 }; -+ enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; -+ struct display_sink_capability sink_caps = { 0 }; -+ uint8_t i; -+ enum signal_type signal = SIGNAL_TYPE_NONE; -+ bool converter_disable_audio = false; -+ union audio_support audio_support = -+ dal_adapter_service_get_audio_support( -+ link->adapter_srv); -+ enum dc_edid_status edid_status; -+ struct dc_context *dc_ctx = link->ctx; -+ struct dc_sink *dc_sink; -+ struct core_sink *sink = NULL; -+ -+ if (false == detect_sink(link)) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ if (link->public.type != dc_connection_none) { -+ /* From Disconnected-to-Connected. */ -+ switch (link->public.connector_signal) { -+ case SIGNAL_TYPE_HDMI_TYPE_A: { -+ transaction_type = DDC_TRANSACTION_TYPE_I2C; -+ if (audio_support.bits.HDMI_AUDIO_NATIVE) -+ signal = SIGNAL_TYPE_HDMI_TYPE_A; -+ else -+ signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ } -+ -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: { -+ transaction_type = DDC_TRANSACTION_TYPE_I2C; -+ signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ } -+ -+ case SIGNAL_TYPE_DVI_DUAL_LINK: { -+ transaction_type = DDC_TRANSACTION_TYPE_I2C; -+ signal = SIGNAL_TYPE_DVI_DUAL_LINK; -+ break; -+ } -+ -+ case SIGNAL_TYPE_EDP: { -+ detect_dp_sink_caps(link); -+ transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; -+ signal = SIGNAL_TYPE_EDP; -+ break; -+ } -+ -+ case SIGNAL_TYPE_DISPLAY_PORT: { -+ signal = link_detect_sink(link); -+ transaction_type = get_ddc_transaction_type( -+ signal); -+ -+ if (transaction_type == -+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { -+ signal = -+ SIGNAL_TYPE_DISPLAY_PORT; -+ detect_dp_sink_caps(link); -+ -+ /* DP active dongles */ -+ if (is_dp_active_dongle( -+ link->dpcd_caps.dongle_type)) { -+ if (!link->dpcd_caps. -+ sink_count.bits.SINK_COUNT) { -+ link->public.type = -+ dc_connection_none; -+ /* active dongle unplug -+ * processing for short irq -+ */ -+ link_unplug(link); -+ return; -+ } -+ -+ if (link->dpcd_caps.dongle_type != -+ DISPLAY_DONGLE_DP_HDMI_CONVERTER) { -+ converter_disable_audio = true; -+ } -+ } -+ if (is_mst_supported(link)) { -+ 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 (dc_helpers_dp_mst_start_top_mgr(link->ctx, &link->public)) { -+ return; -+ } else { -+ /* MST not supported */ -+ signal = SIGNAL_TYPE_DISPLAY_PORT; -+ } -+ } -+ } -+ else { -+ /* DP passive dongles */ -+ signal = dp_passive_dongle_detection(link->ddc, -+ &sink_caps, -+ &audio_support); -+ } -+ break; -+ } -+ -+ default: -+ DC_ERROR("Invalid connector type! signal:%d\n", -+ link->public.connector_signal); -+ return; -+ } /* 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, -+ transaction_type); -+ -+ sink_init_data.link = &link->public; -+ sink_init_data.sink_signal = 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 = sink_create(&sink_init_data); -+ if (!dc_sink) { -+ DC_ERROR("Failed to create sink!\n"); -+ return; -+ } -+ -+ sink = DC_SINK_TO_CORE(dc_sink); -+ -+ /*AG TODO handle failure */ -+ /*Only non MST case here */ -+ if (!dc_link_add_sink(&link->public, &sink->public)) -+ BREAK_TO_DEBUGGER(); -+ -+ edid_status = read_edid(link); -+ -+ switch (edid_status) { -+ case EDID_BAD_CHECKSUM: -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "EDID checksum invalid.\n"); -+ break; -+ case EDID_NO_RESPONSE: -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "No EDID read.\n"); -+ return; -+ -+ default: -+ break; -+ } -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_DETECTION, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "%s: " -+ "manufacturer_id = %X, " -+ "product_id = %X, " -+ "serial_number = %X, " -+ "manufacture_week = %d, " -+ "manufacture_year = %d, " -+ "display_name = %s, " -+ "speaker_flag = %d, " -+ "audio_mode_count = %d\n", -+ __func__, -+ sink->public.edid_caps.manufacturer_id, -+ sink->public.edid_caps.product_id, -+ sink->public.edid_caps.serial_number, -+ sink->public.edid_caps.manufacture_week, -+ sink->public.edid_caps.manufacture_year, -+ sink->public.edid_caps.display_name, -+ sink->public.edid_caps.speaker_flags, -+ sink->public.edid_caps.audio_mode_count); -+ -+ for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) { -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_DETECTION, -+ LOG_MINOR_DETECTION_EDID_PARSER, -+ "%s: mode number = %d, " -+ "format_code = %d, " -+ "channel_count = %d, " -+ "sample_rate = %d, " -+ "sample_size = %d\n", -+ __func__, -+ i, -+ sink->public.edid_caps.audio_modes[i].format_code, -+ sink->public.edid_caps.audio_modes[i].channel_count, -+ sink->public.edid_caps.audio_modes[i].sample_rate, -+ sink->public.edid_caps.audio_modes[i].sample_size); -+ } -+ -+ } else { -+ /* From Connected-to-Disconnected. */ -+ switch (link->public.connector_signal) { -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ dc_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public); -+ break; -+ default: -+ break; -+ } -+ link_unplug(link); -+ } -+ -+ LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", -+ link->link_index, &sink->public, -+ (signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected")); -+ -+ /* TODO: */ -+ -+ return; -+} -+ -+static bool construct( -+ struct core_link *link, -+ const struct link_init_data *init_params) -+{ -+ struct irq *hpd_gpio = NULL; -+ struct ddc_service_init_data ddc_service_init_data = { 0 }; -+ struct dc_context *dc_ctx = init_params->ctx; -+ struct encoder_init_data enc_init_data = { 0 }; -+ struct connector_feature_support cfs = { 0 }; -+ -+ link->dc = init_params->dc; -+ link->adapter_srv = init_params->adapter_srv; -+ link->connector_index = init_params->connector_index; -+ link->ctx = dc_ctx; -+ link->link_index = init_params->link_index; -+ -+ link->link_id = dal_adapter_service_get_connector_obj_id( -+ init_params->adapter_srv, -+ init_params->connector_index); -+ -+ if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { -+ dal_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", -+ __func__, init_params->connector_index); -+ goto create_fail; -+ } -+ -+ switch (link->link_id.id) { -+ case CONNECTOR_ID_HDMI_TYPE_A: -+ link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; -+ break; -+ case CONNECTOR_ID_SINGLE_LINK_DVID: -+ case CONNECTOR_ID_SINGLE_LINK_DVII: -+ link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -+ break; -+ case CONNECTOR_ID_DUAL_LINK_DVID: -+ case CONNECTOR_ID_DUAL_LINK_DVII: -+ link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; -+ break; -+ case CONNECTOR_ID_DISPLAY_PORT: -+ link->public.connector_signal = SIGNAL_TYPE_DISPLAY_PORT; -+ hpd_gpio = dal_adapter_service_obtain_hpd_irq( -+ init_params->adapter_srv, -+ link->link_id); -+ -+ if (hpd_gpio != NULL) { -+ link->public.irq_source_hpd_rx = -+ dal_irq_get_rx_source(hpd_gpio); -+ dal_adapter_service_release_irq( -+ init_params->adapter_srv, hpd_gpio); -+ } -+ break; -+ case CONNECTOR_ID_EDP: -+ link->public.connector_signal = SIGNAL_TYPE_EDP; -+ hpd_gpio = dal_adapter_service_obtain_hpd_irq( -+ init_params->adapter_srv, -+ link->link_id); -+ -+ if (hpd_gpio != NULL) { -+ link->public.irq_source_hpd_rx = -+ dal_irq_get_rx_source(hpd_gpio); -+ dal_adapter_service_release_irq( -+ init_params->adapter_srv, hpd_gpio); -+ } -+ break; -+ default: -+ dal_logger_write(dc_ctx->logger, -+ LOG_MAJOR_WARNING, LOG_MINOR_TM_LINK_SRV, -+ "Unsupported Connector type:%d!\n", link->link_id.id); -+ goto create_fail; -+ } -+ -+ /* TODO: #DAL3 Implement id to str function.*/ -+ LINK_INFO("Connector[%d] description:\n", -+ init_params->connector_index); -+ -+ link->connector = dal_connector_create(dc_ctx, -+ init_params->adapter_srv, -+ link->link_id); -+ if (NULL == link->connector) { -+ DC_ERROR("Failed to create connector object!\n"); -+ goto create_fail; -+ } -+ -+ -+ hpd_gpio = dal_adapter_service_obtain_hpd_irq( -+ init_params->adapter_srv, -+ link->link_id); -+ -+ if (hpd_gpio != NULL) { -+ link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio); -+ dal_adapter_service_release_irq( -+ init_params->adapter_srv, hpd_gpio); -+ } -+ -+ ddc_service_init_data.as = link->adapter_srv; -+ ddc_service_init_data.ctx = link->ctx; -+ ddc_service_init_data.id = link->link_id; -+ link->ddc = dal_ddc_service_create(&ddc_service_init_data); -+ -+ if (NULL == link->ddc) { -+ DC_ERROR("Failed to create ddc_service!\n"); -+ goto create_fail; -+ } -+ -+ dal_connector_get_features(link->connector, &cfs); -+ -+ enc_init_data.adapter_service = link->adapter_srv; -+ enc_init_data.ctx = dc_ctx; -+ enc_init_data.encoder = dal_adapter_service_get_src_obj( -+ link->adapter_srv, link->link_id, 0); -+ enc_init_data.connector = link->link_id; -+ enc_init_data.channel = cfs.ddc_line; -+ enc_init_data.hpd_source = cfs.hpd_line; -+ link->link_enc = dc_ctx->dc->hwss.encoder_create(&enc_init_data); -+ -+ if( link->link_enc == NULL) { -+ DC_ERROR("Failed to create link encoder!\n"); -+ goto create_fail; -+ } -+ -+ /* -+ * TODO check if GPIO programmed correctly -+ * -+ * If GPIO isn't programmed correctly HPD might not rise or drain -+ * fast enough, leading to bounces. -+ */ -+#define DELAY_ON_CONNECT_IN_MS 500 -+#define DELAY_ON_DISCONNECT_IN_MS 500 -+ -+ dal_connector_program_hpd_filter( -+ link->connector, -+ DELAY_ON_CONNECT_IN_MS, -+ DELAY_ON_DISCONNECT_IN_MS); -+ -+ return true; -+ -+create_fail: -+ return false; -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+struct core_link *link_create(const struct link_init_data *init_params) -+{ -+ struct core_link *link = -+ dc_service_alloc(init_params->ctx, sizeof(*link)); -+ link->ctx = init_params->ctx; -+ -+ if (NULL == link) -+ goto alloc_fail; -+ -+ if (false == construct(link, init_params)) -+ goto construct_fail; -+ -+ return link; -+ -+construct_fail: -+ dc_service_free(init_params->ctx, link); -+ -+alloc_fail: -+ return NULL; -+} -+ -+void link_destroy(struct core_link **link) -+{ -+ destruct(*link); -+ dc_service_free((*link)->ctx, *link); -+ *link = NULL; -+} -+ -+static void dpcd_configure_panel_mode( -+ struct core_link *link, -+ enum dp_panel_mode panel_mode) -+{ -+ union dpcd_edp_config edp_config_set; -+ bool panel_mode_edp = false; -+ -+ dc_service_memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config)); -+ -+ if (DP_PANEL_MODE_DEFAULT != panel_mode) { -+ -+ switch (panel_mode) { -+ case DP_PANEL_MODE_EDP: -+ case DP_PANEL_MODE_SPECIAL: -+ panel_mode_edp = true; -+ break; -+ -+ default: -+ break; -+ } -+ -+ /*set edp panel mode in receiver*/ -+ core_link_read_dpcd( -+ link, -+ DPCD_ADDRESS_EDP_CONFIG_SET, -+ &edp_config_set.raw, -+ sizeof(edp_config_set.raw)); -+ -+ if (edp_config_set.bits.PANEL_MODE_EDP -+ != panel_mode_edp) { -+ enum ddc_result result = DDC_RESULT_UNKNOWN; -+ -+ edp_config_set.bits.PANEL_MODE_EDP = -+ panel_mode_edp; -+ result = core_link_write_dpcd( -+ link, -+ DPCD_ADDRESS_EDP_CONFIG_SET, -+ &edp_config_set.raw, -+ sizeof(edp_config_set.raw)); -+ -+ ASSERT(result == DDC_RESULT_SUCESSFULL); -+ } -+ } -+ dal_logger_write(link->ctx->logger, LOG_MAJOR_DETECTION, -+ LOG_MINOR_DETECTION_DP_CAPS, -+ "Connector: %d eDP panel mode supported: %d " -+ "eDP panel mode enabled: %d \n", -+ link->connector_index, -+ link->dpcd_caps.panel_mode_edp, -+ panel_mode_edp); -+} -+ -+static enum dc_status enable_link_dp(struct core_stream *stream) -+{ -+ enum dc_status status; -+ bool skip_video_pattern; -+ struct core_link *link = stream->sink->link; -+ struct link_settings link_settings = {0}; -+ enum dp_panel_mode panel_mode; -+ -+ /* get link settings for video mode timing */ -+ decide_link_settings(stream, &link_settings); -+ status = dp_enable_link_phy( -+ stream->sink->link, -+ stream->signal, -+ stream->stream_enc->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(link, &link_settings, skip_video_pattern)) { -+ link->cur_link_settings = link_settings; -+ status = DC_OK; -+ } -+ else -+ status = DC_ERROR_UNEXPECTED; -+ -+ return status; -+} -+ -+static enum dc_status enable_link_hdmi(struct core_stream *stream) -+{ -+ struct core_link *link = stream->sink->link; -+ -+ /* TODO:Need to add missing use cases, reference -+ * dal_hw_sequencer_enable_link_base*/ -+ enum dc_status status = DC_OK; -+ -+ /* enable video output */ -+ /* here we need to specify that encoder output settings -+ * need to be calculated as for the set mode, -+ * it will lead to querying dynamic link capabilities -+ * which should be done before enable output */ -+ -+ uint32_t normalized_pix_clk = stream->public.timing.pix_clk_khz; -+ switch (stream->public.timing.display_color_depth) { -+ case COLOR_DEPTH_888: -+ break; -+ case COLOR_DEPTH_101010: -+ normalized_pix_clk = (normalized_pix_clk * 30) / 24; -+ break; -+ case COLOR_DEPTH_121212: -+ normalized_pix_clk = (normalized_pix_clk * 36) / 24; -+ break; -+ case COLOR_DEPTH_161616: -+ normalized_pix_clk = (normalized_pix_clk * 48) / 24; -+ break; -+ default: -+ break; -+ } -+ -+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ dal_ddc_service_write_scdc_data( -+ stream->sink->link->ddc, -+ normalized_pix_clk, -+ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); -+ -+ stream->sink->link->cur_link_settings.lane_count = -+ (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) -+ ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; -+ -+ if (link->ctx->dc->hwss.encoder_enable_output( -+ stream->sink->link->link_enc, -+ &stream->sink->link->cur_link_settings, -+ stream->stream_enc->id, -+ dal_clock_source_get_id(stream->clock_source), -+ stream->signal, -+ stream->public.timing.display_color_depth, -+ stream->public.timing.pix_clk_khz) != ENCODER_RESULT_OK) -+ status = DC_ERROR_UNEXPECTED; -+ -+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) -+ dal_ddc_service_read_scdc_data(link->ddc); -+ -+ return status; -+} -+ -+/****************************enable_link***********************************/ -+enum dc_status core_link_enable(struct core_stream *stream) -+{ -+ enum dc_status status; -+ switch (stream->signal) { -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_EDP: -+ status = enable_link_dp(stream); -+ break; -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ status = enable_link_hdmi(stream); -+ break; -+ -+ default: -+ status = DC_ERROR_UNEXPECTED; -+ break; -+ } -+ -+ if (stream->audio) { -+ stream->ctx->dc->hwss.set_afmt_memory_power_state( -+ stream->ctx, stream->stream_enc->id, true); -+ /* notify audio driver for audio modes of monitor */ -+ dal_audio_enable_azalia_audio_jack_presence(stream->audio, -+ stream->stream_enc->id); -+ -+ /* un-mute audio */ -+ dal_audio_unmute(stream->audio, stream->stream_enc->id, -+ stream->signal); -+ } -+ -+ return status; -+} -+ -+enum dc_status core_link_disable(struct core_stream *stream) -+{ -+ /* TODO dp_set_hw_test_pattern */ -+ enum dc_status status = DC_OK; -+ struct dc *dc = stream->ctx->dc; -+ -+ /* here we need to specify that encoder output settings -+ * need to be calculated as for the set mode, -+ * it will lead to querying dynamic link capabilities -+ * which should be done before enable output */ -+ -+ if (dc_is_dp_signal(stream->signal)) -+ dp_disable_link_phy(stream->sink->link, stream->signal); -+ else if (ENCODER_RESULT_OK != dc->hwss.encoder_disable_output( -+ stream->sink->link->link_enc, stream->signal)) -+ status = DC_ERROR_UNEXPECTED; -+ -+ if (stream->audio) { -+ dc->hwss.set_afmt_memory_power_state( -+ stream->ctx, stream->stream_enc->id, false); -+ } -+ -+ return status; -+} -+ -+enum dc_status dc_link_validate_mode_timing( -+ const struct core_sink *sink, -+ struct core_link *link, -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t max_pix_clk = sink->dongle_max_pix_clk; -+ -+ if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) -+ return DC_EXCEED_DONGLE_MAX_CLK; -+ -+ switch (sink->public.sink_signal) { -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ if(!dp_validate_mode_timing( -+ link, -+ timing)) -+ return DC_NO_DP_LINK_BANDWIDTH; -+ break; -+ -+ default: -+ break; -+ } -+ -+ return DC_OK; -+} -+ -+bool dc_link_set_backlight_level(const struct dc_link *public, uint32_t level) -+{ -+ struct core_link *protected = DC_LINK_TO_CORE(public); -+ struct dc_context *ctx = protected->ctx; -+ -+ dal_logger_write(ctx->logger, LOG_MAJOR_BACKLIGHT, -+ LOG_MINOR_BACKLIGHT_INTERFACE, -+ "New Backlight level: %d (0x%X)\n", level, level); -+ -+ ctx->dc->hwss.encoder_set_lcd_backlight_level(protected->link_enc, level); -+ -+ return true; -+} -+ -+void core_link_resume(struct core_link *link) -+{ -+ dal_connector_program_hpd_filter( -+ link->connector, -+ DELAY_ON_CONNECT_IN_MS, -+ DELAY_ON_DISCONNECT_IN_MS); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c -new file mode 100644 -index 0000000..9214aec ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c -@@ -0,0 +1,1689 @@ -+/* Copyright 2015 Advanced Micro Devices, Inc. */ -+#include "dc_services.h" -+#include "dc.h" -+#include "dc_helpers.h" -+#include "inc/core_types.h" -+#include "link_hwss.h" -+#include "ddc_service_interface.h" -+#include "connector_interface.h" -+#include "core_status.h" -+#include "dpcd_defs.h" -+ -+/* maximum pre emphasis level allowed for each voltage swing level*/ -+static const enum pre_emphasis voltage_swing_to_pre_emphasis[] = { -+ PRE_EMPHASIS_LEVEL3, -+ PRE_EMPHASIS_LEVEL2, -+ PRE_EMPHASIS_LEVEL1, -+ PRE_EMPHASIS_DISABLED }; -+ -+enum { -+ POST_LT_ADJ_REQ_LIMIT = 6, -+ POST_LT_ADJ_REQ_TIMEOUT = 200 -+}; -+ -+enum { -+ LINK_TRAINING_MAX_RETRY_COUNT = 5, -+ /* to avoid infinite loop where-in the receiver -+ * switches between different VS -+ */ -+ LINK_TRAINING_MAX_CR_RETRY = 100 -+}; -+ -+static const struct link_settings link_training_fallback_table[] = { -+/* 2160 Mbytes/sec*/ -+{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -+/* 1080 Mbytes/sec*/ -+{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -+/* 648 Mbytes/sec*/ -+{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -+/* 1080 Mbytes/sec*/ -+{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -+/* 540 Mbytes/sec*/ -+{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -+/* 324 Mbytes/sec*/ -+{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -+/* 540 Mbytes/sec*/ -+{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -+/* 270 Mbytes/sec*/ -+{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -+/* 162 Mbytes/sec*/ -+{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } }; -+ -+static void wait_for_training_aux_rd_interval( -+ struct core_link* link, -+ uint32_t default_wait_in_micro_secs) -+{ -+ uint8_t training_rd_interval; -+ -+ /* overwrite the delay if rev > 1.1*/ -+ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { -+ /* DP 1.2 or later - retrieve delay through -+ * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ -+ core_link_read_dpcd( -+ link, -+ DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL, -+ &training_rd_interval, -+ sizeof(training_rd_interval)); -+ default_wait_in_micro_secs = training_rd_interval ? -+ (training_rd_interval * 4000) : -+ default_wait_in_micro_secs; -+ } -+ -+ dc_service_delay_in_microseconds(link->ctx, default_wait_in_micro_secs); -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s:\n wait = %d\n", -+ __func__, -+ default_wait_in_micro_secs); -+} -+ -+static void dpcd_set_training_pattern( -+ struct core_link* link, -+ union dpcd_training_pattern dpcd_pattern) -+{ -+ core_link_write_dpcd( -+ link, -+ DPCD_ADDRESS_TRAINING_PATTERN_SET, -+ &dpcd_pattern.raw, -+ 1); -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s\n %x pattern = %x\n", -+ __func__, -+ DPCD_ADDRESS_TRAINING_PATTERN_SET, -+ dpcd_pattern.bits.TRAINING_PATTERN_SET); -+} -+ -+static void dpcd_set_link_settings( -+ struct core_link* link, -+ const struct link_training_settings *lt_settings) -+{ -+ uint8_t rate = (uint8_t) -+ (lt_settings->link_settings.link_rate); -+ -+ union down_spread_ctrl downspread = {{0}}; -+ union lane_count_set lane_count_set = {{0}}; -+ uint8_t link_set_buffer[2]; -+ -+ -+ downspread.raw = (uint8_t) -+ (lt_settings->link_settings.link_spread); -+ -+ lane_count_set.bits.LANE_COUNT_SET = -+ lt_settings->link_settings.lane_count; -+ -+ lane_count_set.bits.ENHANCED_FRAMING = 1; -+ -+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = -+ link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; -+ -+ link_set_buffer[0] = rate; -+ link_set_buffer[1] = lane_count_set.raw; -+ -+ core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET, -+ link_set_buffer, 2); -+ core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, -+ &downspread.raw, sizeof(downspread)); -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", -+ __func__, -+ DPCD_ADDRESS_LINK_BW_SET, -+ lt_settings->link_settings.link_rate, -+ DPCD_ADDRESS_LANE_COUNT_SET, -+ lt_settings->link_settings.lane_count, -+ DPCD_ADDRESS_DOWNSPREAD_CNTL, -+ lt_settings->link_settings.link_spread); -+ -+} -+ -+static enum dpcd_training_patterns -+ hw_training_pattern_to_dpcd_training_pattern( -+ struct core_link* link, -+ enum hw_dp_training_pattern pattern) -+{ -+ enum dpcd_training_patterns dpcd_tr_pattern = -+ DPCD_TRAINING_PATTERN_VIDEOIDLE; -+ -+ switch (pattern) { -+ case HW_DP_TRAINING_PATTERN_1: -+ dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; -+ break; -+ case HW_DP_TRAINING_PATTERN_2: -+ dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; -+ break; -+ case HW_DP_TRAINING_PATTERN_3: -+ dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; -+ break; -+ default: -+ ASSERT(0); -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s: Invalid HW Training pattern: %d\n", -+ __func__, pattern); -+ break; -+ } -+ -+ return dpcd_tr_pattern; -+ -+} -+ -+static void dpcd_set_lt_pattern_and_lane_settings( -+ struct core_link* link, -+ const struct link_training_settings *lt_settings, -+ enum hw_dp_training_pattern pattern) -+{ -+ union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; -+ const uint32_t dpcd_base_lt_offset = -+ DPCD_ADDRESS_TRAINING_PATTERN_SET; -+ uint8_t dpcd_lt_buffer[5] = {0}; -+ union dpcd_training_pattern dpcd_pattern = {{0}}; -+ uint32_t lane; -+ uint32_t size_in_bytes; -+ bool edp_workaround = false; /* TODO link_prop.INTERNAL */ -+ -+ /***************************************************************** -+ * DpcdAddress_TrainingPatternSet -+ *****************************************************************/ -+ dpcd_pattern.bits.TRAINING_PATTERN_SET = -+ hw_training_pattern_to_dpcd_training_pattern(link, pattern); -+ -+ dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset] -+ = dpcd_pattern.raw; -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s\n %x pattern = %x\n", -+ __func__, -+ DPCD_ADDRESS_TRAINING_PATTERN_SET, -+ dpcd_pattern.bits.TRAINING_PATTERN_SET); -+ -+ -+ /***************************************************************** -+ * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set -+ *****************************************************************/ -+ for (lane = 0; lane < -+ (uint32_t)(lt_settings->link_settings.lane_count); lane++) { -+ -+ dpcd_lane[lane].bits.VOLTAGE_SWING_SET = -+ (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); -+ dpcd_lane[lane].bits.PRE_EMPHASIS_SET = -+ (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS); -+ -+ dpcd_lane[lane].bits.MAX_SWING_REACHED = -+ (lt_settings->lane_settings[lane].VOLTAGE_SWING == -+ VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); -+ dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = -+ (lt_settings->lane_settings[lane].PRE_EMPHASIS == -+ PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); -+ } -+ -+ /* concatinate everything into one buffer*/ -+ -+ size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]); -+ -+ // 0x00103 - 0x00102 -+ dc_service_memmove( -+ &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset], -+ dpcd_lane, -+ size_in_bytes); -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s:\n %x VS set = %x PE set = %x \ -+ max VS Reached = %x max PE Reached = %x\n", -+ __func__, -+ DPCD_ADDRESS_LANE0_SET, -+ dpcd_lane[0].bits.VOLTAGE_SWING_SET, -+ dpcd_lane[0].bits.PRE_EMPHASIS_SET, -+ dpcd_lane[0].bits.MAX_SWING_REACHED, -+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); -+ -+ -+ if (edp_workaround) { -+ /* for eDP write in 2 parts because the 5-byte burst is -+ * causing issues on some eDP panels (EPR#366724) -+ */ -+ core_link_write_dpcd( -+ link, -+ DPCD_ADDRESS_TRAINING_PATTERN_SET, -+ &dpcd_pattern.raw, -+ sizeof(dpcd_pattern.raw) ); -+ -+ core_link_write_dpcd( -+ link, -+ DPCD_ADDRESS_LANE0_SET, -+ (uint8_t *)(dpcd_lane), -+ size_in_bytes); -+ -+ } else -+ /* write it all in (1 + number-of-lanes)-byte burst*/ -+ core_link_write_dpcd( -+ link, -+ dpcd_base_lt_offset, -+ dpcd_lt_buffer, -+ size_in_bytes + sizeof(dpcd_pattern.raw) ); -+ -+ link->ln_setting = lt_settings->lane_settings[0]; -+} -+ -+static bool is_cr_done(enum lane_count ln_count, -+ union lane_status *dpcd_lane_status) -+{ -+ bool done = true; -+ uint32_t lane; -+ /*LANEx_CR_DONE bits All 1's?*/ -+ for (lane = 0; lane < (uint32_t)(ln_count); lane++) { -+ if (!dpcd_lane_status[lane].bits.CR_DONE_0) -+ done = false; -+ } -+ return done; -+ -+} -+ -+static bool is_ch_eq_done(enum lane_count ln_count, -+ union lane_status *dpcd_lane_status, -+ union lane_align_status_updated *lane_status_updated) -+{ -+ bool done = true; -+ uint32_t lane; -+ if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE) -+ done = false; -+ else { -+ for (lane = 0; lane < (uint32_t)(ln_count); lane++) { -+ if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 || -+ !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) -+ done = false; -+ } -+ } -+ return done; -+ -+} -+ -+static void update_drive_settings( -+ struct link_training_settings *dest, -+ struct link_training_settings src) -+{ -+ uint32_t lane; -+ for (lane = 0; lane < src.link_settings.lane_count; lane++) { -+ dest->lane_settings[lane].VOLTAGE_SWING = -+ src.lane_settings[lane].VOLTAGE_SWING; -+ dest->lane_settings[lane].PRE_EMPHASIS = -+ src.lane_settings[lane].PRE_EMPHASIS; -+ dest->lane_settings[lane].POST_CURSOR2 = -+ src.lane_settings[lane].POST_CURSOR2; -+ } -+} -+ -+static uint8_t get_nibble_at_index(const uint8_t *buf, -+ uint32_t index) -+{ -+ uint8_t nibble; -+ nibble = buf[index / 2]; -+ -+ if (index % 2) -+ nibble >>= 4; -+ else -+ nibble &= 0x0F; -+ -+ return nibble; -+} -+ -+static enum pre_emphasis get_max_pre_emphasis_for_voltage_swing( -+ enum voltage_swing voltage) -+{ -+ enum pre_emphasis pre_emphasis; -+ pre_emphasis = PRE_EMPHASIS_MAX_LEVEL; -+ -+ if (voltage <= VOLTAGE_SWING_MAX_LEVEL) -+ pre_emphasis = voltage_swing_to_pre_emphasis[voltage]; -+ -+ return pre_emphasis; -+ -+} -+ -+static void find_max_drive_settings( -+ const struct link_training_settings *link_training_setting, -+ struct link_training_settings *max_lt_setting) -+{ -+ uint32_t lane; -+ struct lane_settings max_requested; -+ -+ max_requested.VOLTAGE_SWING = -+ link_training_setting-> -+ lane_settings[0].VOLTAGE_SWING; -+ max_requested.PRE_EMPHASIS = -+ link_training_setting-> -+ lane_settings[0].PRE_EMPHASIS; -+ /*max_requested.postCursor2 = -+ * link_training_setting->laneSettings[0].postCursor2;*/ -+ -+ /* Determine what the maximum of the requested settings are*/ -+ for (lane = 1; lane < link_training_setting->link_settings.lane_count; -+ lane++) { -+ if (link_training_setting->lane_settings[lane].VOLTAGE_SWING > -+ max_requested.VOLTAGE_SWING) -+ -+ max_requested.VOLTAGE_SWING = -+ link_training_setting-> -+ lane_settings[lane].VOLTAGE_SWING; -+ -+ -+ if (link_training_setting->lane_settings[lane].PRE_EMPHASIS > -+ max_requested.PRE_EMPHASIS) -+ max_requested.PRE_EMPHASIS = -+ link_training_setting-> -+ lane_settings[lane].PRE_EMPHASIS; -+ -+ /* -+ if (link_training_setting->laneSettings[lane].postCursor2 > -+ max_requested.postCursor2) -+ { -+ max_requested.postCursor2 = -+ link_training_setting->laneSettings[lane].postCursor2; -+ } -+ */ -+ } -+ -+ /* make sure the requested settings are -+ * not higher than maximum settings*/ -+ if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL) -+ max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL; -+ -+ if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL) -+ max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL; -+ /* -+ if (max_requested.postCursor2 > PostCursor2_MaxLevel) -+ max_requested.postCursor2 = PostCursor2_MaxLevel; -+ */ -+ -+ /* make sure the pre-emphasis matches the voltage swing*/ -+ if (max_requested.PRE_EMPHASIS > -+ get_max_pre_emphasis_for_voltage_swing( -+ max_requested.VOLTAGE_SWING)) -+ max_requested.PRE_EMPHASIS = -+ get_max_pre_emphasis_for_voltage_swing( -+ max_requested.VOLTAGE_SWING); -+ -+ /* -+ * Post Cursor2 levels are completely independent from -+ * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels -+ * can only be applied to each allowable combination of voltage -+ * swing and pre-emphasis levels */ -+ /* if ( max_requested.postCursor2 > -+ * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing)) -+ * max_requested.postCursor2 = -+ * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing); -+ */ -+ -+ max_lt_setting->link_settings.link_rate = -+ link_training_setting->link_settings.link_rate; -+ max_lt_setting->link_settings.lane_count = -+ link_training_setting->link_settings.lane_count; -+ max_lt_setting->link_settings.link_spread = -+ link_training_setting->link_settings.link_spread; -+ -+ for (lane = 0; lane < -+ link_training_setting->link_settings.lane_count; -+ lane++) { -+ max_lt_setting->lane_settings[lane].VOLTAGE_SWING = -+ max_requested.VOLTAGE_SWING; -+ max_lt_setting->lane_settings[lane].PRE_EMPHASIS = -+ max_requested.PRE_EMPHASIS; -+ /*max_lt_setting->laneSettings[lane].postCursor2 = -+ * max_requested.postCursor2; -+ */ -+ } -+ -+} -+ -+static void get_lane_status_and_drive_settings( -+ struct core_link* link, -+ const struct link_training_settings *link_training_setting, -+ union lane_status *ln_status, -+ union lane_align_status_updated *ln_status_updated, -+ struct link_training_settings *req_settings) -+{ -+ uint8_t dpcd_buf[6] = {0}; -+ union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}}; -+ struct link_training_settings request_settings = {{0}}; -+ uint32_t lane; -+ -+ dc_service_memset(req_settings, '\0', sizeof(struct link_training_settings)); -+ -+ core_link_read_dpcd( -+ link, -+ DPCD_ADDRESS_LANE_01_STATUS, -+ (uint8_t *)(dpcd_buf), -+ sizeof(dpcd_buf)); -+ -+ -+ for (lane = 0; lane < -+ (uint32_t)(link_training_setting->link_settings.lane_count); -+ lane++) { -+ -+ ln_status[lane].raw = -+ get_nibble_at_index(&dpcd_buf[0], lane); -+ dpcd_lane_adjust[lane].raw = -+ get_nibble_at_index(&dpcd_buf[4], lane); -+ } -+ -+ ln_status_updated->raw = dpcd_buf[2]; -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ", -+ __func__, -+ DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0], -+ DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]); -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n", -+ __func__, -+ DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, -+ dpcd_buf[4], -+ DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3, -+ dpcd_buf[5]); -+ -+ /*copy to req_settings*/ -+ request_settings.link_settings.lane_count = -+ link_training_setting->link_settings.lane_count; -+ request_settings.link_settings.link_rate = -+ link_training_setting->link_settings.link_rate; -+ request_settings.link_settings.link_spread = -+ link_training_setting->link_settings.link_spread; -+ -+ for (lane = 0; lane < -+ (uint32_t)(link_training_setting->link_settings.lane_count); -+ lane++) { -+ -+ request_settings.lane_settings[lane].VOLTAGE_SWING = -+ (enum voltage_swing)(dpcd_lane_adjust[lane].bits. -+ VOLTAGE_SWING_LANE); -+ request_settings.lane_settings[lane].PRE_EMPHASIS = -+ (enum pre_emphasis)(dpcd_lane_adjust[lane].bits. -+ PRE_EMPHASIS_LANE); -+ } -+ -+ /*Note: for postcursor2, read adjusted -+ * postcursor2 settings from*/ -+ /*DpcdAddress_AdjustRequestPostCursor2 = -+ *0x020C (not implemented yet)*/ -+ -+ /* we find the maximum of the requested settings across all lanes*/ -+ /* and set this maximum for all lanes*/ -+ find_max_drive_settings(&request_settings, req_settings); -+ -+ /* if post cursor 2 is needed in the future, -+ * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C -+ */ -+ -+} -+ -+static void dpcd_set_lane_settings( -+ struct core_link* link, -+ const struct link_training_settings *link_training_setting) -+{ -+ union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; -+ uint32_t lane; -+ -+ for (lane = 0; lane < -+ (uint32_t)(link_training_setting-> -+ link_settings.lane_count); -+ lane++) { -+ dpcd_lane[lane].bits.VOLTAGE_SWING_SET = -+ (uint8_t)(link_training_setting-> -+ lane_settings[lane].VOLTAGE_SWING); -+ dpcd_lane[lane].bits.PRE_EMPHASIS_SET = -+ (uint8_t)(link_training_setting-> -+ lane_settings[lane].PRE_EMPHASIS); -+ dpcd_lane[lane].bits.MAX_SWING_REACHED = -+ (link_training_setting-> -+ lane_settings[lane].VOLTAGE_SWING == -+ VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); -+ dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = -+ (link_training_setting-> -+ lane_settings[lane].PRE_EMPHASIS == -+ PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); -+ } -+ -+ core_link_write_dpcd(link, -+ DPCD_ADDRESS_LANE0_SET, -+ (uint8_t *)(dpcd_lane), -+ link_training_setting->link_settings.lane_count); -+ -+ /* -+ if (LTSettings.link.rate == LinkRate_High2) -+ { -+ DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0}; -+ for ( uint32_t lane = 0; -+ lane < lane_count_DPMax; lane++) -+ { -+ dpcd_lane2[lane].bits.post_cursor2_set = -+ static_cast<unsigned char>( -+ LTSettings.laneSettings[lane].postCursor2); -+ dpcd_lane2[lane].bits.max_post_cursor2_reached = 0; -+ } -+ m_pDpcdAccessSrv->WriteDpcdData( -+ DpcdAddress_Lane0Set2, -+ reinterpret_cast<unsigned char*>(dpcd_lane2), -+ LTSettings.link.lanes); -+ } -+ */ -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ "%s\n %x VS set = %x PE set = %x \ -+ max VS Reached = %x max PE Reached = %x\n", -+ __func__, -+ DPCD_ADDRESS_LANE0_SET, -+ dpcd_lane[0].bits.VOLTAGE_SWING_SET, -+ dpcd_lane[0].bits.PRE_EMPHASIS_SET, -+ dpcd_lane[0].bits.MAX_SWING_REACHED, -+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); -+ -+ link->ln_setting = link_training_setting->lane_settings[0]; -+ -+} -+ -+static bool is_max_vs_reached( -+ const struct link_training_settings *lt_settings) -+{ -+ uint32_t lane; -+ for (lane = 0; lane < -+ (uint32_t)(lt_settings->link_settings.lane_count); -+ lane++) { -+ if (lt_settings->lane_settings[lane].VOLTAGE_SWING -+ == VOLTAGE_SWING_MAX_LEVEL) -+ return true; -+ } -+ return false; -+ -+} -+ -+void set_drive_settings( -+ struct core_link *link, -+ struct link_training_settings *lt_settings) -+{ -+ /* program ASIC PHY settings*/ -+ dp_set_hw_lane_settings(link, lt_settings); -+ -+ /* Notify DP sink the PHY settings from source */ -+ dpcd_set_lane_settings(link, lt_settings); -+} -+ -+static bool perform_post_lt_adj_req_sequence( -+ struct core_link *link, -+ struct link_training_settings *lt_settings) -+{ -+ enum lane_count lane_count = -+ lt_settings->link_settings.lane_count; -+ -+ uint32_t adj_req_count; -+ uint32_t adj_req_timer; -+ bool req_drv_setting_changed; -+ uint32_t lane; -+ -+ req_drv_setting_changed = false; -+ for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT; -+ adj_req_count++) { -+ -+ req_drv_setting_changed = false; -+ -+ for (adj_req_timer = 0; -+ adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT; -+ adj_req_timer++) { -+ -+ struct link_training_settings req_settings; -+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; -+ union lane_align_status_updated -+ dpcd_lane_status_updated; -+ -+ get_lane_status_and_drive_settings( -+ link, -+ lt_settings, -+ dpcd_lane_status, -+ &dpcd_lane_status_updated, -+ &req_settings); -+ -+ if (dpcd_lane_status_updated.bits. -+ POST_LT_ADJ_REQ_IN_PROGRESS == 0) -+ return true; -+ -+ if (!is_cr_done(lane_count, dpcd_lane_status)) -+ return false; -+ -+ if (!is_ch_eq_done( -+ lane_count, -+ dpcd_lane_status, -+ &dpcd_lane_status_updated)) -+ return false; -+ -+ for (lane = 0; lane < (uint32_t)(lane_count); lane++) { -+ -+ if (lt_settings-> -+ lane_settings[lane].VOLTAGE_SWING != -+ req_settings.lane_settings[lane]. -+ VOLTAGE_SWING || -+ lt_settings->lane_settings[lane].PRE_EMPHASIS != -+ req_settings.lane_settings[lane].PRE_EMPHASIS) { -+ -+ req_drv_setting_changed = true; -+ break; -+ } -+ } -+ -+ if (req_drv_setting_changed) { -+ update_drive_settings( -+ lt_settings,req_settings); -+ -+ set_drive_settings(link, lt_settings); -+ break; -+ } -+ -+ dc_service_sleep_in_milliseconds(link->ctx, 1); -+ } -+ -+ if (!req_drv_setting_changed) { -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_LINK_SERVICE, -+ "%s: Post Link Training Adjust Request Timed out\n", -+ __func__); -+ -+ ASSERT(0); -+ return true; -+ } -+ } -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_LINK_SERVICE, -+ "%s: Post Link Training Adjust Request limit reached\n", -+ __func__); -+ -+ ASSERT(0); -+ return true; -+ -+} -+ -+static bool perform_channel_equalization_sequence( -+ struct core_link *link, -+ struct link_training_settings *lt_settings) -+{ -+ struct link_training_settings req_settings; -+ enum hw_dp_training_pattern hw_tr_pattern; -+ uint32_t retries_ch_eq; -+ enum lane_count lane_count = lt_settings->link_settings.lane_count; -+ union lane_align_status_updated dpcd_lane_status_updated = {{0}}; -+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; -+ -+ /*TODO hw_tr_pattern = HW_DP_TRAINING_PATTERN_3;*/ -+ hw_tr_pattern = HW_DP_TRAINING_PATTERN_2; -+ -+ dp_set_hw_training_pattern(link, hw_tr_pattern); -+ -+ for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT; -+ retries_ch_eq++) { -+ -+ dp_set_hw_lane_settings(link, lt_settings); -+ -+ /* 2. update DPCD*/ -+ if (!retries_ch_eq) -+ /* EPR #361076 - write as a 5-byte burst, -+ * but only for the 1-st iteration*/ -+ dpcd_set_lt_pattern_and_lane_settings( -+ link, -+ lt_settings, -+ hw_tr_pattern); -+ else -+ dpcd_set_lane_settings(link, lt_settings); -+ -+ /* 3. wait for receiver to lock-on*/ -+ wait_for_training_aux_rd_interval(link, 400); -+ -+ /* 4. Read lane status and requested -+ * drive settings as set by the sink*/ -+ -+ get_lane_status_and_drive_settings( -+ link, -+ lt_settings, -+ dpcd_lane_status, -+ &dpcd_lane_status_updated, -+ &req_settings); -+ -+ /* 5. check CR done*/ -+ if (!is_cr_done(lane_count, dpcd_lane_status)) -+ return false; -+ -+ /* 6. check CHEQ done*/ -+ if (is_ch_eq_done(lane_count, -+ dpcd_lane_status, -+ &dpcd_lane_status_updated)) -+ return true; -+ -+ /* 7. update VS/PE/PC2 in lt_settings*/ -+ update_drive_settings(lt_settings, req_settings); -+ } -+ -+ return false; -+ -+} -+ -+static bool perform_clock_recovery_sequence( -+ struct core_link *link, -+ struct link_training_settings *lt_settings) -+{ -+ uint32_t retries_cr; -+ uint32_t retry_count; -+ uint32_t lane; -+ struct link_training_settings req_settings; -+ enum lane_count lane_count = -+ lt_settings->link_settings.lane_count; -+ enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1; -+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; -+ union lane_align_status_updated dpcd_lane_status_updated; -+ -+ retries_cr = 0; -+ retry_count = 0; -+ /* initial drive setting (VS/PE/PC2)*/ -+ for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { -+ lt_settings->lane_settings[lane].VOLTAGE_SWING = -+ VOLTAGE_SWING_LEVEL0; -+ lt_settings->lane_settings[lane].PRE_EMPHASIS = -+ PRE_EMPHASIS_DISABLED; -+ lt_settings->lane_settings[lane].POST_CURSOR2 = -+ POST_CURSOR2_DISABLED; -+ } -+ -+ dp_set_hw_training_pattern(link, hw_tr_pattern); -+ -+ /* najeeb - The synaptics MST hub can put the LT in -+ * infinite loop by switching the VS -+ */ -+ /* between level 0 and level 1 continuously, here -+ * we try for CR lock for LinkTrainingMaxCRRetry count*/ -+ while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && -+ (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { -+ -+ dc_service_memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); -+ dc_service_memset(&dpcd_lane_status_updated, '\0', -+ sizeof(dpcd_lane_status_updated)); -+ -+ /* 1. call HWSS to set lane settings*/ -+ dp_set_hw_lane_settings( -+ link, -+ lt_settings); -+ -+ /* 2. update DPCD of the receiver*/ -+ if (!retries_cr) -+ /* EPR #361076 - write as a 5-byte burst, -+ * but only for the 1-st iteration.*/ -+ dpcd_set_lt_pattern_and_lane_settings( -+ link, -+ lt_settings, -+ hw_tr_pattern); -+ else -+ dpcd_set_lane_settings( -+ link, -+ lt_settings); -+ -+ -+ /* 3. wait receiver to lock-on*/ -+ wait_for_training_aux_rd_interval( -+ link, -+ 100); -+ -+ /* 4. Read lane status and requested drive -+ * settings as set by the sink -+ */ -+ get_lane_status_and_drive_settings( -+ link, -+ lt_settings, -+ dpcd_lane_status, -+ &dpcd_lane_status_updated, -+ &req_settings); -+ -+ -+ /* 5. check CR done*/ -+ if (is_cr_done(lane_count, dpcd_lane_status)) -+ return true; -+ -+ /* 6. max VS reached*/ -+ if (is_max_vs_reached(lt_settings)) -+ return false; -+ -+ /* 7. same voltage*/ -+ /* Note: VS same for all lanes, -+ * so comparing first lane is sufficient*/ -+ if (lt_settings->lane_settings[0].VOLTAGE_SWING == -+ req_settings.lane_settings[0].VOLTAGE_SWING) -+ retries_cr++; -+ else -+ retries_cr = 0; -+ -+ -+ /* 8. update VS/PE/PC2 in lt_settings*/ -+ update_drive_settings(lt_settings, req_settings); -+ -+ retry_count++; -+ } -+ -+ if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { -+ ASSERT(0); -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_LINK_SERVICE, -+ "%s: Link Training Error, could not \ -+ get CR after %d tries. \ -+ Possibly voltage swing issue", __func__, -+ LINK_TRAINING_MAX_CR_RETRY); -+ -+ } -+ -+ return false; -+} -+ -+ bool perform_link_training( -+ struct core_link *link, -+ const struct link_settings *link_setting, -+ bool skip_video_pattern) -+{ -+ bool status; -+ union dpcd_training_pattern dpcd_pattern = {{0}}; -+ union lane_count_set lane_count_set = {{0}}; -+ const int8_t *link_rate = "Unknown"; -+ struct link_training_settings lt_settings; -+ -+ status = false; -+ dc_service_memset(<_settings, '\0', sizeof(lt_settings)); -+ -+ lt_settings.link_settings.link_rate = link_setting->link_rate; -+ lt_settings.link_settings.lane_count = link_setting->lane_count; -+ -+ /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/ -+ -+ /* TODO hard coded to SS for now -+ * lt_settings.link_settings.link_spread = -+ * dal_display_path_is_ss_supported( -+ * path_mode->display_path) ? -+ * LINK_SPREAD_05_DOWNSPREAD_30KHZ : -+ * LINK_SPREAD_DISABLED; -+ */ -+ lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; -+ -+ /* 1. set link rate, lane count and spread*/ -+ dpcd_set_link_settings(link, <_settings); -+ -+ /* 2. perform link training (set link training done -+ * to false is done as well)*/ -+ if (perform_clock_recovery_sequence(link, <_settings)) { -+ -+ if (perform_channel_equalization_sequence(link, <_settings)) -+ status = true; -+ } -+ -+ if (status || !skip_video_pattern) { -+ -+ /* 3. set training not in progress*/ -+ dpcd_pattern.bits.TRAINING_PATTERN_SET = -+ DPCD_TRAINING_PATTERN_VIDEOIDLE; -+ dpcd_set_training_pattern(link, dpcd_pattern); -+ -+ /* 4. mainlink output idle pattern*/ -+ dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE); -+ -+ /* 5. post training adjust if required*/ -+ if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED -+ == 1) { -+ if (status == true) { -+ if (perform_post_lt_adj_req_sequence( -+ link, <_settings) == false) -+ status = false; -+ } -+ -+ lane_count_set.bits.LANE_COUNT_SET = -+ lt_settings.link_settings.lane_count; -+ lane_count_set.bits.ENHANCED_FRAMING = 1; -+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; -+ -+ core_link_write_dpcd( -+ link, -+ DPCD_ADDRESS_LANE_COUNT_SET, -+ &lane_count_set.raw, -+ sizeof(lane_count_set)); -+ } -+ } -+ -+ /* 6. print status message*/ -+ switch (lt_settings.link_settings.link_rate) { -+ -+ case LINK_RATE_LOW: -+ link_rate = "Low"; -+ break; -+ case LINK_RATE_HIGH: -+ link_rate = "High"; -+ break; -+ case LINK_RATE_HIGH2: -+ link_rate = "High2"; -+ break; -+ case LINK_RATE_RBR2: -+ link_rate = "RBR2"; -+ break; -+ default: -+ break; -+ } -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_MST, -+ LOG_MINOR_MST_PROGRAMMING, -+ "Link training for %d lanes at %s rate %s\n", -+ lt_settings.link_settings.lane_count, -+ link_rate, -+ status ? "succeeded" : "failed"); -+ -+ return status; -+} -+ -+/*TODO add more check to see if link support request link configuration */ -+static bool is_link_setting_supported( -+ const struct link_settings *link_setting, -+ const struct link_settings *max_link_setting) -+{ -+ if (link_setting->lane_count > max_link_setting->lane_count || -+ link_setting->link_rate > max_link_setting->link_rate) -+ return false; -+ return true; -+} -+ -+static const uint32_t get_link_training_fallback_table_len( -+ struct core_link *link) -+{ -+ return ARRAY_SIZE(link_training_fallback_table); -+} -+ -+static const struct link_settings *get_link_training_fallback_table( -+ struct core_link *link, uint32_t i) -+{ -+ return &link_training_fallback_table[i]; -+} -+ -+static bool exceeded_limit_link_setting(const struct link_settings *link_setting, -+ const struct link_settings *limit_link_setting) -+{ -+ return (link_setting->lane_count * link_setting->link_rate -+ > limit_link_setting->lane_count * limit_link_setting->link_rate ? -+ true : false); -+} -+ -+ -+bool dp_hbr_verify_link_cap( -+ struct core_link *link, -+ struct link_settings *known_limit_link_setting) -+{ -+ struct link_settings max_link_cap = {0}; -+ bool success; -+ bool skip_link_training; -+ const struct link_settings *cur; -+ bool skip_video_pattern; -+ uint32_t i; -+ -+ success = false; -+ skip_link_training = false; -+ -+ /* TODO confirm this is correct for cz */ -+ max_link_cap.lane_count = LANE_COUNT_FOUR; -+ max_link_cap.link_rate = LINK_RATE_HIGH2; -+ max_link_cap.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; -+ -+ /* TODO implement override and monitor patch later */ -+ -+ /* try to train the link from high to low to -+ * find the physical link capability -+ */ -+ /* disable PHY done possible by BIOS, will be done by driver itself */ -+ dp_disable_link_phy(link, link->public.connector_signal); -+ -+ for (i = 0; i < get_link_training_fallback_table_len(link) && -+ !success; i++) { -+ cur = get_link_training_fallback_table(link, i); -+ -+ if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN && -+ exceeded_limit_link_setting(cur, -+ known_limit_link_setting)) -+ continue; -+ -+ if (!is_link_setting_supported(cur, &max_link_cap)) -+ continue; -+ -+ skip_video_pattern = true; -+ if (cur->link_rate == LINK_RATE_LOW) -+ skip_video_pattern = false; -+ if (dp_enable_link_phy( -+ link, -+ link->public.connector_signal, -+ ENGINE_ID_UNKNOWN, -+ cur)) { -+ if (skip_link_training) -+ success = true; -+ else { -+ uint8_t num_retries = 3; -+ uint8_t j; -+ uint8_t delay_between_retries = 10; -+ for (j = 0; j < num_retries; ++j) { -+ success = perform_link_training( -+ link, -+ cur, -+ skip_video_pattern); -+ -+ if (success) -+ break; -+ -+ dc_service_sleep_in_milliseconds( -+ link->ctx, -+ delay_between_retries); -+ -+ delay_between_retries += 10; -+ } -+ } -+ } -+ -+ if (success) -+ link->verified_link_cap = *cur; -+ -+ /* always disable the link before trying another -+ * setting or before returning we'll enable it later -+ * based on the actual mode we're driving -+ */ -+ dp_disable_link_phy(link, link->public.connector_signal); -+ } -+ -+ /* Link Training failed for all Link Settings -+ * (Lane Count is still unknown) -+ */ -+ if (!success) { -+ /* If all LT fails for all settings, -+ * set verified = failed safe (1 lane low) -+ */ -+ link->verified_link_cap.lane_count = LANE_COUNT_ONE; -+ link->verified_link_cap.link_rate = LINK_RATE_LOW; -+ -+ link->verified_link_cap.link_spread = -+ LINK_SPREAD_DISABLED; -+ } -+ -+ link->max_link_setting = link->verified_link_cap; -+ -+ return success; -+} -+ -+static uint32_t bandwidth_in_kbps_from_timing( -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t bits_per_channel = 0; -+ uint32_t kbps; -+ switch (timing->display_color_depth) { -+ -+ case COLOR_DEPTH_666: -+ bits_per_channel = 6; -+ break; -+ case COLOR_DEPTH_888: -+ bits_per_channel = 8; -+ break; -+ case COLOR_DEPTH_101010: -+ bits_per_channel = 10; -+ break; -+ case COLOR_DEPTH_121212: -+ bits_per_channel = 12; -+ break; -+ case COLOR_DEPTH_141414: -+ bits_per_channel = 14; -+ break; -+ case COLOR_DEPTH_161616: -+ bits_per_channel = 16; -+ break; -+ default: -+ break; -+ } -+ ASSERT(bits_per_channel != 0); -+ -+ kbps = timing->pix_clk_khz; -+ kbps *= bits_per_channel; -+ -+ if (timing->flags.Y_ONLY != 1) -+ /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ -+ kbps *= 3; -+ -+ return kbps; -+ -+} -+ -+static uint32_t bandwidth_in_kbps_from_link_settings( -+ const struct link_settings *link_setting) -+{ -+ uint32_t link_rate_in_kbps = link_setting->link_rate * -+ LINK_RATE_REF_FREQ_IN_KHZ; -+ -+ uint32_t lane_count = link_setting->lane_count; -+ uint32_t kbps = link_rate_in_kbps; -+ kbps *= lane_count; -+ kbps *= 8; /* 8 bits per byte*/ -+ -+ return kbps; -+ -+} -+ -+bool dp_validate_mode_timing( -+ struct core_link *link, -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t req_bw; -+ uint32_t max_bw; -+ -+ const struct link_settings *link_setting; -+ -+ /*always DP fail safe mode*/ -+ if (timing->pix_clk_khz == (uint32_t)25175 && -+ timing->h_addressable == (uint32_t)640 && -+ timing->v_addressable == (uint32_t)480) -+ return true; -+ -+ /* For static validation we always use reported -+ * link settings for other cases, when no modelist -+ * changed we can use verified link setting*/ -+ link_setting = &link->reported_link_cap; -+ -+ /* TODO: DYNAMIC_VALIDATION needs to be implemented */ -+ /*if (flags.DYNAMIC_VALIDATION == 1 && -+ link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) -+ link_setting = &link->verified_link_cap; -+ */ -+ -+ req_bw = bandwidth_in_kbps_from_timing(timing); -+ max_bw = bandwidth_in_kbps_from_link_settings(link_setting); -+ -+ if (req_bw < max_bw) { -+ /* remember the biggest mode here, during -+ * initial link training (to get -+ * verified_link_cap), LS sends event about -+ * cannot train at reported cap to upper -+ * layer and upper layer will re-enumerate modes. -+ * this is not necessary if the lower -+ * verified_link_cap is enough to drive -+ * all the modes */ -+ -+ /* TODO: DYNAMIC_VALIDATION needs to be implemented */ -+ /* if (flags.DYNAMIC_VALIDATION == 1) -+ dpsst->max_req_bw_for_verified_linkcap = dal_max( -+ dpsst->max_req_bw_for_verified_linkcap, req_bw); */ -+ return true; -+ } else -+ return false; -+} -+ -+void decide_link_settings(struct core_stream *stream, -+ struct link_settings *link_setting) -+{ -+ -+ const struct link_settings *cur_ls; -+ struct core_link* link; -+ uint32_t req_bw; -+ uint32_t link_bw; -+ uint32_t i; -+ -+ req_bw = bandwidth_in_kbps_from_timing( -+ &stream->public.timing); -+ -+ /* if preferred is specified through AMDDP, use it, if it's enough -+ * to drive the mode -+ */ -+ link = stream->sink->link; -+ -+ if ((link->reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) && -+ (link->reported_link_cap.link_rate <= -+ link->verified_link_cap.link_rate)) { -+ -+ link_bw = bandwidth_in_kbps_from_link_settings( -+ &link->reported_link_cap); -+ -+ if (req_bw < link_bw) { -+ *link_setting = link->reported_link_cap; -+ return; -+ } -+ } -+ -+ /* search for first suitable setting for the requested -+ * bandwidth -+ */ -+ for (i = 0; i < get_link_training_fallback_table_len(link); i++) { -+ -+ cur_ls = get_link_training_fallback_table(link, i); -+ -+ link_bw = -+ bandwidth_in_kbps_from_link_settings( -+ cur_ls); -+ -+ if (req_bw < link_bw) { -+ if (is_link_setting_supported( -+ cur_ls, -+ &link->max_link_setting)) { -+ *link_setting = *cur_ls; -+ return; -+ } -+ } -+ } -+ -+ BREAK_TO_DEBUGGER(); -+ ASSERT(link->verified_link_cap.lane_count != -+ LANE_COUNT_UNKNOWN); -+ -+ *link_setting = link->verified_link_cap; -+} -+ -+/*************************Short Pulse IRQ***************************/ -+ -+static bool hpd_rx_irq_check_link_loss_status( -+ struct core_link *link, -+ union hpd_irq_data *hpd_irq_dpcd_data) -+{ -+ uint8_t irq_reg_rx_power_state; -+ enum dc_status dpcd_result = DC_ERROR_UNEXPECTED; -+ union lane_status lane_status; -+ uint32_t lane; -+ bool sink_status_changed; -+ bool return_code; -+ -+ sink_status_changed = false; -+ return_code = false; -+ -+ if (link->cur_link_settings.lane_count == 0) -+ return return_code; -+ /*1. Check that we can handle interrupt: Not in FS DOS, -+ * Not in "Display Timeout" state, Link is trained. -+ */ -+ -+ dpcd_result = core_link_read_dpcd(link, -+ DPCD_ADDRESS_POWER_STATE, -+ &irq_reg_rx_power_state, -+ sizeof(irq_reg_rx_power_state)); -+ -+ if (dpcd_result != DC_OK) { -+ irq_reg_rx_power_state = DP_PWR_STATE_D0; -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_HPD_IRQ, -+ "%s: DPCD read failed to obtain power state.\n", -+ __func__); -+ } -+ -+ if (irq_reg_rx_power_state == DP_PWR_STATE_D0) { -+ -+ /*2. Check that Link Status changed, before re-training.*/ -+ -+ /*parse lane status*/ -+ for (lane = 0; lane < -+ (uint32_t)(link->cur_link_settings.lane_count) && -+ !sink_status_changed; lane++) { -+ -+ /* check status of lanes 0,1 -+ * changed DpcdAddress_Lane01Status (0x202)*/ -+ lane_status.raw = get_nibble_at_index( -+ &hpd_irq_dpcd_data->bytes.lane01_status.raw, -+ lane); -+ -+ if (!lane_status.bits.CHANNEL_EQ_DONE_0 || -+ !lane_status.bits.CR_DONE_0 || -+ !lane_status.bits.SYMBOL_LOCKED_0) { -+ /* if one of the channel equalization, clock -+ * recovery or symbol lock is dropped -+ * consider it as (link has been -+ * dropped) dp sink status has changed*/ -+ sink_status_changed = true; -+ break; -+ } -+ -+ } -+ -+ /* Check interlane align.*/ -+ if (sink_status_changed || -+ !hpd_irq_dpcd_data->bytes.lane_status_updated.bits. -+ INTERLANE_ALIGN_DONE) { -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_HPD_IRQ, -+ "%s: Link Status changed.\n", -+ __func__); -+ -+ return_code = true; -+ } -+ } -+ -+ return return_code; -+} -+ -+static enum dc_status read_hpd_rx_irq_data( -+ struct core_link *link, -+ union hpd_irq_data *irq_data) -+{ -+ /* The HW reads 16 bytes from 200h on HPD, -+ * but if we get an AUX_DEFER, the HW cannot retry -+ * and this causes the CTS tests 4.3.2.1 - 3.2.4 to -+ * fail, so we now explicitly read 6 bytes which is -+ * the req from the above mentioned test cases. -+ */ -+ return core_link_read_dpcd( -+ link, -+ DPCD_ADDRESS_SINK_COUNT, -+ irq_data->raw, -+ sizeof(union hpd_irq_data)); -+} -+ -+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) -+{ -+ struct core_link *link = DC_LINK_TO_LINK(dc_link); -+ union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; -+ enum dc_status result = DDC_RESULT_UNKNOWN; -+ bool status = false; -+ /* For use cases related to down stream connection status change, -+ * PSR and device auto test, refer to function handle_sst_hpd_irq -+ * in DAL2.1*/ -+ -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_HPD_IRQ, -+ "%s: Got short pulse HPD on connector %d\n", -+ __func__, link->connector_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) { -+ dal_logger_write(link->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_HPD_IRQ, -+ "%s: DPCD read failed to obtain irq data\n", -+ __func__); -+ return false; -+ } -+ -+ /* check if we have MST msg and return since we poll for it */ -+ if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY || -+ hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) -+ return false; -+ -+ -+ /* For now we only handle 'Downstream port status' case. */ -+ /* If we got sink count changed it means Downstream port status changed, -+ * then DM should call DC to do the detection. */ -+ if (hpd_rx_irq_check_link_loss_status( -+ link, -+ &hpd_irq_dpcd_data)) { -+ perform_link_training(link, &link->cur_link_settings, true); -+ status = false; -+ } -+ -+ if (hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT -+ != link->dpcd_sink_count) -+ status = true; -+ -+ /* reasons for HPD RX: -+ * 1. Link Loss - ie Re-train the Link -+ * 2. MST sideband message -+ * 3. Automated Test - ie. Internal Commit -+ * 4. CP (copy protection) - (not interesting for DM???) -+ * 5. DRR -+ * 6. Downstream Port status changed -ie. Detect - this the only one -+ * which is interesting for DM because it must call dc_link_detect. -+ */ -+ return status; -+} -+ -+/*query dpcd for version and mst cap addresses*/ -+bool is_mst_supported(struct core_link *link) -+{ -+ bool mst = false; -+ enum dc_status st = DC_OK; -+ union dpcd_rev rev; -+ union mstm_cap cap; -+ -+ rev.raw = 0; -+ cap.raw = 0; -+ -+ st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw, -+ sizeof(rev)); -+ -+ if (st == DC_OK && rev.raw >= DPCD_REV_12) { -+ -+ st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP, -+ &cap.raw, sizeof(cap)); -+ if (st == DC_OK && cap.bits.MST_CAP == 1) -+ mst = true; -+ } -+ return mst; -+ -+} -+ -+static void get_active_converter_info( -+ uint8_t data, struct core_link *link) -+{ -+ union dp_downstream_port_present ds_port = { .byte = data }; -+ -+ /* decode converter info*/ -+ if (!ds_port.fields.PORT_PRESENT) { -+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; -+ ddc_service_set_dongle_type(link->ddc, -+ link->dpcd_caps.dongle_type); -+ return; -+ } -+ -+ switch (ds_port.fields.PORT_TYPE) { -+ case DOWNSTREAM_VGA: -+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER; -+ break; -+ case DOWNSTREAM_DVI_HDMI: -+ /* At this point we don't know is it DVI or HDMI, -+ * assume DVI.*/ -+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER; -+ break; -+ default: -+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; -+ break; -+ } -+ -+ if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) { -+ uint8_t det_caps[4]; -+ union dwnstream_port_caps_byte0 *port_caps = -+ (union dwnstream_port_caps_byte0 *)det_caps; -+ core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS, -+ det_caps, sizeof(det_caps)); -+ -+ switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { -+ case DOWN_STREAM_DETAILED_VGA: -+ link->dpcd_caps.dongle_type = -+ DISPLAY_DONGLE_DP_VGA_CONVERTER; -+ break; -+ case DOWN_STREAM_DETAILED_DVI: -+ link->dpcd_caps.dongle_type = -+ DISPLAY_DONGLE_DP_DVI_CONVERTER; -+ break; -+ case DOWN_STREAM_DETAILED_HDMI: -+ link->dpcd_caps.dongle_type = -+ DISPLAY_DONGLE_DP_HDMI_CONVERTER; -+ -+ if (ds_port.fields.DETAILED_CAPS) { -+ -+ union dwnstream_port_caps_byte3_hdmi -+ hdmi_caps = {.raw = det_caps[3] }; -+ -+ link->dpcd_caps.is_dp_hdmi_s3d_converter = -+ hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; -+ } -+ break; -+ } -+ } -+ ddc_service_set_dongle_type(link->ddc, -+ link->dpcd_caps.dongle_type); -+} -+ -+static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, -+ int length) -+{ -+ int retry = 0; -+ struct dp_device_vendor_id dp_id; -+ union dp_downstream_port_present ds_port = { 0 }; -+ -+ if (!link->dpcd_caps.dpcd_rev.raw) { -+ do { -+ dp_receiver_power_ctrl(link, true); -+ core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, -+ dpcd_data, length); -+ link->dpcd_caps.dpcd_rev.raw = dpcd_data[ -+ DPCD_ADDRESS_DPCD_REV - -+ DPCD_ADDRESS_DPCD_REV]; -+ } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); -+ } -+ -+ ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - -+ DPCD_ADDRESS_DPCD_REV]; -+ -+ get_active_converter_info(ds_port.byte, link); -+ -+ /* read IEEE branch device id */ -+ core_link_read_dpcd(link, DPCD_ADDRESS_BRANCH_DEVICE_ID_START, -+ (uint8_t *)&dp_id, sizeof(dp_id)); -+ link->dpcd_caps.branch_dev_id = -+ (dp_id.ieee_oui[0] << 16) + -+ (dp_id.ieee_oui[1] << 8) + -+ dp_id.ieee_oui[2]; -+ -+ if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { -+ switch (link->dpcd_caps.branch_dev_id) { -+ /* Some active dongles (DP-VGA, DP-DLDVI converters) power down -+ * all internal circuits including AUX communication preventing -+ * reading DPCD table and EDID (spec violation). -+ * Encoder will skip DP RX power down on disable_output to -+ * keep receiver powered all the time.*/ -+ case DP_BRANCH_DEVICE_ID_1: -+ case DP_BRANCH_DEVICE_ID_4: -+ link->dp_wa.bits.KEEP_RECEIVER_POWERED = 1; -+ break; -+ -+ /* TODO: May need work around for other dongles. */ -+ default: -+ link->dp_wa.bits.KEEP_RECEIVER_POWERED = 0; -+ break; -+ } -+ } else -+ link->dp_wa.bits.KEEP_RECEIVER_POWERED = 0; -+} -+ -+static void retrieve_link_cap(struct core_link *link) -+{ -+ uint8_t dpcd_data[ -+ DPCD_ADDRESS_EDP_CONFIG_CAP - -+ DPCD_ADDRESS_DPCD_REV + 1]; -+ -+ union down_stream_port_count down_strm_port_count; -+ union edp_configuration_cap edp_config_cap; -+ union max_down_spread max_down_spread; -+ union dp_downstream_port_present ds_port = { 0 }; -+ -+ dc_service_memset(dpcd_data, '\0', sizeof(dpcd_data)); -+ dc_service_memset(&down_strm_port_count, -+ '\0', sizeof(union down_stream_port_count)); -+ dc_service_memset(&edp_config_cap, '\0', -+ sizeof(union edp_configuration_cap)); -+ dc_service_memset(&max_down_spread, '\0', -+ sizeof(union max_down_spread)); -+ -+ core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, -+ dpcd_data, sizeof(dpcd_data)); -+ link->dpcd_caps.dpcd_rev.raw = dpcd_data[ -+ DPCD_ADDRESS_DPCD_REV - -+ DPCD_ADDRESS_DPCD_REV]; -+ -+ ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - -+ DPCD_ADDRESS_DPCD_REV]; -+ -+ get_active_converter_info(ds_port.byte, link); -+ -+ dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); -+ -+ link->dpcd_caps.allow_invalid_MSA_timing_param = -+ down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; -+ -+ link->dpcd_caps.max_ln_count.raw = dpcd_data[ -+ DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV]; -+ -+ max_down_spread.raw = dpcd_data[ -+ DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV]; -+ -+ link->reported_link_cap.lane_count = -+ link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; -+ link->reported_link_cap.link_rate = dpcd_data[ -+ DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV]; -+ link->reported_link_cap.link_spread = -+ max_down_spread.bits.MAX_DOWN_SPREAD ? -+ LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; -+ -+ edp_config_cap.raw = dpcd_data[ -+ DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV]; -+ link->dpcd_caps.panel_mode_edp = -+ edp_config_cap.bits.ALT_SCRAMBLER_RESET; -+ -+ link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN; -+ -+ /* read sink count */ -+ core_link_read_dpcd(link, -+ DPCD_ADDRESS_SINK_COUNT, -+ &link->dpcd_caps.sink_count.raw, -+ sizeof(link->dpcd_caps.sink_count.raw)); -+ -+ /* Display control registers starting at DPCD 700h are only valid and -+ * enabled if this eDP config cap bit is set. */ -+ if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { -+ /* Read the Panel's eDP revision at DPCD 700h. */ -+ core_link_read_dpcd(link, -+ DPCD_ADDRESS_EDP_REV, -+ (uint8_t *)(&link->edp_revision), -+ sizeof(link->edp_revision)); -+ } -+ /* TODO: Confirm if need retrieve_psr_link_cap */ -+} -+ -+void detect_dp_sink_caps(struct core_link *link) -+{ -+ retrieve_link_cap(link); -+ -+ /* dc init_hw has power encoder using default -+ * signal for connector. For native DP, no -+ * need to power up encoder again. If not native -+ * DP, hw_init may need check signal or power up -+ * encoder here. -+ */ -+ -+ if (is_mst_supported(link)) { -+ link->verified_link_cap = link->reported_link_cap; -+ } else { -+ dp_hbr_verify_link_cap(link, -+ &link->reported_link_cap); -+ } -+ /* TODO save sink caps in link->sink */ -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c -new file mode 100644 -index 0000000..164cdeb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c -@@ -0,0 +1,188 @@ -+/* Copyright 2015 Advanced Micro Devices, Inc. */ -+ -+#include "dc_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 "include/connector_interface.h" -+#include "hw_sequencer.h" -+#include "include/ddc_service_interface.h" -+ -+enum dc_status core_link_read_dpcd( -+ struct core_link* link, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t size) -+{ -+ if (dal_ddc_service_read_dpcd_data(link->ddc, address, data, size) -+ != DDC_RESULT_SUCESSFULL) -+ 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 (dal_ddc_service_write_dpcd_data(link->ddc, address, data, size) -+ != DDC_RESULT_SUCESSFULL) -+ 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)); -+} -+ -+ -+/* TODO: HBR2 need raise clock for DP link training */ -+enum dc_status dp_enable_link_phy( -+ struct core_link *link, -+ enum signal_type signal, -+ enum engine_id engine, -+ const struct link_settings *link_settings) -+{ -+ enum dc_status status = DC_OK; -+ -+ if (link->dc->hwss.encoder_enable_output( -+ link->link_enc, -+ link_settings, -+ engine, -+ CLOCK_SOURCE_ID_EXTERNAL, -+ signal, -+ COLOR_DEPTH_UNDEFINED, -+ 0) != ENCODER_RESULT_OK) -+ status = DC_ERROR_UNEXPECTED; -+ -+ dp_receiver_power_ctrl(link, true); -+ -+ return status; -+} -+ -+void dp_disable_link_phy(struct core_link *link, enum signal_type signal) -+{ -+ if(!link) -+ return; -+ -+ if (!link->dp_wa.bits.KEEP_RECEIVER_POWERED) -+ dp_receiver_power_ctrl(link, false); -+ -+ link->dc->hwss.encoder_disable_output(link->link_enc, signal); -+ -+ /* Clear current link setting.*/ -+ dc_service_memset(&link->cur_link_settings, 0, -+ sizeof(link->cur_link_settings)); -+} -+ -+bool dp_set_hw_training_pattern( -+ struct core_link *link, -+ enum hw_dp_training_pattern pattern) -+{ -+ enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; -+ struct encoder_set_dp_phy_pattern_param pattern_param = {0}; -+ struct link_encoder *encoder = link->link_enc; -+ -+ switch (pattern) { -+ case HW_DP_TRAINING_PATTERN_1: -+ test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; -+ break; -+ case HW_DP_TRAINING_PATTERN_2: -+ test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; -+ break; -+ case HW_DP_TRAINING_PATTERN_3: -+ test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; -+ break; -+ default: -+ break; -+ } -+ -+ pattern_param.dp_phy_pattern = test_pattern; -+ pattern_param.custom_pattern = NULL; -+ pattern_param.custom_pattern_size = 0; -+ pattern_param.dp_panel_mode = dp_get_panel_mode(link); -+ -+ link->ctx->dc->hwss.encoder_set_dp_phy_pattern(encoder, &pattern_param); -+ -+ return true; -+} -+ -+ -+bool 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 */ -+ link->ctx->dc->hwss.encoder_dp_set_lane_settings(encoder, link_settings); -+ -+ return true; -+} -+ -+enum dp_panel_mode dp_get_panel_mode(struct core_link *link) -+{ -+ /* We need to explicitly check that connector -+ * is not DP. Some Travis_VGA get reported -+ * by video bios as DP. -+ */ -+ if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { -+ -+ switch (link->dpcd_caps.branch_dev_id) { -+ case DP_BRANCH_DEVICE_ID_2: -+ if (strncmp( -+ link->dpcd_caps.branch_dev_name, -+ DP_VGA_LVDS_CONVERTER_ID_2, -+ sizeof( -+ link->dpcd_caps. -+ branch_dev_name)) == 0) { -+ return DP_PANEL_MODE_SPECIAL; -+ } -+ break; -+ case DP_BRANCH_DEVICE_ID_3: -+ if (strncmp(link->dpcd_caps.branch_dev_name, -+ DP_VGA_LVDS_CONVERTER_ID_3, -+ sizeof( -+ link->dpcd_caps. -+ branch_dev_name)) == 0) { -+ return DP_PANEL_MODE_SPECIAL; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (link->dpcd_caps.panel_mode_edp) { -+ return DP_PANEL_MODE_EDP; -+ } -+ } -+ -+ return DP_PANEL_MODE_DEFAULT; -+} -+ -+void dp_set_hw_test_pattern( -+ struct core_link *link, -+ enum dp_test_pattern test_pattern) -+{ -+ struct encoder_set_dp_phy_pattern_param pattern_param = {0}; -+ struct link_encoder *encoder = link->link_enc; -+ -+ pattern_param.dp_phy_pattern = test_pattern; -+ pattern_param.custom_pattern = NULL; -+ pattern_param.custom_pattern_size = 0; -+ pattern_param.dp_panel_mode = dp_get_panel_mode(link); -+ -+ link->ctx->dc->hwss.encoder_set_dp_phy_pattern(encoder, &pattern_param); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c -new file mode 100644 -index 0000000..5803e22 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c -@@ -0,0 +1,378 @@ -+/* -+* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_services.h" -+ -+#include "resource.h" -+#include "include/irq_service_interface.h" -+#include "link_encoder_types.h" -+#include "stream_encoder_types.h" -+ -+ -+void unreference_clock_source( -+ struct resource_context *res_ctx, -+ struct clock_source *clock_source) -+{ -+ int i; -+ for (i = 0; i < res_ctx->pool.clk_src_count; i++) { -+ if (res_ctx->pool.clock_sources[i] == clock_source) { -+ res_ctx->clock_source_ref_count[i]--; -+ } -+ } -+} -+ -+void reference_clock_source( -+ struct resource_context *res_ctx, -+ struct clock_source *clock_source) -+{ -+ int i; -+ for (i = 0; i < res_ctx->pool.clk_src_count; i++) { -+ if (res_ctx->pool.clock_sources[i] == clock_source) { -+ res_ctx->clock_source_ref_count[i]++; -+ } -+ } -+} -+ -+bool is_same_timing( -+ const struct dc_crtc_timing *timing1, -+ const struct dc_crtc_timing *timing2) -+{ -+ return dal_memcmp(timing1, timing2, sizeof(struct dc_crtc_timing)) == 0; -+} -+ -+static bool is_sharable_clk_src( -+ const struct core_stream *stream_with_clk_src, -+ const struct core_stream *stream) -+{ -+ enum clock_source_id id = dal_clock_source_get_id( -+ stream_with_clk_src->clock_source); -+ -+ if (stream_with_clk_src->clock_source == NULL) -+ return false; -+ -+ if (!dc_is_dp_signal(stream->signal) && id == CLOCK_SOURCE_ID_EXTERNAL) -+ return false; -+ -+ if(!is_same_timing( -+ &stream_with_clk_src->public.timing, &stream->public.timing)) -+ return false; -+ -+ return true; -+} -+ -+struct clock_source *find_used_clk_src_for_sharing( -+ struct validate_context *context, -+ struct core_stream *stream) -+{ -+ uint8_t i, j; -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ for (j = 0; j < target->stream_count; j++) -+ { -+ if (target->streams[j]->clock_source == NULL) -+ continue; -+ if (is_sharable_clk_src(target->streams[j], stream)) -+ return target->streams[j]->clock_source; -+ } -+ } -+ -+ return NULL; -+} -+ -+static enum pixel_format convert_pixel_format_to_dalsurface( -+ enum surface_pixel_format surface_pixel_format) -+{ -+ enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; -+ -+ switch (surface_pixel_format) { -+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: -+ dal_pixel_format = PIXEL_FORMAT_INDEX8; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: -+ dal_pixel_format = PIXEL_FORMAT_RGB565; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565: -+ dal_pixel_format = PIXEL_FORMAT_RGB565; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: -+ dal_pixel_format = PIXEL_FORMAT_ARGB8888; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: -+ dal_pixel_format = PIXEL_FORMAT_ARGB8888; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: -+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: -+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: -+ dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: -+ dal_pixel_format = PIXEL_FORMAT_FP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: -+ dal_pixel_format = PIXEL_FORMAT_FP16; -+ break; -+ -+ -+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: -+ dal_pixel_format = PIXEL_FORMAT_420BPP12; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: -+ dal_pixel_format = PIXEL_FORMAT_420BPP12; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb: -+ dal_pixel_format = PIXEL_FORMAT_422BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr: -+ dal_pixel_format = PIXEL_FORMAT_422BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY: -+ dal_pixel_format = PIXEL_FORMAT_422BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY: -+ dal_pixel_format = PIXEL_FORMAT_422BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555: -+ dal_pixel_format = PIXEL_FORMAT_444BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565: -+ dal_pixel_format = PIXEL_FORMAT_444BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444: -+ dal_pixel_format = PIXEL_FORMAT_444BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551: -+ dal_pixel_format = PIXEL_FORMAT_444BPP16; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888: -+ dal_pixel_format = PIXEL_FORMAT_444BPP32; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010: -+ dal_pixel_format = PIXEL_FORMAT_444BPP32; -+ break; -+ case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102: -+ dal_pixel_format = PIXEL_FORMAT_444BPP32; -+ break; -+ default: -+ dal_pixel_format = PIXEL_FORMAT_UNKNOWN; -+ break; -+ } -+ return dal_pixel_format; -+} -+ -+static void calculate_viewport( -+ const struct dc_surface *surface, -+ struct core_stream *stream) -+{ -+ const struct rect src = surface->src_rect; -+ const struct rect clip = surface->clip_rect; -+ const struct rect dst = surface->dst_rect; -+ -+ /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio -+ * num_pixels = clip.num_pix * scl_ratio -+ */ -+ stream->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width; -+ stream->viewport.width = clip.width * src.width / dst.width; -+ -+ stream->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height; -+ stream->viewport.height = clip.height * src.height / dst.height; -+ -+ /* Minimum viewport such that 420/422 chroma vp is non 0 */ -+ if (stream->viewport.width < 2) -+ { -+ stream->viewport.width = 2; -+ } -+ if (stream->viewport.height < 2) -+ { -+ stream->viewport.height = 2; -+ } -+} -+ -+static void calculate_overscan( -+ const struct dc_surface *surface, -+ struct core_stream *stream) -+{ -+ stream->overscan.left = stream->public.dst.x; -+ if (stream->public.src.x < surface->clip_rect.x) -+ stream->overscan.left += (surface->clip_rect.x -+ - stream->public.src.x) * stream->public.dst.width -+ / stream->public.src.width; -+ -+ stream->overscan.right = stream->public.timing.h_addressable -+ - stream->public.dst.x - stream->public.dst.width; -+ if (stream->public.src.x + stream->public.src.width -+ > surface->clip_rect.x + surface->clip_rect.width) -+ stream->overscan.right = stream->public.timing.h_addressable - -+ dal_fixed31_32_floor(dal_fixed31_32_div( -+ dal_fixed31_32_from_int( -+ stream->viewport.width), -+ stream->ratios.horz)) - -+ stream->overscan.left; -+ -+ -+ stream->overscan.top = stream->public.dst.y; -+ if (stream->public.src.y < surface->clip_rect.y) -+ stream->overscan.top += (surface->clip_rect.y -+ - stream->public.src.y) * stream->public.dst.height -+ / stream->public.src.height; -+ -+ stream->overscan.bottom = stream->public.timing.v_addressable -+ - stream->public.dst.y - stream->public.dst.height; -+ if (stream->public.src.y + stream->public.src.height -+ > surface->clip_rect.y + surface->clip_rect.height) -+ stream->overscan.bottom = stream->public.timing.v_addressable - -+ dal_fixed31_32_floor(dal_fixed31_32_div( -+ dal_fixed31_32_from_int( -+ stream->viewport.height), -+ stream->ratios.vert)) - -+ stream->overscan.top; -+ -+ -+ /* TODO: Add timing overscan to finalize overscan calculation*/ -+} -+ -+static void calculate_scaling_ratios( -+ const struct dc_surface *surface, -+ struct core_stream *stream) -+{ -+ const uint32_t in_w = stream->public.src.width; -+ const uint32_t in_h = stream->public.src.height; -+ const uint32_t out_w = stream->public.dst.width; -+ const uint32_t out_h = stream->public.dst.height; -+ -+ stream->ratios.horz = dal_fixed31_32_from_fraction( -+ surface->src_rect.width, -+ surface->dst_rect.width); -+ stream->ratios.vert = dal_fixed31_32_from_fraction( -+ surface->src_rect.height, -+ surface->dst_rect.height); -+ -+ if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) -+ stream->ratios.horz.value *= 2; -+ else if (surface->stereo_format -+ == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) -+ stream->ratios.vert.value *= 2; -+ -+ stream->ratios.vert.value = stream->ratios.vert.value * in_h / out_h; -+ stream->ratios.horz.value = stream->ratios.horz.value * in_w / out_w; -+ -+ stream->ratios.horz_c = stream->ratios.horz; -+ stream->ratios.vert_c = stream->ratios.vert; -+ -+ if (stream->format == PIXEL_FORMAT_420BPP12) { -+ stream->ratios.horz_c.value /= 2; -+ stream->ratios.vert_c.value /= 2; -+ } else if (stream->format == PIXEL_FORMAT_422BPP16) { -+ stream->ratios.horz_c.value /= 2; -+ } -+} -+ -+/*TODO: per pipe not per stream*/ -+void build_scaling_params( -+ const struct dc_surface *surface, -+ struct core_stream *stream) -+{ -+ /* Important: scaling ratio calculation requires pixel format, -+ * overscan calculation requires scaling ratios and viewport -+ * and lb depth/taps calculation requires overscan. Call sequence -+ * is therefore important */ -+ stream->format = convert_pixel_format_to_dalsurface(surface->format); -+ -+ calculate_viewport(surface, stream); -+ -+ calculate_scaling_ratios(surface, stream); -+ -+ calculate_overscan(surface, stream); -+ -+ /* Check if scaling is required update taps if not */ -+ if (dal_fixed31_32_u2d19(stream->ratios.horz) == 1 << 19) -+ stream->taps.h_taps = 1; -+ else -+ stream->taps.h_taps = surface->scaling_quality.h_taps; -+ -+ if (dal_fixed31_32_u2d19(stream->ratios.horz_c) == 1 << 19) -+ stream->taps.h_taps_c = 1; -+ else -+ stream->taps.h_taps_c = surface->scaling_quality.h_taps_c; -+ -+ if (dal_fixed31_32_u2d19(stream->ratios.vert) == 1 << 19) -+ stream->taps.v_taps = 1; -+ else -+ stream->taps.v_taps = surface->scaling_quality.v_taps; -+ -+ if (dal_fixed31_32_u2d19(stream->ratios.vert_c) == 1 << 19) -+ stream->taps.v_taps_c = 1; -+ else -+ stream->taps.v_taps_c = surface->scaling_quality.v_taps_c; -+} -+ -+void build_scaling_params_for_context( -+ const struct dc *dc, -+ struct validate_context *context) -+{ -+ uint8_t i, j, k; -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ if (context->target_flags[i].unchanged) -+ continue; -+ for (j = 0; j < target->status.surface_count; j++) { -+ const struct dc_surface *surface = target->status.surfaces[j]; -+ for (k = 0; k < target->stream_count; k++) { -+ struct core_stream *stream = target->streams[k]; -+ -+ build_scaling_params(surface, stream); -+ } -+ } -+ } -+} -+ -+bool logical_attach_surfaces_to_target( -+ struct dc_surface *surfaces[], -+ uint8_t surface_count, -+ struct dc_target *dc_target) -+{ -+ uint8_t i; -+ struct core_target *target = DC_TARGET_TO_CORE(dc_target); -+ -+ if (target->status.surface_count >= MAX_SURFACE_NUM) { -+ dal_error("Surface: this target has too many surfaces!\n"); -+ return false; -+ } -+ -+ for (i = 0; i < target->status.surface_count; i++) -+ dc_surface_release(target->status.surfaces[i]); -+ -+ for (i = 0; i < surface_count; i++) { -+ struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); -+ surface->status.dc_target = &target->public; -+ target->status.surfaces[i] = surfaces[i]; -+ dc_surface_retain(target->status.surfaces[i]); -+ } -+ target->status.surface_count = surface_count; -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c -new file mode 100644 -index 0000000..3d537d5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c -@@ -0,0 +1,118 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dc_services.h" -+#include "dc_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 sink_init_data *init_params) -+{ -+ -+ struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); -+ -+ sink->protected.public.sink_signal = init_params->sink_signal; -+ sink->protected.link = core_link; -+ sink->protected.ctx = core_link->ctx; -+ sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk; -+ sink->protected.converter_disable_audio = -+ init_params->converter_disable_audio; -+ -+ return true; -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+ -+void dc_sink_retain(const struct dc_sink *dc_sink) -+{ -+ struct sink *sink = DC_SINK_TO_SINK(dc_sink); -+ -+ ++sink->ref_count; -+} -+ -+void dc_sink_release(const struct dc_sink *dc_sink) -+{ -+ struct core_sink *core_sink = DC_SINK_TO_CORE(dc_sink); -+ struct sink *sink = DC_SINK_TO_SINK(dc_sink); -+ -+ --sink->ref_count; -+ -+ if (sink->ref_count == 0) { -+ destruct(sink); -+ dc_service_free(core_sink->ctx, sink); -+ } -+} -+ -+ -+/******************************************************************************* -+ * Protected functions - visible only inside of DC (not visible in DM) -+ ******************************************************************************/ -+ -+struct dc_sink *sink_create(const struct sink_init_data *init_params) -+{ -+ struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); -+ -+ struct sink *sink = dc_service_alloc(core_link->ctx, sizeof(*sink)); -+ -+ if (NULL == sink) -+ goto alloc_fail; -+ -+ if (false == construct(sink, init_params)) -+ goto construct_fail; -+ -+ /* TODO should we move this outside to where the assignment actually happens? */ -+ dc_sink_retain(&sink->protected.public); -+ -+ return &sink->protected.public; -+ -+construct_fail: -+ dc_service_free(core_link->ctx, sink); -+ -+alloc_fail: -+ return NULL; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c -new file mode 100644 -index 0000000..1a7bf50 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c -@@ -0,0 +1,172 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#include "dc_services.h" -+#include "dc.h" -+#include "core_types.h" -+#include "resource.h" -+ -+/******************************************************************************* -+ * Private definitions -+ ******************************************************************************/ -+ -+struct stream { -+ struct core_stream protected; -+ int ref_count; -+}; -+ -+#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public) -+ -+/******************************************************************************* -+ * Private functions -+ ******************************************************************************/ -+ -+static void build_bit_depth_reduction_params( -+ struct bit_depth_reduction_params *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; -+ fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; -+ -+ fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; -+ /* frame random is on by default */ -+ fmt_bit_depth->flags.FRAME_RANDOM = 1; -+ /* apply RGB dithering */ -+ fmt_bit_depth->flags.RGB_RANDOM = true; -+ -+ return; -+ -+} -+ -+static void setup_pixel_encoding( -+ struct clamping_and_pixel_encoding_params *clamping) -+{ -+ /*TODO: Need to un-hardcode, refer to function with same name -+ * in dal2 hw_sequencer*/ -+ -+ clamping->pixel_encoding = PIXEL_ENCODING_RGB; -+ -+ return; -+} -+ -+static bool construct(struct core_stream *stream, -+ const struct dc_sink *dc_sink_data) -+{ -+ uint32_t i = 0; -+ -+ stream->sink = DC_SINK_TO_CORE(dc_sink_data); -+ stream->ctx = stream->sink->ctx; -+ stream->public.sink = dc_sink_data; -+ -+ dc_sink_retain(dc_sink_data); -+ -+ build_bit_depth_reduction_params(&stream->fmt_bit_depth); -+ setup_pixel_encoding(&stream->clamping); -+ -+ /* Copy audio modes */ -+ /* TODO - Remove this translation */ -+ for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) -+ { -+ stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; -+ stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; -+ stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; -+ stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; -+ } -+ stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; -+ stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; -+ stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency; -+ dc_service_memmove( -+ stream->public.audio_info.display_name, -+ dc_sink_data->edid_caps.display_name, -+ AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); -+ stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; -+ stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; -+ stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; -+ -+ /* TODO - Unhardcode port_id */ -+ stream->public.audio_info.port_id[0] = 0x5558859e; -+ stream->public.audio_info.port_id[1] = 0xd989449; -+ -+ /* EDID CAP translation for HDMI 2.0 */ -+ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; -+ return true; -+} -+ -+static void destruct(struct core_stream *stream) -+{ -+ dc_sink_release(&stream->sink->public); -+} -+ -+void dc_stream_retain(struct dc_stream *dc_stream) -+{ -+ struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); -+ stream->ref_count++; -+} -+ -+void dc_stream_release(struct dc_stream *public) -+{ -+ struct stream *stream = DC_STREAM_TO_STREAM(public); -+ struct core_stream *protected = DC_STREAM_TO_CORE(public); -+ struct dc_context *ctx = protected->ctx; -+ stream->ref_count--; -+ -+ if (stream->ref_count == 0) { -+ destruct(protected); -+ dc_service_free(ctx, stream); -+ } -+} -+ -+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink) -+{ -+ struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); -+ struct stream *stream; -+ -+ if (sink == NULL) -+ goto alloc_fail; -+ -+ stream = dc_service_alloc(sink->ctx, sizeof(struct stream)); -+ -+ if (NULL == stream) -+ goto alloc_fail; -+ -+ if (false == construct(&stream->protected, dc_sink)) -+ goto construct_fail; -+ -+ dc_stream_retain(&stream->protected.public); -+ -+ return &stream->protected.public; -+ -+construct_fail: -+ dc_service_free(sink->ctx, stream); -+ -+alloc_fail: -+ return NULL; -+} -+ -+ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c -new file mode 100644 -index 0000000..41a5feb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c -@@ -0,0 +1,124 @@ -+/* -+ * 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 "dc_services.h" -+#include "dc.h" -+ -+/* DC core (private) */ -+#include "core_dc.h" -+#include "adjustment_types.h" -+ -+ -+/******************************************************************************* -+ * Private structures -+ ******************************************************************************/ -+struct surface { -+ struct core_surface protected; -+ enum dc_irq_source irq_source; -+ int ref_count; -+}; -+ -+#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) -+#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) -+ -+/******************************************************************************* -+ * Private functions -+ ******************************************************************************/ -+static bool construct(struct dc_context *ctx, struct surface *surface) -+{ -+ uint32_t i; -+ struct gamma_ramp *gamma = -+ &surface->protected.public.gamma_correction; -+ -+ /* construct gamma default value. */ -+ for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { -+ gamma->gamma_ramp_rgb256x3x16.red[i] = -+ (unsigned short) (i << 8); -+ gamma->gamma_ramp_rgb256x3x16.green[i] = -+ (unsigned short) (i << 8); -+ gamma->gamma_ramp_rgb256x3x16.blue[i] = -+ (unsigned short) (i << 8); -+ } -+ gamma->type = GAMMA_RAMP_TYPE_RGB256; -+ gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); -+ -+ surface->protected.ctx = ctx; -+ return true; -+} -+ -+static void destruct(struct surface *surface) -+{ -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+void enable_surface_flip_reporting(struct dc_surface *dc_surface, -+ uint32_t controller_id) -+{ -+ struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); -+ surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; -+ /*register_flip_interrupt(surface);*/ -+} -+ -+struct dc_surface *dc_create_surface(const struct dc *dc) -+{ -+ struct surface *surface = dc_service_alloc(dc->ctx, sizeof(*surface)); -+ -+ if (NULL == surface) -+ goto alloc_fail; -+ -+ if (false == construct(dc->ctx, surface)) -+ goto construct_fail; -+ -+ dc_surface_retain(&surface->protected.public); -+ -+ return &surface->protected.public; -+ -+construct_fail: -+ dc_service_free(dc->ctx, surface); -+ -+alloc_fail: -+ return NULL; -+} -+ -+void dc_surface_retain(const struct dc_surface *dc_surface) -+{ -+ struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); -+ -+ ++surface->ref_count; -+} -+ -+void dc_surface_release(const struct dc_surface *dc_surface) -+{ -+ struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); -+ --surface->ref_count; -+ -+ if (surface->ref_count == 0) { -+ destruct(surface); -+ dc_service_free(surface->protected.ctx, surface); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c -new file mode 100644 -index 0000000..9243c01 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c -@@ -0,0 +1,473 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_services.h" -+#include "core_types.h" -+#include "hw_sequencer.h" -+#include "resource.h" -+ -+#define COEFF_RANGE 3 -+#define REGAMMA_COEFF_A0 31308 -+#define REGAMMA_COEFF_A1 12920 -+#define REGAMMA_COEFF_A2 55 -+#define REGAMMA_COEFF_A3 55 -+#define REGAMMA_COEFF_GAMMA 2400 -+ -+struct target { -+ struct core_target protected; -+ int ref_count; -+}; -+ -+#define DC_TARGET_TO_TARGET(dc_target) \ -+ container_of(dc_target, struct target, protected.public) -+#define CORE_TARGET_TO_TARGET(core_target) \ -+ container_of(core_target, struct target, protected) -+ -+static void construct( -+ struct core_target *target, -+ struct dc_context *ctx, -+ struct dc_stream *dc_streams[], -+ uint8_t stream_count) -+{ -+ uint8_t i; -+ for (i = 0; i < stream_count; i++) { -+ target->streams[i] = DC_STREAM_TO_CORE(dc_streams[i]); -+ target->public.streams[i] = dc_streams[i]; -+ dc_stream_retain(dc_streams[i]); -+ } -+ -+ target->ctx = ctx; -+ target->stream_count = stream_count; -+} -+ -+static void destruct(struct core_target *core_target) -+{ -+ int i; -+ -+ for (i = 0; i < core_target->status.surface_count; i++) { -+ dc_surface_release(core_target->status.surfaces[i]); -+ core_target->status.surfaces[i] = 0; -+ } -+ for (i = 0; i < core_target->stream_count; i++) { -+ dc_stream_release(&core_target->streams[i]->public); -+ core_target->streams[i] = 0; -+ } -+} -+ -+void dc_target_retain(struct dc_target *dc_target) -+{ -+ struct target *target = DC_TARGET_TO_TARGET(dc_target); -+ -+ target->ref_count++; -+} -+ -+void dc_target_release(struct dc_target *dc_target) -+{ -+ struct target *target = DC_TARGET_TO_TARGET(dc_target); -+ struct core_target *protected = DC_TARGET_TO_CORE(dc_target); -+ -+ ASSERT(target->ref_count > 0); -+ target->ref_count--; -+ if (target->ref_count == 0) { -+ destruct(protected); -+ dc_service_free(protected->ctx, target); -+ } -+} -+ -+const struct dc_target_status *dc_target_get_status( -+ const struct dc_target* dc_target) -+{ -+ struct core_target* target = DC_TARGET_TO_CORE(dc_target); -+ return &target->status; -+} -+ -+struct dc_target *dc_create_target_for_streams( -+ struct dc_stream *dc_streams[], -+ uint8_t stream_count) -+{ -+ struct core_stream *stream; -+ struct target *target; -+ -+ if (0 == stream_count) -+ goto target_alloc_fail; -+ -+ stream = DC_STREAM_TO_CORE(dc_streams[0]); -+ -+ target = dc_service_alloc(stream->ctx, sizeof(struct target)); -+ -+ if (NULL == target) -+ goto target_alloc_fail; -+ -+ construct(&target->protected, stream->ctx, dc_streams, stream_count); -+ -+ dc_target_retain(&target->protected.public); -+ -+ return &target->protected.public; -+ -+ -+target_alloc_fail: -+ return NULL; -+} -+ -+static void build_gamma_params( -+ enum pixel_format pixel_format, -+ struct gamma_parameters *gamma_param) -+{ -+ uint32_t i; -+ -+ /* translate parameters */ -+ gamma_param->surface_pixel_format = pixel_format; -+ -+ gamma_param->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW; -+ gamma_param->degamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW; -+ -+ gamma_param->selected_gamma_lut = GRAPHICS_GAMMA_LUT_LEGACY; -+ -+ /* TODO support non-legacy gamma */ -+ gamma_param->disable_adjustments = false; -+ gamma_param->flag.bits.config_is_changed = 0; -+ gamma_param->flag.bits.regamma_update = 1; -+ gamma_param->flag.bits.gamma_update = 1; -+ -+ /* Set regamma */ -+ gamma_param->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 0; -+ gamma_param->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 0; -+ gamma_param->regamma.features.bits.GAMMA_RAMP_ARRAY = 0; -+ gamma_param->regamma.features.bits.APPLY_DEGAMMA = 0; -+ -+ for (i = 0; i < COEFF_RANGE; i++) { -+ gamma_param->regamma.gamma_coeff.a0[i] = REGAMMA_COEFF_A0; -+ gamma_param->regamma.gamma_coeff.a1[i] = REGAMMA_COEFF_A1; -+ gamma_param->regamma.gamma_coeff.a2[i] = REGAMMA_COEFF_A2; -+ gamma_param->regamma.gamma_coeff.a3[i] = REGAMMA_COEFF_A3; -+ gamma_param->regamma.gamma_coeff.gamma[i] = REGAMMA_COEFF_GAMMA; -+ } -+} -+ -+ -+static bool program_gamma( -+ struct dc_context *ctx, -+ struct dc_surface *surface, -+ struct input_pixel_processor *ipp, -+ struct output_pixel_processor *opp) -+{ -+ struct gamma_parameters *gamma_param; -+ bool result= false; -+ -+ gamma_param = dc_service_alloc(ctx, sizeof(struct gamma_parameters)); -+ -+ if (!gamma_param) -+ goto gamma_param_fail; -+ -+ build_gamma_params(surface->format, gamma_param); -+ -+ result = ctx->dc->hwss.set_gamma_ramp(ipp, opp, -+ &surface->gamma_correction, -+ gamma_param); -+ -+ dc_service_free(ctx, gamma_param); -+ -+gamma_param_fail: -+ return result; -+} -+ -+bool dc_commit_surfaces_to_target( -+ struct dc *dc, -+ struct dc_surface *surfaces[], -+ uint8_t surface_count, -+ struct dc_target *dc_target) -+ -+{ -+ uint8_t i, j; -+ struct core_target *target = DC_TARGET_TO_CORE(dc_target); -+ bool need_blanking = (target->status.surface_count == 0); -+ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_INTERFACE_TRACE, -+ LOG_MINOR_COMPONENT_DC, -+ "%s: commit %d surfaces to target 0x%x", -+ __func__, -+ surface_count, -+ dc_target); -+ -+ -+ if (!logical_attach_surfaces_to_target( -+ surfaces, -+ surface_count, -+ dc_target)) { -+ BREAK_TO_DEBUGGER(); -+ goto unexpected_fail; -+ } -+ -+ for (i = 0; i < surface_count; i++) -+ for (j = 0; j < target->stream_count; j++) -+ build_scaling_params(surfaces[i], target->streams[j]); -+ -+ if (dc->hwss.validate_bandwidth(dc, &dc->current_context) != DC_OK) { -+ BREAK_TO_DEBUGGER(); -+ goto unexpected_fail; -+ } -+ -+ dc->hwss.program_bw(dc, &dc->current_context); -+ -+ if (need_blanking) -+ dc_target_disable_memory_requests(dc_target); -+ -+ for (i = 0; i < surface_count; i++) { -+ struct dc_surface *surface = surfaces[i]; -+ struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface); -+ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_INTERFACE_TRACE, -+ LOG_MINOR_COMPONENT_DC, -+ "0x%x:", -+ surface); -+ dc_surface_retain(surface); -+ -+ program_gamma(dc->ctx, surface, -+ target->streams[0]->ipp, -+ target->streams[0]->opp); -+ -+ dc->hwss.set_plane_config( -+ core_surface, -+ target); -+ -+ dc->hwss.update_plane_address(core_surface, target); -+ } -+ -+ if (surface_count > 0 && need_blanking) -+ dc_target_enable_memory_requests(dc_target); -+ -+ return true; -+ -+unexpected_fail: -+ for (i = 0; i < surface_count; i++) { -+ target->status.surfaces[i] = NULL; -+ } -+ target->status.surface_count = 0; -+ -+ return false; -+} -+ -+bool dc_target_is_connected_to_sink( -+ const struct dc_target * dc_target, -+ const struct dc_sink *dc_sink) -+{ -+ struct core_target *target = DC_TARGET_TO_CORE(dc_target); -+ uint8_t i; -+ for (i = 0; i < target->stream_count; i++) { -+ if (&target->streams[i]->sink->public == dc_sink) -+ return true; -+ } -+ return false; -+} -+ -+void dc_target_enable_memory_requests(struct dc_target *target) -+{ -+ uint8_t i; -+ struct core_target *core_target = DC_TARGET_TO_CORE(target); -+ for (i = 0; i < core_target->stream_count; i++) { -+ struct timing_generator *tg = core_target->streams[i]->tg; -+ if (false == core_target->ctx->dc->hwss.enable_memory_requests(tg)) { -+ dal_error("DC: failed to unblank crtc!\n"); -+ BREAK_TO_DEBUGGER(); -+ } -+ } -+} -+ -+void dc_target_disable_memory_requests(struct dc_target *target) -+{ -+ uint8_t i; -+ struct core_target *core_target = DC_TARGET_TO_CORE(target); -+ for (i = 0; i < core_target->stream_count; i++) { -+ struct timing_generator *tg = core_target->streams[i]->tg; -+ -+ if (NULL == tg) { -+ dal_error("DC: timing generator is NULL!\n"); -+ BREAK_TO_DEBUGGER(); -+ continue; -+ } -+ -+ if (false == core_target->ctx->dc->hwss.disable_memory_requests(tg)) { -+ dal_error("DC: failed to blank crtc!\n"); -+ BREAK_TO_DEBUGGER(); -+ } -+ } -+} -+ -+/** -+ * Update the cursor attributes and set cursor surface address -+ */ -+bool dc_target_set_cursor_attributes( -+ struct dc_target *dc_target, -+ const struct dc_cursor_attributes *attributes) -+{ -+ struct core_target *core_target; -+ struct input_pixel_processor *ipp; -+ -+ if (NULL == dc_target) { -+ dal_error("DC: dc_target is NULL!\n"); -+ return false; -+ -+ } -+ -+ core_target = DC_TARGET_TO_CORE(dc_target); -+ ipp = core_target->streams[0]->ipp; -+ -+ if (NULL == ipp) { -+ dal_error("DC: input pixel processor is NULL!\n"); -+ return false; -+ } -+ -+ if (true == core_target->ctx->dc->hwss.cursor_set_attributes(ipp, attributes)) -+ return true; -+ -+ return false; -+} -+ -+bool dc_target_set_cursor_position( -+ struct dc_target *dc_target, -+ const struct dc_cursor_position *position) -+{ -+ struct core_target *core_target; -+ struct input_pixel_processor *ipp; -+ -+ if (NULL == dc_target) { -+ dal_error("DC: dc_target is NULL!\n"); -+ return false; -+ } -+ -+ if (NULL == position) { -+ dal_error("DC: cursor position is NULL!\n"); -+ return false; -+ } -+ -+ core_target = DC_TARGET_TO_CORE(dc_target); -+ ipp = core_target->streams[0]->ipp; -+ -+ if (NULL == ipp) { -+ dal_error("DC: input pixel processor is NULL!\n"); -+ return false; -+ } -+ -+ -+ if (true == core_target->ctx->dc->hwss.cursor_set_position(ipp, position)) -+ return true; -+ -+ return false; -+} -+ -+/* TODO: #flip temporary to make flip work */ -+uint8_t dc_target_get_link_index(const struct dc_target *dc_target) -+{ -+ const struct core_target *target = CONST_DC_TARGET_TO_CORE(dc_target); -+ -+ return target->streams[0]->sink->link->link_index; -+} -+ -+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) -+{ -+ struct core_target *core_target = DC_TARGET_TO_CORE(dc_target); -+ struct timing_generator *tg = core_target->streams[0]->tg; -+ -+ return core_target->ctx->dc->hwss.get_vblank_counter(tg); -+} -+ -+enum dc_irq_source dc_target_get_irq_src( -+ const struct dc_target *dc_target, const enum irq_type irq_type) -+{ -+ struct core_target *core_target = DC_TARGET_TO_CORE(dc_target); -+ -+ /* #TODO - Remove the assumption that the controller is always in the -+ * first stream of a core target */ -+ uint8_t controller_idx = core_target->streams[0]->controller_idx; -+ -+ /* Get controller id */ -+ enum controller_id crtc_id = controller_idx + 1; -+ -+ /* Calculate controller offset */ -+ unsigned int offset = crtc_id - CONTROLLER_ID_D0; -+ unsigned int base = irq_type; -+ -+ /* Calculate irq source */ -+ enum dc_irq_source src = base + offset; -+ -+ return src; -+} -+ -+void dc_target_log( -+ const struct dc_target *dc_target, -+ struct dal_logger *dal_logger, -+ enum log_major log_major, -+ enum log_minor log_minor) -+{ -+ int i; -+ -+ const struct core_target *core_target = -+ CONST_DC_TARGET_TO_CORE(dc_target); -+ -+ dal_logger_write(dal_logger, -+ log_major, -+ log_minor, -+ "core_target 0x%x: surface_count=%d, stream_count=%d", -+ core_target, -+ core_target->status.surface_count, -+ core_target->stream_count); -+ -+ for (i = 0; i < core_target->stream_count; i++) { -+ const struct core_stream *core_stream = core_target->streams[i]; -+ -+ dal_logger_write(dal_logger, -+ log_major, -+ log_minor, -+ "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;", -+ core_stream, -+ core_stream->public.src.x, -+ core_stream->public.src.y, -+ core_stream->public.src.width, -+ core_stream->public.src.height, -+ core_stream->public.dst.x, -+ core_stream->public.dst.y, -+ core_stream->public.dst.width, -+ core_stream->public.dst.height); -+ dal_logger_write(dal_logger, -+ log_major, -+ log_minor, -+ "\tpix_clk_khz: %d, h_total: %d, v_total: %d", -+ core_stream->public.timing.pix_clk_khz, -+ core_stream->public.timing.h_total, -+ core_stream->public.timing.v_total); -+ dal_logger_write(dal_logger, -+ log_major, -+ log_minor, -+ "\tsink name: %s, serial: %d", -+ core_stream->sink->public.edid_caps.display_name, -+ core_stream->sink->public.edid_caps.serial_number); -+ dal_logger_write(dal_logger, -+ log_major, -+ log_minor, -+ "\tconnector: %d", -+ core_stream->sink->link->connector_index); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h -new file mode 100644 -index 0000000..1db9395 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dc.h -@@ -0,0 +1,440 @@ -+/* -+ * 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" -+/* TODO: We should not include audio_interface.h here. Maybe just define -+ * struct audio_info here */ -+#include "audio_interface.h" -+#include "logger_types.h" -+ -+#define MAX_SINKS_PER_LINK 4 -+ -+/******************************************************************************* -+ * Display Core Interfaces -+ ******************************************************************************/ -+struct dc_init_data { -+ struct dc_context *ctx; -+ struct adapter_service *adapter_srv; -+}; -+ -+struct dc_caps { -+ uint32_t max_targets; -+ uint32_t max_links; -+ uint32_t max_audios; -+}; -+ -+void dc_get_caps(const struct dc *dc, struct dc_caps *caps); -+ -+struct dc *dc_create(const struct dal_init_data *init_params); -+void dc_destroy(struct dc **dc); -+ -+/******************************************************************************* -+ * Surface Interfaces -+ ******************************************************************************/ -+ -+struct dc_surface { -+ bool enabled; -+ 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 plane_tiling_info tiling_info; -+ struct plane_colorimetry colorimetry; -+ -+ enum surface_pixel_format format; -+ enum dc_rotation_angle rotation; -+ enum plane_stereo_format stereo_format; -+ -+ struct gamma_ramp gamma_correction; -+}; -+ -+/* -+ * This structure is filled in by dc_surface_get_status and contains -+ * the last requested address and the currently active address so the called -+ * can determine if there are any outstanding flips -+ */ -+struct dc_surface_status { -+ struct dc_plane_address requested_address; -+ struct dc_plane_address current_address; -+ const struct dc_target *dc_target; -+}; -+ -+/* -+ * Create a new surface with default parameters; -+ */ -+struct dc_surface *dc_create_surface(const struct dc *dc); -+const struct dc_surface_status* dc_surface_get_status( -+ struct dc_surface *dc_surface); -+ -+void dc_surface_retain(const struct dc_surface *dc_surface); -+void dc_surface_release(const struct dc_surface *dc_surface); -+ -+/* -+ * This structure holds a surface address. There could be multiple addresses -+ * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such -+ * as frame durations and DCC format can also be set. -+ */ -+struct dc_flip_addrs { -+ struct dc_plane_address address; -+ -+ /* TODO: DCC format info */ -+ /* TODO: add flip duration for FreeSync */ -+}; -+ -+/* -+ * Optimized flip address update function. -+ * -+ * After this call: -+ * Surface addresses and flip attributes are programmed. -+ * Surface flip occur at next configured time (h_sync or v_sync flip) -+ */ -+void dc_flip_surface_addrs(struct dc* dc, -+ const struct dc_surface *const surfaces[], -+ struct dc_flip_addrs flip_addrs[], -+ uint32_t count); -+ -+/* -+ * Set up surface attributes and associate to a target -+ * The surfaces parameter is an absolute set of all surface active for the target. -+ * If no surfaces are provided, the target will be blanked; no memory read. -+ * Any flip related attribute changes must be done through this interface. -+ * -+ * After this call: -+ * Surfaces attributes are programmed and configured to be composed into target. -+ * This does not trigger a flip. No surface address is programmed. -+ */ -+bool dc_commit_surfaces_to_target( -+ struct dc *dc, -+ struct dc_surface *dc_surfaces[], -+ uint8_t surface_count, -+ struct dc_target *dc_target); -+ -+/******************************************************************************* -+ * Target Interfaces -+ ******************************************************************************/ -+#define MAX_STREAM_NUM 1 -+ -+struct dc_target { -+ uint32_t temp; -+ const struct dc_stream *streams[MAX_STREAM_NUM]; -+}; -+ -+/* -+ * Target status is returned from dc_target_get_status in order to get the -+ * the IRQ source, current frame counter and currently attached surfaces. -+ */ -+struct dc_target_status { -+ enum dc_irq_source page_flip_src; -+ enum dc_irq_source v_update_src; -+ uint32_t cur_frame_count; -+ const struct dc_surface *surfaces[MAX_SURFACE_NUM]; -+ uint8_t surface_count; -+}; -+ -+struct dc_target *dc_create_target_for_streams( -+ struct dc_stream *dc_streams[], -+ uint8_t stream_count); -+ -+/* -+ * Get the current target status. -+ */ -+const struct dc_target_status *dc_target_get_status( -+ const struct dc_target* dc_target); -+ -+void dc_target_retain(struct dc_target *dc_target); -+void dc_target_release(struct dc_target *dc_target); -+void dc_target_log( -+ const struct dc_target *dc_target, -+ struct dal_logger *dal_logger, -+ enum log_major log_major, -+ enum log_minor log_minor); -+ -+uint8_t dc_get_current_target_count(const struct dc *dc); -+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i); -+ -+bool dc_target_is_connected_to_sink( -+ const struct dc_target *dc_target, -+ const struct dc_sink *dc_sink); -+ -+uint8_t dc_target_get_link_index(const struct dc_target *dc_target); -+uint8_t dc_target_get_controller_id(const struct dc_target *dc_target); -+ -+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target); -+enum dc_irq_source dc_target_get_irq_src( -+ const struct dc_target *dc_target, const enum irq_type irq_type); -+ -+void dc_target_enable_memory_requests(struct dc_target *target); -+void dc_target_disable_memory_requests(struct dc_target *target); -+ -+/* -+ * Structure to store surface/target associations for validation -+ */ -+struct dc_validation_set { -+ const struct dc_target *target; -+ const struct dc_surface *surfaces[4]; -+ uint8_t surface_count; -+}; -+ -+/* -+ * This function takes a set of resources and checks that they are cofunctional. -+ * -+ * After this call: -+ * No hardware is programmed for call. Only validation is done. -+ */ -+bool dc_validate_resources( -+ const struct dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count); -+ -+/* -+ * Set up streams and links associated to targets to drive sinks -+ * The targets parameter is an absolute set of all active targets. -+ * -+ * After this call: -+ * Phy, Encoder, Timing Generator are programmed and enabled. -+ * New targets are enabled with blank stream; no memory read. -+ */ -+bool dc_commit_targets( -+ struct dc *dc, -+ struct dc_target *targets[], -+ uint8_t target_count); -+ -+/******************************************************************************* -+ * Stream Interfaces -+ ******************************************************************************/ -+struct dc_stream { -+ const struct dc_sink *sink; -+ struct dc_crtc_timing timing; -+ -+ struct rect src; /* viewport in target space*/ -+ struct rect dst; /* stream addressable area */ -+ -+ struct audio_info audio_info; -+ -+ /* TODO: dithering */ -+ /* TODO: transfer function (CSC/regamma/gamut remap) */ -+ /* TODO: custom INFO packets */ -+ /* TODO: DRR/Freesync parameters */ -+ /* TODO: ABM info (DMCU) */ -+ /* TODO: PSR info */ -+ /* TODO: CEA VIC */ -+}; -+ -+/** -+ * Create a new default stream for the requested sink -+ */ -+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink); -+ -+void dc_stream_retain(struct dc_stream *dc_stream); -+void dc_stream_release(struct dc_stream *dc_stream); -+ -+/******************************************************************************* -+ * 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 *sink[MAX_SINKS_PER_LINK]; /* TODO: multiple sink support for MST */ -+ unsigned int sink_count; -+ enum dc_connection_type type; -+ enum signal_type connector_signal; -+ enum dc_irq_source irq_source_hpd; -+ enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ -+}; -+ -+/* -+ * Return an enumerated dc_link. dc_link order is constant and determined at -+ * boot time. They cannot be created or destroyed. -+ * Use dc_get_caps() to get number of links. -+ */ -+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); -+ -+/* Return id of physical connector represented by a dc_link at link_index.*/ -+const struct graphics_object_id dc_get_link_id_at_index( -+ struct dc *dc, uint32_t link_index); -+ -+/* Set backlight level of an embedded panel (eDP, LVDS). */ -+bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level); -+ -+/* Request DC to detect if there is a Panel connected. */ -+void dc_link_detect(const struct dc_link *dc_link); -+ -+/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). -+ * Return: -+ * true - Downstream port status changed. DM should call DC to do the -+ * detection. -+ * false - no change in Downstream port status. No further action required -+ * from DM. */ -+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link); -+ -+bool dc_link_add_sink( -+ struct dc_link *link, -+ struct dc_sink *sink -+ ); -+ -+void dc_link_remove_sink(struct dc_link *link, const struct dc_sink *sink); -+ -+/******************************************************************************* -+ * Sink Interfaces - A sink corresponds to a display output device -+ ******************************************************************************/ -+ -+/* -+ * The sink structure contains EDID and other display device properties -+ */ -+struct dc_sink { -+ enum signal_type sink_signal; -+ struct dc_edid dc_edid; /* raw edid */ -+ struct dc_edid_caps edid_caps; /* parse display caps */ -+}; -+ -+void dc_sink_retain(const struct dc_sink *sink); -+void dc_sink_release(const struct dc_sink *sink); -+ -+const struct audio **dc_get_audios(struct dc *dc); -+ -+struct sink_init_data { -+ enum signal_type sink_signal; -+ struct dc_link *link; -+ uint32_t dongle_max_pix_clk; -+ bool converter_disable_audio; -+}; -+ -+struct dc_sink *sink_create(const struct sink_init_data *init_params); -+ -+ -+/******************************************************************************* -+ * Cursor interfaces - To manages the cursor within a target -+ ******************************************************************************/ -+struct dc_cursor { -+ struct dc_plane_address address; -+ struct dc_cursor_attributes attributes; -+}; -+ -+/* -+ * Create a new cursor with default values for a given target. -+ */ -+struct dc_cursor *dc_create_cursor_for_target( -+ const struct dc *dc, -+ struct dc_target *dc_target); -+ -+/** -+ * Commit cursor attribute changes such as pixel format and dimensions and -+ * surface address. -+ * -+ * After this call: -+ * Cursor address and format is programmed to the new values. -+ * Cursor position is unmodified. -+ */ -+bool dc_commit_cursor( -+ const struct dc *dc, -+ struct dc_cursor *cursor); -+ -+/* -+ * Optimized cursor position update -+ * -+ * After this call: -+ * Cursor position will be programmed as well as enable/disable bit. -+ */ -+bool dc_set_cursor_position( -+ const struct dc *dc, -+ struct dc_cursor *cursor, -+ struct dc_cursor_position *pos); -+ -+ -+ -+/******************************************************************************* -+ * Interrupt interfaces -+ ******************************************************************************/ -+enum dc_irq_source dc_interrupt_to_irq_source( -+ struct dc *dc, -+ uint32_t src_id, -+ uint32_t ext_id); -+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable); -+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); -+const enum dc_irq_source dc_get_hpd_irq_source_at_index( -+ struct dc *dc, uint32_t link_index); -+const struct dc_target *dc_get_target_on_irq_source( -+ const struct dc *dc, -+ enum dc_irq_source src); -+ -+ -+/******************************************************************************* -+ * Power Interfaces -+ ******************************************************************************/ -+ -+void dc_set_power_state( -+ struct dc *dc, -+ enum dc_acpi_cm_power_state power_state, -+ enum dc_video_power_state video_power_state); -+void dc_resume(const struct dc *dc); -+ -+/******************************************************************************* -+ * DDC Interfaces -+ ******************************************************************************/ -+ -+const struct ddc_service *dc_get_ddc_at_index( -+ struct dc *dc, uint32_t link_index); -+const struct dc_ddc* dc_get_ddc_from_sink(const struct dc_sink* sink); -+const struct dc_ddc* dc_get_ddc_from_link(const struct dc_link* link); -+bool dc_ddc_query_i2c(const struct dc_ddc* ddc, -+ uint32_t address, -+ uint8_t* write_buf, -+ uint32_t write_size, -+ uint8_t* read_buf, -+ uint32_t read_size); -+bool dc_ddc_dpcd_read(const struct dc_ddc* ddc, uint32_t address, -+ uint8_t* data, uint32_t len); -+bool dc_ddc_dpcd_write(const struct dc_ddc* ddc, uint32_t address, -+ const uint8_t* data, uint32_t len); -+ -+ -+ -+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, -+ uint8_t *data, -+ uint32_t size); -+ -+ -+#endif /* DC_INTERFACE_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dc_helpers.h b/drivers/gpu/drm/amd/dal/dc/dc_helpers.h -new file mode 100644 -index 0000000..c06eb8c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dc_helpers.h -@@ -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 -+ * -+ */ -+ -+/** -+ * This file defines helper functions provided by the Display Manager to -+ * Display Core. -+ */ -+#ifndef __DC_HELPERS__ -+#define __DC_HELPERS__ -+ -+#include "dc_types.h" -+#include "dc.h" -+ -+enum dc_edid_status dc_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 dc_helpers_dp_mst_write_payload_allocation_table( -+ struct dc_context *ctx, -+ const struct dc_sink *sink, -+ struct dp_mst_stream_allocation *alloc_entity, -+ bool enable); -+ -+/* -+ * Polls for ACT (allocation change trigger) handled and -+ */ -+bool dc_helpers_dp_mst_poll_for_allocation_change_trigger( -+ struct dc_context *ctx, -+ const struct dc_sink *sink); -+/* -+ * Sends ALLOCATE_PAYLOAD message. -+ */ -+bool dc_helpers_dp_mst_send_payload_allocation( -+ struct dc_context *ctx, -+ const struct dc_sink *sink, -+ bool enable); -+ -+void dc_helpers_dp_mst_handle_mst_hpd_rx_irq( -+ void *param); -+ -+bool dc_helpers_dp_mst_start_top_mgr( -+ struct dc_context *ctx, -+ const struct dc_link *link); -+ -+void dc_helpers_dp_mst_stop_top_mgr( -+ struct dc_context *ctx, -+ const struct dc_link *link); -+ -+#endif /* __DC_HELPERS__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dc_services.h b/drivers/gpu/drm/amd/dal/dc/dc_services.h -new file mode 100644 -index 0000000..f430864 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dc_services.h -@@ -0,0 +1,174 @@ -+/* -+ * 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 __DC_SERVICES_H__ -+#define __DC_SERVICES_H__ -+ -+/* TODO: remove when DC is complete. */ -+#include "dal_services_types.h" -+#include "include/dal_types.h" -+#include "logger_interface.h" -+#include "irq_types.h" -+#include "dal_power_interface_types.h" -+ -+ -+/* if the pointer is not NULL, the allocated memory is zeroed */ -+void *dc_service_alloc(struct dc_context *ctx, uint32_t size); -+ -+void dc_service_free(struct dc_context *ctx, void *p); -+ -+void dc_service_memset(void *p, int32_t c, uint32_t count); -+ -+void dc_service_memmove(void *dst, const void *src, uint32_t size); -+ -+/* TODO: rename to dc_memcmp*/ -+int32_t dal_memcmp(const void *p1, const void *p2, uint32_t count); -+ -+/* TODO: remove when windows_dm will start registering for IRQs */ -+irq_handler_idx dc_service_register_interrupt( -+ struct dc_context *ctx, -+ struct dc_interrupt_params *int_params, -+ interrupt_handler ih, -+ void *handler_args); -+ -+/* TODO: remove when windows_dm will start registering for IRQs */ -+void dc_service_unregister_interrupt( -+ struct dc_context *ctx, -+ enum dc_irq_source irq_source, -+ irq_handler_idx handler_idx); -+ -+/************************************** -+ * Calls to Power Play (PP) component -+ **************************************/ -+ -+/* 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 dc_service_pp_pre_dce_clock_change( -+ struct dc_context *ctx, -+ struct dal_to_power_info *input, -+ struct power_to_dal_info *output); -+ -+struct dc_pp_display_configuration { -+ bool nb_pstate_switch_disable;/* controls NB PState switch */ -+ bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ -+ bool cpu_pstate_disable; -+ uint32_t cpu_pstate_separation_time; -+}; -+ -+/* 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 dc_service_pp_post_dce_clock_change( -+ struct dc_context *ctx, -+ const struct dc_pp_display_configuration *pp_display_cfg); -+ -+/* 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( -+ struct dc_context *ctx, -+ struct dal_system_clock_range *sys_clks); -+ -+/* for future use */ -+bool dc_service_pp_set_display_clock( -+ struct dc_context *ctx, -+ struct dal_to_power_dclk *dclk); -+ -+void dc_service_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds); -+ -+/* end of power component calls */ -+ -+void dc_service_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds); -+ -+/* -+ * -+ * general debug capabilities -+ * -+ */ -+#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) -+ -+#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) -+#define ASSERT_CRITICAL(expr) do { \ -+ if (WARN_ON(!(expr))) { \ -+ kgdb_breakpoint(); \ -+ } \ -+} while (0) -+#else -+#define ASSERT_CRITICAL(expr) do { \ -+ if (WARN_ON(!(expr))) { \ -+ ; \ -+ } \ -+} while (0) -+#endif -+ -+#if defined(CONFIG_DEBUG_KERNEL_DAL) -+#define ASSERT(expr) ASSERT_CRITICAL(expr) -+ -+#else -+#define ASSERT(expr) WARN_ON(!(expr)) -+#endif -+ -+#define BREAK_TO_DEBUGGER() ASSERT(0) -+ -+#else -+ -+#define ASSERT_CRITICAL(expr) do {if (expr)/* Do nothing */; } while (0) -+ -+#define ASSERT(expr) do {if (expr)/* Do nothing */; } while (0) -+ -+#define BREAK_TO_DEBUGGER() do {} while (0) -+ -+#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ -+ -+#endif /* __DC_SERVICES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dc_temp.h b/drivers/gpu/drm/amd/dal/dc/dc_temp.h -new file mode 100644 -index 0000000..b609deb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dc_temp.h -@@ -0,0 +1,508 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_TEMP_H_ -+#define DC_TEMP_H_ -+ -+#include "dc_types.h" -+ -+#define MAX_SURFACE_NUM 2 -+ -+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 pipe_gating_control { -+ PIPE_GATING_CONTROL_DISABLE = 0, -+ PIPE_GATING_CONTROL_ENABLE, -+ PIPE_GATING_CONTROL_INIT -+}; -+ -+enum surface_color_space { -+ SURFACE_COLOR_SPACE_SRGB = 0x0000, -+ SURFACE_COLOR_SPACE_BT601 = 0x0001, -+ SURFACE_COLOR_SPACE_BT709 = 0x0002, -+ SURFACE_COLOR_SPACE_XVYCC_BT601 = 0x0004, -+ SURFACE_COLOR_SPACE_XVYCC_BT709 = 0x0008, -+ SURFACE_COLOR_SPACE_XRRGB = 0x0010 -+}; -+ -+enum { -+ MAX_LANES = 2, -+ MAX_COFUNC_PATH = 6, -+ LAYER_INDEX_PRIMARY = -1, -+}; -+ -+/* Scaling format */ -+enum scaling_transformation { -+ SCALING_TRANSFORMATION_UNINITIALIZED, -+ SCALING_TRANSFORMATION_IDENTITY = 0x0001, -+ SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002, -+ SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004, -+ SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008, -+ SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010, -+ SCALING_TRANSFORMATION_INVALID = 0x80000000, -+ -+ /* Flag the first and last */ -+ SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY, -+ SCALING_TRANSFORMATION_END = -+ SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE -+}; -+ -+struct view_stereo_3d_support { -+ enum view_3d_format format; -+ struct { -+ uint32_t CLONE_MODE:1; -+ uint32_t SCALING:1; -+ uint32_t SINGLE_FRAME_SW_PACKED:1; -+ } features; -+}; -+ -+struct plane_colorimetry { -+ enum surface_color_space color_space; -+ bool limited_range; -+}; -+ -+enum tiling_mode { -+ TILING_MODE_INVALID, -+ TILING_MODE_LINEAR, -+ TILING_MODE_TILED, -+ TILING_MODE_COUNT -+}; -+ -+struct view_position { -+ uint32_t x; -+ uint32_t y; -+}; -+ -+union plane_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 -+ */ -+ uint32_t NUM_BANKS:5; -+ /* 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 -+ */ -+ uint32_t BANK_WIDTH:4; -+ /* 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 -+ */ -+ uint32_t BANK_HEIGHT:4; -+ /* Specifies the macro tile aspect ratio. Only applies -+ * to 2D and 3D tiling modes. -+ */ -+ uint32_t TILE_ASPECT:3; -+ /* 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. -+ */ -+ uint32_t TILE_SPLIT:3; -+ /* Specifies the addressing within a tile. -+ * 0x0 - DISPLAY_MICRO_TILING -+ * 0x1 - THIN_MICRO_TILING -+ * 0x2 - DEPTH_MICRO_TILING -+ * 0x3 - ROTATED_MICRO_TILING -+ */ -+ uint32_t TILE_MODE:2; -+ /* Specifies the number of pipes and how they are -+ * interleaved in the surface. -+ * Refer to memory addressing document for complete -+ * details and constraints. -+ */ -+ uint32_t PIPE_CONFIG:5; -+ /* 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. -+ */ -+ uint32_t ARRAY_MODE:4; -+ } grph; -+ -+ -+ struct { -+ /*possible values: 2,4,8,16*/ -+ uint32_t NUM_BANKS:5; -+ /*must use enum video_array_mode*/ -+ uint32_t ARRAY_MODE:4; -+ /*must use enum addr_pipe_config*/ -+ uint32_t PIPE_CONFIG:5; -+ /*possible values 1,2,4,8 */ -+ uint32_t BANK_WIDTH_LUMA:4; -+ /*possible values 1,2,4,8 */ -+ uint32_t BANK_HEIGHT_LUMA:4; -+ /*must use enum macro_tile_aspect*/ -+ uint32_t TILE_ASPECT_LUMA:3; -+ /*must use enum tile_split*/ -+ uint32_t TILE_SPLIT_LUMA:3; -+ /*must use micro_tile_mode */ -+ uint32_t TILE_MODE_LUMA:2; -+ /*possible values: 1,2,4,8*/ -+ uint32_t BANK_WIDTH_CHROMA:4; -+ /*possible values: 1,2,4,8*/ -+ uint32_t BANK_HEIGHT_CHROMA:4; -+ /*must use enum macro_tile_aspect*/ -+ uint32_t TILE_ASPECT_CHROMA:3; -+ /*must use enum tile_split*/ -+ uint32_t TILE_SPLIT_CHROMA:3; -+ /*must use enum micro_tile_mode*/ -+ uint32_t TILE_MODE_CHROMA:2; -+ -+ } video; -+ -+ uint64_t value; -+}; -+ -+union plane_size { -+ /* Grph or Video will be selected -+ * based on format above: -+ * Use Video structure if -+ * format >= DalPixelFormat_VideoBegin -+ * else use Grph structure -+ */ -+ struct { -+ struct rect surface_size; -+ /* Graphic surface pitch in pixels. -+ * In LINEAR_GENERAL mode, pitch -+ * is 32 pixel aligned. -+ */ -+ uint32_t surface_pitch; -+ } grph; -+ -+ struct { -+ struct rect luma_size; -+ /* Graphic surface pitch in pixels. -+ * In LINEAR_GENERAL mode, pitch is -+ * 32 pixel aligned. -+ */ -+ uint32_t luma_pitch; -+ -+ struct rect chroma_size; -+ /* Graphic surface pitch in pixels. -+ * In LINEAR_GENERAL mode, pitch is -+ * 32 pixel aligned. -+ */ -+ uint32_t chroma_pitch; -+ } video; -+}; -+ -+/* Windows only */ -+enum dc_scaling_transform { -+ SCL_TRANS_CENTERED = 0, -+ SCL_TRANS_ASPECT_RATIO, -+ SCL_TRANS_FULL -+}; -+ -+struct dev_c_lut { -+ uint8_t red; -+ uint8_t green; -+ uint8_t blue; -+}; -+ -+struct dev_c_lut16 { -+ uint16_t red; -+ uint16_t green; -+ uint16_t blue; -+}; -+ -+enum gamma_ramp_type { -+ GAMMA_RAMP_UNINITIALIZED = 0, -+ GAMMA_RAMP_DEFAULT, -+ GAMMA_RAMP_RBG256X3X16, -+ GAMMA_RAMP_DXGI_1, -+}; -+ -+enum surface_type { -+ OVERLAY_SURFACE = 1, GRAPHIC_SURFACE -+}; -+ -+#define CONST_RGB_GAMMA_VALUE 2400 -+ -+enum { -+ RGB_256X3X16 = 256, DX_GAMMA_RAMP_MAX = 1025 -+}; -+ -+struct gamma_ramp_rgb256x3x16 { -+ uint16_t red[RGB_256X3X16]; -+ uint16_t green[RGB_256X3X16]; -+ uint16_t blue[RGB_256X3X16]; -+}; -+ -+struct dxgi_rgb { -+ struct fixed32_32 red; -+ struct fixed32_32 green; -+ struct fixed32_32 blue; -+}; -+ -+struct gamma_ramp_dxgi_1 { -+ struct dxgi_rgb scale; -+ struct dxgi_rgb offset; -+ struct dxgi_rgb gamma_curve[DX_GAMMA_RAMP_MAX]; -+}; -+ -+struct gamma_ramp { -+ enum gamma_ramp_type type; -+ union { -+ struct gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; -+ struct gamma_ramp_dxgi_1 gamma_ramp_dxgi1; -+ }; -+ uint32_t size; -+}; -+ -+struct regamma_ramp { -+ uint16_t gamma[RGB_256X3X16 * 3]; -+}; -+ -+/* used by Graphics and Overlay gamma */ -+struct gamma_coeff { -+ int32_t gamma[3]; -+ int32_t a0[3]; /* index 0 for red, 1 for green, 2 for blue */ -+ int32_t a1[3]; -+ int32_t a2[3]; -+ int32_t a3[3]; -+}; -+ -+struct regamma_lut { -+ union { -+ struct { -+ uint32_t GRAPHICS_DEGAMMA_SRGB :1; -+ uint32_t OVERLAY_DEGAMMA_SRGB :1; -+ uint32_t GAMMA_RAMP_ARRAY :1; -+ uint32_t APPLY_DEGAMMA :1; -+ uint32_t RESERVED :28; -+ } bits; -+ uint32_t value; -+ } features; -+ -+ union { -+ struct regamma_ramp regamma_ramp; -+ struct gamma_coeff gamma_coeff; -+ }; -+}; -+ -+union gamma_flag { -+ struct { -+ uint32_t config_is_changed :1; -+ uint32_t both_pipe_req :1; -+ uint32_t regamma_update :1; -+ uint32_t gamma_update :1; -+ uint32_t reserved :28; -+ } bits; -+ uint32_t u_all; -+}; -+ -+enum graphics_regamma_adjust { -+ GRAPHICS_REGAMMA_ADJUST_BYPASS = 0, GRAPHICS_REGAMMA_ADJUST_HW, /* without adjustments */ -+ GRAPHICS_REGAMMA_ADJUST_SW /* use adjustments */ -+}; -+ -+enum graphics_gamma_lut { -+ GRAPHICS_GAMMA_LUT_LEGACY = 0, /* use only legacy LUT */ -+ GRAPHICS_GAMMA_LUT_REGAMMA, /* use only regamma LUT */ -+ GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA /* use legacy & regamma LUT's */ -+}; -+ -+enum graphics_degamma_adjust { -+ GRAPHICS_DEGAMMA_ADJUST_BYPASS = 0, GRAPHICS_DEGAMMA_ADJUST_HW, /*without adjustments */ -+ GRAPHICS_DEGAMMA_ADJUST_SW /* use adjustments */ -+}; -+ -+struct gamma_parameters { -+ union gamma_flag flag; -+ enum pixel_format surface_pixel_format; /*OS surface pixel format*/ -+ struct regamma_lut regamma; -+ -+ enum graphics_regamma_adjust regamma_adjust_type; -+ enum graphics_degamma_adjust degamma_adjust_type; -+ -+ enum graphics_gamma_lut selected_gamma_lut; -+ -+ bool disable_adjustments; -+ -+ /* here we grow with parameters if necessary */ -+}; -+ -+struct pixel_format_support { -+ bool INDEX8 :1; -+ bool RGB565 :1; -+ bool ARGB8888 :1; -+ bool ARGB2101010 :1; -+ bool ARGB2101010_XRBIAS :1; -+ bool FP16 :1; -+}; -+ -+struct render_mode { -+ struct view view; -+ enum pixel_format pixel_format; -+}; -+ -+struct refresh_rate { -+ uint32_t field_rate; -+ bool INTERLACED :1; -+ bool VIDEO_OPTIMIZED_RATE :1; -+}; -+ -+struct stereo_3d_view { -+ enum view_3d_format view_3d_format; -+ union { -+ uint32_t raw; -+ struct /*stereo_3d_view_flags*/ -+ { -+ bool SINGLE_FRAME_SW_PACKED :1; -+ bool EXCLUSIVE_3D :1; -+ } bits; -+ } flags; -+}; -+ -+enum solution_importance { -+ SOLUTION_IMPORTANCE_PREFERRED = 1, -+ /* Means we want to use this solution -+ * even in wide topology configurations*/ -+ SOLUTION_IMPORTANCE_SAFE, -+ SOLUTION_IMPORTANCE_UNSAFE, -+ SOLUTION_IMPORTANCE_DEFAULT -+/* Temporary state , means Solution object -+ * should define importance by itself -+ */ -+}; -+ -+struct solution { -+ const struct dc_mode_timing *dc_mode_timing; -+ enum solution_importance importance; -+ bool is_custom_mode; -+ uint32_t scl_support[NUM_PIXEL_FORMATS]; -+ /* bit vector of the scaling that can be supported on the timing */ -+ uint32_t scl_support_guaranteed[NUM_PIXEL_FORMATS]; -+ /* subset of m_sclSupport that can be guaranteed supported */ -+}; -+ -+enum timing_select { -+ TIMING_SELECT_DEFAULT, -+ TIMING_SELECT_NATIVE_ONLY, -+ TIMING_SELECT_PRESERVE_ASPECT -+}; -+ -+enum downscale_state { -+ DOWNSCALESTATE_DEFAULT, // Disabled, but not user selected -+ DOWNSCALESTATE_DISABLED, // User disabled through CCC -+ DOWNSCALESTATE_ENABLED // User enabled through CCC -+}; -+struct scaling_support { -+ bool IDENTITY :1; -+ bool FULL_SCREEN_SCALE :1; -+ bool PRESERVE_ASPECT_RATIO_SCALE :1; -+ bool CENTER_TIMING :1; -+}; -+ -+ -+/* TODO: combine the two cursor functions into one to make cursor -+ * programming resistant to changes in OS call sequence. */ -+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); -+ -+/****************************************************************************** -+ * TODO: these definitions only for Timing Sync feature bring-up. Remove -+ * when the feature is complete. -+ *****************************************************************************/ -+ -+#define MAX_TARGET_NUM 6 -+ -+void dc_print_sync_report( -+ const struct dc *dc); -+ -+/******************************************************************************/ -+ -+#endif /* DC_TEMP_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h -new file mode 100644 -index 0000000..b6526e9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h -@@ -0,0 +1,677 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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" -+ -+/* forward declarations */ -+struct dc; -+struct dc_surface; -+struct dc_target; -+struct dc_stream; -+struct dc_link; -+struct dc_sink; -+struct dal; -+ -+#define MAX_EDID_BUFFER_SIZE 512 -+ -+/*Displayable pixel format in fb*/ -+enum surface_pixel_format { -+ SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0, -+ /*TOBE REMOVED paletta 256 colors*/ -+ SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS = -+ SURFACE_PIXEL_FORMAT_GRPH_BEGIN, -+ /*16 bpp*/ -+ SURFACE_PIXEL_FORMAT_GRPH_ARGB1555, -+ /*16 bpp*/ -+ SURFACE_PIXEL_FORMAT_GRPH_RGB565, -+ /*32 bpp*/ -+ SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, -+ /*32 bpp swaped*/ -+ SURFACE_PIXEL_FORMAT_GRPH_BGRA8888, -+ -+ SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010, -+ /*swaped*/ -+ SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010, -+ /*TOBE REMOVED swaped, XR_BIAS has no differance -+ * for pixel layout than previous and we can -+ * delete this after discusion*/ -+ SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS, -+ /*64 bpp */ -+ SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616, -+ /*swaped & float*/ -+ SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F, -+ /*grow graphics here if necessary */ -+ -+ SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, -+ SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = -+ SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, -+ SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, -+ SURFACE_PIXEL_FORMAT_VIDEO_422_YCb, -+ SURFACE_PIXEL_FORMAT_VIDEO_422_YCr, -+ SURFACE_PIXEL_FORMAT_VIDEO_422_CbY, -+ SURFACE_PIXEL_FORMAT_VIDEO_422_CrY, -+ /*grow 422/420 video here if necessary */ -+ SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555 = -+ SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010, -+ SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102 -+ /*grow 444 video here if necessary */ -+}; -+ -+ -+/* Pixel format */ -+enum pixel_format { -+ /*graph*/ -+ PIXEL_FORMAT_UNINITIALIZED, -+ PIXEL_FORMAT_INDEX8, -+ PIXEL_FORMAT_RGB565, -+ PIXEL_FORMAT_ARGB8888, -+ PIXEL_FORMAT_ARGB2101010, -+ PIXEL_FORMAT_ARGB2101010_XRBIAS, -+ PIXEL_FORMAT_FP16, -+ /*video*/ -+ PIXEL_FORMAT_420BPP12, -+ PIXEL_FORMAT_422BPP16, -+ PIXEL_FORMAT_444BPP16, -+ PIXEL_FORMAT_444BPP32, -+ /*end of pixel format definition*/ -+ PIXEL_FORMAT_INVALID, -+ -+ PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, -+ PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, -+ PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, -+ PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP32, -+ PIXEL_FORMAT_UNKNOWN -+}; -+ -+enum plane_stereo_format { -+ PLANE_STEREO_FORMAT_NONE = 0, -+ PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1, -+ PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2, -+ PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3, -+ PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5, -+ PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6, -+ PLANE_STEREO_FORMAT_CHECKER_BOARD = 7 -+}; -+ -+/* 3D format for view, typically define how L/R eye surface is arranged within -+ * frames -+ */ -+enum view_3d_format { -+ VIEW_3D_FORMAT_NONE = 0, -+ VIEW_3D_FORMAT_FRAME_SEQUENTIAL, -+ VIEW_3D_FORMAT_SIDE_BY_SIDE, -+ VIEW_3D_FORMAT_TOP_AND_BOTTOM, -+ VIEW_3D_FORMAT_COUNT, -+ VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL -+}; -+ -+enum dc_pixel_encoding { -+ PIXEL_ENCODING_UNDEFINED, -+ PIXEL_ENCODING_RGB, -+ PIXEL_ENCODING_YCBCR422, -+ PIXEL_ENCODING_YCBCR444, -+ PIXEL_ENCODING_YCBCR420, -+ PIXEL_ENCODING_COUNT -+}; -+ -+/* TODO: Find way to calculate number of bits -+ * Please increase if pixel_format enum increases -+ * num from PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32 -+ */ -+#define NUM_PIXEL_FORMATS 10 -+ -+ -+ -+union large_integer { -+ struct { -+ uint32_t low_part; -+ int32_t high_part; -+ }; -+ -+ struct { -+ uint32_t low_part; -+ int32_t high_part; -+ } u; -+ -+ int64_t quad_part; -+}; -+ -+#define PHYSICAL_ADDRESS_LOC union large_integer -+ -+enum dc_edid_connector_type { -+ EDID_CONNECTOR_UNKNOWN = 0, -+ EDID_CONNECTOR_ANALOG = 1, -+ EDID_CONNECTOR_DIGITAL = 10, -+ EDID_CONNECTOR_DVI = 11, -+ EDID_CONNECTOR_HDMIA = 12, -+ EDID_CONNECTOR_MDDI = 14, -+ EDID_CONNECTOR_DISPLAYPORT = 15 -+}; -+ -+enum dc_edid_status { -+ EDID_OK, -+ EDID_BAD_INPUT, -+ EDID_NO_RESPONSE, -+ EDID_BAD_CHECKSUM, -+}; -+ -+/* audio capability from EDID*/ -+struct dc_cea_audio_mode { -+ uint8_t format_code; /* ucData[0] [6:3]*/ -+ uint8_t channel_count; /* ucData[0] [2:0]*/ -+ uint8_t sample_rate; /* ucData[1]*/ -+ union { -+ uint8_t sample_size; /* for LPCM*/ -+ /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/ -+ uint8_t max_bit_rate; -+ uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/ -+ }; -+}; -+ -+struct dc_edid { -+ uint32_t length; -+ uint8_t raw_edid[MAX_EDID_BUFFER_SIZE]; -+}; -+ -+/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION -+ * is used. In this case we assume speaker location are: front left, front -+ * right and front center. */ -+#define DEFAULT_SPEAKER_LOCATION 5 -+ -+#define DC_MAX_AUDIO_DESC_COUNT 16 -+ -+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 -+ -+struct dc_edid_caps { -+ /* sink identification */ -+ uint16_t manufacturer_id; -+ uint16_t product_id; -+ uint32_t serial_number; -+ uint8_t manufacture_week; -+ uint8_t manufacture_year; -+ uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; -+ -+ /* audio caps */ -+ uint8_t speaker_flags; -+ uint32_t audio_mode_count; -+ struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT]; -+ uint32_t audio_latency; -+ uint32_t video_latency; -+ -+ /*HDMI 2.0 caps*/ -+ uint8_t lte_340mcsc_scramble; -+}; -+ -+struct scaling_taps { -+ uint32_t v_taps; -+ uint32_t h_taps; -+ uint32_t v_taps_c; -+ uint32_t h_taps_c; -+}; -+ -+struct scaling_ratios { -+ struct fixed31_32 horz; -+ struct fixed31_32 vert; -+ struct fixed31_32 horz_c; -+ struct fixed31_32 vert_c; -+}; -+ -+struct rect { -+ uint32_t x; -+ uint32_t y; -+ uint32_t width; -+ uint32_t height; -+}; -+ -+struct view { -+ uint32_t width; -+ uint32_t height; -+}; -+ -+struct dc_resolution { -+ uint32_t width; -+ uint32_t height; -+}; -+ -+ -+struct dc_mode_flags { -+ /* note: part of refresh rate flag*/ -+ uint32_t INTERLACE :1; -+ /* native display timing*/ -+ uint32_t NATIVE :1; -+ /* preferred is the recommended mode, one per display */ -+ uint32_t PREFERRED :1; -+ /* true if this mode should use reduced blanking timings -+ *_not_ related to the Reduced Blanking adjustment*/ -+ uint32_t REDUCED_BLANKING :1; -+ /* note: part of refreshrate flag*/ -+ uint32_t VIDEO_OPTIMIZED_RATE :1; -+ /* should be reported to upper layers as mode_flags*/ -+ uint32_t PACKED_PIXEL_FORMAT :1; -+ /*< preferred view*/ -+ uint32_t PREFERRED_VIEW :1; -+ /* this timing should be used only in tiled mode*/ -+ uint32_t TILED_MODE :1; -+ uint32_t DSE_MODE :1; -+ /* Refresh rate divider when Miracast sink is using a -+ different rate than the output display device -+ Must be zero for wired displays and non-zero for -+ Miracast displays*/ -+ uint32_t MIRACAST_REFRESH_DIVIDER; -+}; -+ -+struct dc_crtc_timing_flags { -+ uint32_t INTERLACE :1; -+ uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1, -+ it is positive polarity --reversed with dal1 or video bios define*/ -+ uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1, -+ it is positive polarity --reversed with dal1 or video bios define*/ -+ -+ uint32_t HORZ_COUNT_BY_TWO:1; -+ -+ uint32_t EXCLUSIVE_3D :1; /* if this bit set, -+ timing can be driven in 3D format only -+ and there is no corresponding 2D timing*/ -+ uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity -+ (right eye = '1', left eye = '0') */ -+ uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right images subsampled -+ when mixed into 3D image. 0 - means summation (3D timing is doubled)*/ -+ uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View, -+ because corresponding 2D timing also present in the list*/ -+ uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing -+ and we want to match priority of corresponding 3D timing*/ -+ uint32_t Y_ONLY :1; -+ -+ uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */ -+ uint32_t DTD_COUNTER :5; /* values 1 to 16 */ -+ -+ /* HDMI 2.0 - Support scrambling for TMDS character -+ * rates less than or equal to 340Mcsc */ -+ uint32_t LTE_340MCSC_SCRAMBLE:1; -+ -+}; -+ -+enum dc_timing_standard { -+ TIMING_STANDARD_UNDEFINED, -+ TIMING_STANDARD_DMT, -+ TIMING_STANDARD_GTF, -+ TIMING_STANDARD_CVT, -+ TIMING_STANDARD_CVT_RB, -+ TIMING_STANDARD_CEA770, -+ TIMING_STANDARD_CEA861, -+ TIMING_STANDARD_HDMI, -+ TIMING_STANDARD_TV_NTSC, -+ TIMING_STANDARD_TV_NTSC_J, -+ TIMING_STANDARD_TV_PAL, -+ TIMING_STANDARD_TV_PAL_M, -+ TIMING_STANDARD_TV_PAL_CN, -+ TIMING_STANDARD_TV_SECAM, -+ TIMING_STANDARD_EXPLICIT, -+ /*!< For explicit timings from EDID, VBIOS, etc.*/ -+ TIMING_STANDARD_USER_OVERRIDE, -+ /*!< For mode timing override by user*/ -+ TIMING_STANDARD_MAX -+}; -+ -+enum dc_aspect_ratio { -+ ASPECT_RATIO_NO_DATA, -+ ASPECT_RATIO_4_3, -+ ASPECT_RATIO_16_9, -+ ASPECT_RATIO_64_27, -+ ASPECT_RATIO_256_135, -+ ASPECT_RATIO_FUTURE -+}; -+ -+enum dc_color_depth { -+ COLOR_DEPTH_UNDEFINED, -+ COLOR_DEPTH_666, -+ COLOR_DEPTH_888, -+ COLOR_DEPTH_101010, -+ COLOR_DEPTH_121212, -+ COLOR_DEPTH_141414, -+ COLOR_DEPTH_161616, -+ COLOR_DEPTH_COUNT -+}; -+ -+enum dc_timing_3d_format { -+ TIMING_3D_FORMAT_NONE, -+ TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ -+ TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ -+ TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ -+ /* for active DP-HDMI dongle*/ -+ TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ -+ TIMING_3D_FORMAT_HW_FRAME_PACKING, -+ TIMING_3D_FORMAT_SW_FRAME_PACKING, -+ TIMING_3D_FORMAT_ROW_INTERLEAVE, -+ TIMING_3D_FORMAT_COLUMN_INTERLEAVE, -+ TIMING_3D_FORMAT_PIXEL_INTERLEAVE, -+ TIMING_3D_FORMAT_SIDE_BY_SIDE, -+ TIMING_3D_FORMAT_TOP_AND_BOTTOM, -+ TIMING_3D_FORMAT_SBS_SW_PACKED, -+ /* Side-by-side, packed by application/driver into 2D frame*/ -+ TIMING_3D_FORMAT_TB_SW_PACKED, -+ /* Top-and-bottom, packed by application/driver into 2D frame*/ -+ -+ TIMING_3D_FORMAT_MAX, -+}; -+ -+enum dc_timing_source { -+ TIMING_SOURCE_UNDEFINED, -+ -+ /* explicitly specifed by user, most important*/ -+ TIMING_SOURCE_USER_FORCED, -+ TIMING_SOURCE_USER_OVERRIDE, -+ TIMING_SOURCE_CUSTOM, -+ TIMING_SOURCE_EXPLICIT, -+ -+ /* explicitly specified by the display device, more important*/ -+ TIMING_SOURCE_EDID_CEA_SVD_3D, -+ TIMING_SOURCE_EDID_CEA_SVD_PREFERRED, -+ TIMING_SOURCE_EDID_CEA_SVD_420, -+ TIMING_SOURCE_EDID_DETAILED, -+ TIMING_SOURCE_EDID_ESTABLISHED, -+ TIMING_SOURCE_EDID_STANDARD, -+ TIMING_SOURCE_EDID_CEA_SVD, -+ TIMING_SOURCE_EDID_CVT_3BYTE, -+ TIMING_SOURCE_EDID_4BYTE, -+ TIMING_SOURCE_VBIOS, -+ TIMING_SOURCE_CV, -+ TIMING_SOURCE_TV, -+ TIMING_SOURCE_HDMI_VIC, -+ -+ /* implicitly specified by display device, still safe but less important*/ -+ TIMING_SOURCE_DEFAULT, -+ -+ /* only used for custom base modes */ -+ TIMING_SOURCE_CUSTOM_BASE, -+ -+ /* these timing might not work, least important*/ -+ TIMING_SOURCE_RANGELIMIT, -+ TIMING_SOURCE_OS_FORCED, -+ TIMING_SOURCE_IMPLICIT, -+ -+ /* only used by default mode list*/ -+ TIMING_SOURCE_BASICMODE, -+ -+ TIMING_SOURCE_COUNT -+}; -+ -+enum dc_timing_support_method { -+ TIMING_SUPPORT_METHOD_UNDEFINED, -+ TIMING_SUPPORT_METHOD_EXPLICIT, -+ TIMING_SUPPORT_METHOD_IMPLICIT, -+ TIMING_SUPPORT_METHOD_NATIVE -+}; -+ -+struct dc_mode_info { -+ uint32_t pixel_width; -+ uint32_t pixel_height; -+ uint32_t field_rate; -+ /* Vertical refresh rate for progressive modes. -+ * Field rate for interlaced modes.*/ -+ -+ enum dc_timing_standard timing_standard; -+ enum dc_timing_source timing_source; -+ struct dc_mode_flags flags; -+}; -+ -+/* TODO: assess necessity*/ -+/*scanning type*/ -+enum scanning_type { -+ SCANNING_TYPE_NODATA = 0, -+ SCANNING_TYPE_OVERSCAN, -+ SCANNING_TYPE_UNDERSCAN, -+ SCANNING_TYPE_FUTURE, -+ SCANNING_TYPE_UNDEFINED -+}; -+ -+struct dc_crtc_timing { -+ uint32_t h_total; -+ uint32_t h_border_left; -+ uint32_t h_addressable; -+ uint32_t h_border_right; -+ uint32_t h_front_porch; -+ uint32_t h_sync_width; -+ -+ uint32_t v_total; -+ uint32_t v_border_top; -+ uint32_t v_addressable; -+ uint32_t v_border_bottom; -+ uint32_t v_front_porch; -+ uint32_t v_sync_width; -+ -+ uint32_t pix_clk_khz; -+ -+ uint32_t vic; -+ uint32_t hdmi_vic; -+ enum dc_timing_standard timing_standard; -+ enum dc_timing_3d_format timing_3d_format; -+ enum dc_color_depth display_color_depth; -+ enum dc_pixel_encoding pixel_encoding; -+ enum dc_aspect_ratio aspect_ratio; -+ enum scanning_type scan_type; -+ -+ struct dc_crtc_timing_flags flags; -+}; -+ -+struct dc_mode_timing { -+ struct dc_mode_info mode_info; -+ struct dc_crtc_timing crtc_timing; -+}; -+ -+/* Rotation angle */ -+enum dc_rotation_angle { -+ ROTATION_ANGLE_0 = 0, -+ ROTATION_ANGLE_90, -+ ROTATION_ANGLE_180, -+ ROTATION_ANGLE_270, -+ ROTATION_ANGLE_COUNT -+}; -+ -+struct dc_cursor_position { -+ uint32_t x; -+ uint32_t y; -+ -+ uint32_t x_origin; -+ uint32_t y_origin; -+ -+ /* -+ * This parameter indicates whether HW cursor should be enabled -+ */ -+ bool enable; -+ -+ /* -+ * This parameter indicates whether cursor hot spot should be -+ * programmed -+ */ -+ bool hot_spot_enable; -+}; -+ -+/* This enum is for programming CURSOR_MODE register field. */ -+/* What this register should be programmed to depends on */ -+/* OS requested cursor shape flags */ -+/* and what we stored in the cursor surface. */ -+enum dc_cursor_color_format { -+ CURSOR_MODE_MONO, -+ CURSOR_MODE_COLOR_1BIT_AND, -+ CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA, -+ CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA -+}; -+ -+union dc_cursor_attribute_flags { -+ struct { -+ uint32_t ENABLE_MAGNIFICATION:1; -+ uint32_t INVERSE_TRANSPARENT_CLAMPING:1; -+ uint32_t HORIZONTAL_MIRROR:1; -+ uint32_t VERTICAL_MIRROR:1; -+ uint32_t RESERVED:28; -+ } bits; -+ uint32_t value; -+}; -+ -+/* This is all the parameters required by DAL in order to */ -+/* update the cursor attributes, */ -+/* including the new cursor image surface address, size, */ -+/* hotspot location, color format, etc. */ -+struct dc_cursor_attributes { -+ PHYSICAL_ADDRESS_LOC address; -+ -+ /* Width and height should correspond to cursor surface width x heigh */ -+ uint32_t width; -+ uint32_t height; -+ uint32_t x_hot; -+ uint32_t y_hot; -+ -+ enum dc_cursor_color_format color_format; -+ -+ /* In case we support HW Cursor rotation in the future */ -+ enum dc_rotation_angle rotation_angle; -+ -+ union dc_cursor_attribute_flags attribute_flags; -+ -+}; -+ -+ -+enum dc_plane_addr_type { -+ PLN_ADDR_TYPE_GRAPHICS = 0, -+ PLN_ADDR_TYPE_GRPH_STEREO, -+ PLN_ADDR_TYPE_VIDEO_PROGRESSIVE, -+ PLN_ADDR_TYPE_VIDEO_INTERLACED, -+ PLN_ADDR_TYPE_VIDEO_PROGRESSIVE_STEREO, -+ PLN_ADDR_TYPE_VIDEO_INTERLACED_STEREO -+}; -+ -+struct dc_plane_address { -+ enum dc_plane_addr_type type; -+ union { -+ struct{ -+ PHYSICAL_ADDRESS_LOC addr; -+ } grph; -+ -+ /*stereo*/ -+ struct { -+ PHYSICAL_ADDRESS_LOC left_addr; -+ PHYSICAL_ADDRESS_LOC right_addr; -+ } grph_stereo; -+ -+ /*video progressive*/ -+ struct { -+ PHYSICAL_ADDRESS_LOC chroma_addr; -+ PHYSICAL_ADDRESS_LOC luma_addr; -+ } video_progressive; -+ -+ /*video interlaced*/ -+ struct { -+ PHYSICAL_ADDRESS_LOC chroma_addr; -+ PHYSICAL_ADDRESS_LOC luma_addr; -+ PHYSICAL_ADDRESS_LOC chroma_bottom_addr; -+ PHYSICAL_ADDRESS_LOC luma_bottom_addr; -+ } video_interlaced; -+ -+ /*video Progressive Stereo*/ -+ struct { -+ PHYSICAL_ADDRESS_LOC left_chroma_addr; -+ PHYSICAL_ADDRESS_LOC left_luma_addr; -+ PHYSICAL_ADDRESS_LOC right_chroma_addr; -+ PHYSICAL_ADDRESS_LOC right_luma_addr; -+ } video_progressive_stereo; -+ -+ /*video interlaced stereo*/ -+ struct { -+ PHYSICAL_ADDRESS_LOC left_chroma_addr; -+ PHYSICAL_ADDRESS_LOC left_luma_addr; -+ PHYSICAL_ADDRESS_LOC left_chroma_bottom_addr; -+ PHYSICAL_ADDRESS_LOC left_luma_bottom_addr; -+ -+ PHYSICAL_ADDRESS_LOC right_chroma_addr; -+ PHYSICAL_ADDRESS_LOC right_luma_addr; -+ PHYSICAL_ADDRESS_LOC right_chroma_bottom_addr; -+ PHYSICAL_ADDRESS_LOC right_luma_bottom_addr; -+ } video_interlaced_stereo; -+ }; -+}; -+ -+enum dc_power_state { -+ DC_POWER_STATE_ON = 1, -+ DC_POWER_STATE_STANDBY, -+ DC_POWER_STATE_SUSPEND, -+ DC_POWER_STATE_OFF -+}; -+ -+/* DC PowerStates */ -+enum dc_video_power_state { -+ DC_VIDEO_POWER_UNSPECIFIED = 0, -+ DC_VIDEO_POWER_ON = 1, -+ DC_VIDEO_POWER_STANDBY, -+ DC_VIDEO_POWER_SUSPEND, -+ DC_VIDEO_POWER_OFF, -+ DC_VIDEO_POWER_HIBERNATE, -+ DC_VIDEO_POWER_SHUTDOWN, -+ DC_VIDEO_POWER_ULPS, /* BACO or Ultra-Light-Power-State */ -+ DC_VIDEO_POWER_AFTER_RESET, -+ DC_VIDEO_POWER_MAXIMUM -+}; -+ -+enum dc_acpi_cm_power_state { -+ DC_ACPI_CM_POWER_STATE_D0 = 1, -+ DC_ACPI_CM_POWER_STATE_D1 = 2, -+ DC_ACPI_CM_POWER_STATE_D2 = 4, -+ DC_ACPI_CM_POWER_STATE_D3 = 8 -+}; -+ -+struct view_port_alignment { -+ uint8_t x_width_size_alignment; -+ uint8_t y_height_size_alignment; -+ uint8_t x_start_alignment; -+ uint8_t y_start_alignment; -+}; -+ -+enum dc_connection_type { -+ dc_connection_none, -+ dc_connection_single, -+ dc_connection_mst_branch, -+ dc_connection_active_dongle -+}; -+ -+struct dc_csc_adjustments { -+ struct fixed31_32 contrast; -+ struct fixed31_32 saturation; -+ struct fixed31_32 brightness; -+ struct fixed31_32 hue; -+}; -+ -+#include "dc_temp.h" -+ -+#endif /* DC_TYPES_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile -new file mode 100644 -index 0000000..5bf9b56 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile -@@ -0,0 +1,33 @@ -+# -+# Makefile for the 'controller' sub-component of DAL. -+# It provides the control and status of HW CRTC block. -+ -+DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -+dce110_ipp_gamma.o dce110_link_encoder.o dce110_opp.o \ -+dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \ -+dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \ -+dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\ -+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ -+dce110_resource.o dce110_transform_bit_depth.o -+ -+AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) -+ -+AMD_DAL_FILES += $(AMD_DAL_DCE110) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0 -+TG_DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -+dce110_ipp_gamma.o dce110_timing_generator.o dce110_link_encoder.o \ -+dce110_opp.o dce110_opp_regamma.o dce110_opp_formatter.o dce110_opp_csc.o \ -+dce110_transform.o dce110_transform_gamut.o dce110_transform_bit_depth.o \ -+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o dce110_resource.o -+ -+AMD_DAL_TG_DCE110 = $(addprefix \ -+ $(AMDDALPATH)/dc/dce110/,$(TG_DCE110)) -+ -+AMD_DAL_FILES += $(AMD_DAL_TG_DCE110) -+endif -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c -new file mode 100644 -index 0000000..7abb790 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c -@@ -0,0 +1,886 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "gmc/gmc_8_2_sh_mask.h" -+#include "gmc/gmc_8_2_d.h" -+ -+#include "include/logger_interface.h" -+#include "include/adapter_service_interface.h" -+ -+#include "dce110_compressor.h" -+ -+#define DCP_REG(reg)\ -+ (reg + cp110->offsets.dcp_offset) -+#define DMIF_REG(reg)\ -+ (reg + cp110->offsets.dmif_offset) -+ -+static const struct dce110_compressor_reg_offsets reg_offsets[] = { -+{ -+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+}, -+{ -+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif_offset = -+ (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL -+ - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), -+} -+}; -+ -+static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; -+ -+enum fbc_idle_force { -+ /* Bit 0 - Display registers updated */ -+ FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, -+ -+ /* Bit 2 - FBC_GRPH_COMP_EN register updated */ -+ FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, -+ /* Bit 3 - FBC_SRC_SEL register updated */ -+ FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, -+ /* Bit 4 - FBC_MIN_COMPRESSION register updated */ -+ FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, -+ /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ -+ FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, -+ /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ -+ FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, -+ /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ -+ FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, -+ -+ /* Bit 24 - Memory write to region 0 defined by MC registers. */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, -+ /* Bit 25 - Memory write to region 1 defined by MC registers */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, -+ /* Bit 26 - Memory write to region 2 defined by MC registers */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, -+ /* Bit 27 - Memory write to region 3 defined by MC registers. */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, -+ -+ /* Bit 28 - Memory write from any client other than MCIF */ -+ FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, -+ /* Bit 29 - CG statics screen signal is inactive */ -+ FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, -+}; -+ -+static uint32_t lpt_size_alignment(struct dce110_compressor *cp110) -+{ -+ /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ -+ return cp110->base.raw_size * cp110->base.banks_num * -+ cp110->base.dram_channels_num; -+} -+ -+static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110, -+ uint32_t lpt_control) -+{ -+ /*LPT MC Config */ -+ if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { -+ /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): -+ * 00 - 1 CHANNEL -+ * 01 - 2 CHANNELS -+ * 02 - 4 OR 6 CHANNELS -+ * (Only for discrete GPU, N/A for CZ) -+ * 03 - 8 OR 12 CHANNELS -+ * (Only for discrete GPU, N/A for CZ) */ -+ switch (cp110->base.dram_channels_num) { -+ case 2: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_PIPES); -+ break; -+ case 1: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_PIPES); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT NUM_PIPES!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping for LPT NUM_BANKS is in -+ * GRPH_CONTROL.GRPH_NUM_BANKS register field -+ * Specifies the number of memory banks for tiling -+ * purposes. Only applies to 2D and 3D tiling modes. -+ * POSSIBLE VALUES: -+ * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK -+ * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK -+ * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK -+ * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ -+ switch (cp110->base.banks_num) { -+ case 16: -+ set_reg_field_value( -+ lpt_control, -+ 3, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 8: -+ set_reg_field_value( -+ lpt_control, -+ 2, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 4: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ case 2: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_NUM_BANKS); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT NUM_BANKS!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping is in DMIF_ADDR_CALC. -+ * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for -+ * Carrizo specifies the memory interleave per pipe. -+ * It effectively specifies the location of pipe bits in -+ * the memory address. -+ * POSSIBLE VALUES: -+ * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte -+ * interleave -+ * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte -+ * interleave -+ */ -+ switch (cp110->base.channel_interleave_size) { -+ case 256: /*256B */ -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); -+ break; -+ case 512: /*512B */ -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT INTERLEAVE_SIZE!!!", -+ __func__); -+ break; -+ } -+ -+ /* The mapping for LOW_POWER_TILING_ROW_SIZE is in -+ * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field -+ * for Carrizo. Specifies the size of dram row in bytes. -+ * This should match up with NOOFCOLS field in -+ * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). -+ * This register DMIF_ADDR_CALC is not used by the -+ * hardware as it is only used for addrlib assertions. -+ * POSSIBLE VALUES: -+ * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row -+ * boundary -+ * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row -+ * boundary -+ * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row -+ * boundary */ -+ switch (cp110->base.raw_size) { -+ case 4096: /*4 KB */ -+ set_reg_field_value( -+ lpt_control, -+ 2, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ case 2048: -+ set_reg_field_value( -+ lpt_control, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ case 1024: -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROW_SIZE); -+ break; -+ default: -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid LPT ROW_SIZE!!!", -+ __func__); -+ break; -+ } -+ } else { -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: LPT MC Configuration is not provided", -+ __func__); -+ } -+ -+ return lpt_control; -+} -+ -+ -+ -+static bool is_source_bigger_than_epanel_size( -+ struct dce110_compressor *cp110, -+ uint32_t source_view_width, -+ uint32_t source_view_height) -+{ -+ if (cp110->base.embedded_panel_h_size != 0 && -+ cp110->base.embedded_panel_v_size != 0 && -+ ((source_view_width * source_view_height) > -+ (cp110->base.embedded_panel_h_size * -+ cp110->base.embedded_panel_v_size))) -+ return true; -+ -+ return false; -+} -+ -+static uint32_t align_to_chunks_number_per_line( -+ struct dce110_compressor *cp110, -+ uint32_t pixels) -+{ -+ return 256 * ((pixels + 255) / 256); -+} -+ -+static void wait_for_fbc_state_changed( -+ struct dce110_compressor *cp110, -+ bool enabled) -+{ -+ uint8_t counter = 0; -+ uint32_t addr = mmFBC_STATUS; -+ uint32_t value; -+ -+ while (counter < 10) { -+ value = dal_read_reg(cp110->base.ctx, addr); -+ if (get_reg_field_value( -+ value, -+ FBC_STATUS, -+ FBC_ENABLE_STATUS) == enabled) -+ break; -+ dc_service_delay_in_microseconds(cp110->base.ctx, 10); -+ counter++; -+ } -+ -+ if (counter == 10) { -+ dal_logger_write( -+ cp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: wait counter exceeded, changes to HW not applied", -+ __func__); -+ } -+} -+ -+void dce110_compressor_power_up_fbc(struct compressor *compressor) -+{ -+ uint32_t value; -+ uint32_t addr; -+ -+ addr = mmFBC_CNTL; -+ value = dal_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); -+ } -+ dal_write_reg(compressor->ctx, addr, value); -+ -+ addr = mmFBC_COMP_MODE; -+ value = dal_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); -+ dal_write_reg(compressor->ctx, addr, value); -+ -+ addr = mmFBC_COMP_CNTL; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); -+ dal_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); -+ dal_write_reg(compressor->ctx, addr, value); -+ compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; -+ -+ value = 0; -+ dal_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); -+ -+ value = 0xFFFFFF; -+ dal_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 = dal_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); -+ dal_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); -+ dal_write_reg(compressor->ctx, addr, value); -+ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); -+ dal_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 = dal_read_reg(compressor->ctx, mmFBC_CNTL); -+ set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); -+ dal_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 = dal_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 = dal_read_reg(compressor->ctx, mmFBC_MISC); -+ if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { -+ value = dal_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 = dal_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. */ -+ dal_write_reg( -+ compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), -+ 0); -+ dal_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. */ -+ dal_write_reg(compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), -+ compressor->compr_surface_address.addr.high_part); -+ dal_write_reg(compressor->ctx, -+ DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), -+ compressed_surf_address_low_part); -+ -+ fbc_pitch = align_to_chunks_number_per_line( -+ cp110, -+ params->source_view_width); -+ -+ if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) -+ fbc_pitch = fbc_pitch / 8; -+ else -+ dal_logger_write( -+ compressor->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Unexpected DCE11 compression ratio", -+ __func__); -+ -+ /* Clear content first. */ -+ dal_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); -+ dal_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 = -+ dal_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); -+ dal_write_reg( -+ compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), -+ value); -+ } -+ /* Disable Underlay pipe LPT Stutter */ -+ addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0, -+ DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dal_write_reg(compressor->ctx, addr, value); -+ -+ /* Disable LPT */ -+ addr = mmLOW_POWER_TILING_CONTROL; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ENABLE); -+ dal_write_reg(compressor->ctx, addr, value); -+ -+ /* Clear selection of Channel(s) containing Compressed Surface */ -+ addr = mmGMCON_LPT_TARGET; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 0xFFFFFFFF, -+ GMCON_LPT_TARGET, -+ STCTRL_LPT_TARGET); -+ dal_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 = dal_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); -+ dal_write_reg(compressor->ctx, -+ DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); -+ -+ /* Enable Underlay pipe LPT Stutter */ -+ addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, -+ STUTTER_ENABLE_NONLPTCH); -+ dal_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 = dal_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 = dal_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); -+ dal_write_reg(compressor->ctx, addr, value); -+ -+ /* Enable LPT */ -+ addr = mmLOW_POWER_TILING_CONTROL; -+ value = dal_read_reg(compressor->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ENABLE); -+ dal_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 = dal_read_reg(compressor->ctx, -+ mmLOW_POWER_TILING_CONTROL); -+ -+ /* POSSIBLE VALUES for Low Power Tiling Mode: -+ * 00 - Use channel 0 -+ * 01 - Use Channel 0 and 1 -+ * 02 - Use Channel 0,1,2,3 -+ * 03 - reserved */ -+ switch (compressor->lpt_channels_num) { -+ /* case 2: -+ * Use Channel 0 & 1 / Not used for DCE 11 */ -+ case 1: -+ /*Use Channel 0 for LPT for DCE 11 */ -+ set_reg_field_value( -+ lpt_control, -+ 0, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_MODE); -+ break; -+ default: -+ dal_logger_write( -+ compressor->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: Invalid selected DRAM channels for LPT!!!", -+ __func__); -+ break; -+ } -+ -+ lpt_control = lpt_memory_control_config(cp110, lpt_control); -+ -+ /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on -+ * FBC compressed surface pitch. -+ * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * -+ * Surface Pitch) / (Row Size * Number of Channels * -+ * Number of Banks)). */ -+ rows_per_channel = 0; -+ lpt_alignment = lpt_size_alignment(cp110); -+ source_view_width = -+ align_to_chunks_number_per_line( -+ cp110, -+ params->source_view_width); -+ source_view_height = (params->source_view_height + 1) & (~0x1); -+ -+ if (lpt_alignment != 0) { -+ rows_per_channel = source_view_width * source_view_height * 4; -+ rows_per_channel = -+ (rows_per_channel % lpt_alignment) ? -+ (rows_per_channel / lpt_alignment + 1) : -+ rows_per_channel / lpt_alignment; -+ } -+ -+ set_reg_field_value( -+ lpt_control, -+ rows_per_channel, -+ LOW_POWER_TILING_CONTROL, -+ LOW_POWER_TILING_ROWS_PER_CHAN); -+ -+ dal_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 = dal_read_reg(compressor->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ FBC_CLIENT_REGION_MASK, -+ FBC_MEMORY_REGION_MASK); -+ dal_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 = dal_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); -+ dal_write_reg(compressor->ctx, addr, value); -+} -+ -+bool dce110_compressor_construct(struct dce110_compressor *compressor, -+ struct dc_context *ctx, struct adapter_service *as) -+{ -+ struct embedded_panel_info panel_info; -+ -+ compressor->base.options.bits.FBC_SUPPORT = true; -+ if (!(dal_adapter_service_is_feature_supported( -+ FEATURE_DISABLE_LPT_SUPPORT))) -+ compressor->base.options.bits.LPT_SUPPORT = true; -+ /* For DCE 11 always use one DRAM channel for LPT */ -+ compressor->base.lpt_channels_num = 1; -+ -+ if (dal_adapter_service_is_feature_supported(FEATURE_DUMMY_FBC_BACKEND)) -+ compressor->base.options.bits.DUMMY_BACKEND = true; -+ -+ /* Check if this system has more than 1 DRAM channel; if only 1 then LPT -+ * should not be supported */ -+ if (compressor->base.memory_bus_width == 64) -+ compressor->base.options.bits.LPT_SUPPORT = false; -+ -+ if (dal_adapter_service_is_feature_supported( -+ FEATURE_DISABLE_FBC_COMP_CLK_GATE)) -+ compressor->base.options.bits.CLK_GATING_DISABLED = true; -+ -+ compressor->base.ctx = ctx; -+ compressor->base.embedded_panel_h_size = 0; -+ compressor->base.embedded_panel_v_size = 0; -+ compressor->base.memory_bus_width = -+ dal_adapter_service_get_asic_vram_bit_width(as); -+ compressor->base.allocated_size = 0; -+ compressor->base.preferred_requested_size = 0; -+ compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; -+ compressor->base.options.raw = 0; -+ compressor->base.banks_num = 0; -+ compressor->base.raw_size = 0; -+ compressor->base.channel_interleave_size = 0; -+ compressor->base.dram_channels_num = 0; -+ compressor->base.lpt_channels_num = 0; -+ compressor->base.attached_inst = 0; -+ compressor->base.is_enabled = false; -+ -+ if (dal_adapter_service_get_embedded_panel_info(as, -+ &panel_info)) { -+ compressor->base.embedded_panel_h_size = -+ panel_info.lcd_timing.horizontal_addressable; -+ compressor->base.embedded_panel_v_size = -+ panel_info.lcd_timing.vertical_addressable; -+ } -+ return true; -+} -+ -+struct compressor *dce110_compressor_create(struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct dce110_compressor *cp110 = -+ dc_service_alloc(ctx, sizeof(struct dce110_compressor)); -+ -+ if (!cp110) -+ return NULL; -+ -+ if (dce110_compressor_construct(cp110, ctx, as)) -+ return &cp110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, cp110); -+ return NULL; -+} -+ -+void dce110_compressor_destroy(struct compressor **compressor) -+{ -+ dc_service_free((*compressor)->ctx, TO_DCE110_COMPRESSOR(*compressor)); -+ *compressor = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h -new file mode 100644 -index 0000000..0beef22 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h -@@ -0,0 +1,84 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_COMPRESSOR_DCE110_H__ -+#define __DC_COMPRESSOR_DCE110_H__ -+ -+#include "../inc/compressor.h" -+ -+#define TO_DCE110_COMPRESSOR(compressor)\ -+ container_of(compressor, struct dce110_compressor, base) -+ -+struct dce110_compressor_reg_offsets { -+ uint32_t dcp_offset; -+ uint32_t dmif_offset; -+}; -+ -+struct dce110_compressor { -+ struct compressor base; -+ struct dce110_compressor_reg_offsets offsets; -+}; -+ -+struct compressor *dce110_compressor_create(struct dc_context *ctx, -+ struct adapter_service *as); -+ -+bool dce110_compressor_construct(struct dce110_compressor *cp110, -+ struct dc_context *ctx, struct adapter_service *as); -+ -+void dce110_compressor_destroy(struct compressor **cp); -+ -+/* FBC RELATED */ -+void dce110_compressor_power_up_fbc(struct compressor *cp); -+ -+void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, -+ struct compr_addr_and_pitch_params *params); -+ -+void dce110_compressor_disable_fbc(struct compressor *cp); -+ -+void dce110_compressor_set_fbc_invalidation_triggers(struct compressor *cp, -+ uint32_t fbc_trigger); -+ -+void dce110_compressor_program_compressed_surface_address_and_pitch( -+ struct compressor *cp, -+ struct compr_addr_and_pitch_params *params); -+ -+bool dce110_compressor_get_required_compressed_surface_size( -+ struct compressor *cp, -+ struct fbc_input_info *input_info, -+ struct fbc_requested_compressed_size *size); -+ -+bool dce110_compressor_is_fbc_enabled_in_hw(struct compressor *cp, -+ uint32_t *fbc_mapped_crtc_id); -+ -+/* LPT RELATED */ -+void dce110_compressor_enable_lpt(struct compressor *cp); -+ -+void dce110_compressor_disable_lpt(struct compressor *cp); -+ -+void dce110_compressor_program_lpt_control(struct compressor *cp, -+ struct compr_addr_and_pitch_params *params); -+ -+bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c -new file mode 100644 -index 0000000..74294cb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c -@@ -0,0 +1,1825 @@ -+/* -+ * 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 "dc_services.h" -+#include "dc.h" -+#include "core_types.h" -+#include "core_status.h" -+#include "resource.h" -+#include "hw_sequencer.h" -+#include "dc_helpers.h" -+ -+#include "dce110/dce110_resource.h" -+#include "dce110/dce110_timing_generator.h" -+#include "dce110/dce110_link_encoder.h" -+#include "dce110/dce110_stream_encoder.h" -+#include "stream_encoder_types.h" -+#include "link_encoder_types.h" -+#include "dce110/dce110_mem_input.h" -+#include "dce110/dce110_ipp.h" -+#include "dce110/dce110_transform.h" -+#include "dce110/dce110_opp.h" -+#include "gpu/dce110/dc_clock_gating_dce110.h" -+ -+/* include DCE11 register header files */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+struct dce110_hw_seq_reg_offsets { -+ uint32_t dcfe_offset; -+ uint32_t blnd_offset; -+ uint32_t crtc_offset; -+ uint32_t dcp_offset; -+}; -+ -+enum crtc_stereo_mixer_mode { -+ HW_STEREO_MIXER_MODE_INACTIVE, -+ HW_STEREO_MIXER_MODE_ROW_INTERLEAVE, -+ HW_STEREO_MIXER_MODE_COLUMN_INTERLEAVE, -+ HW_STEREO_MIXER_MODE_PIXEL_INTERLEAVE, -+ HW_STEREO_MIXER_MODE_BLENDER -+}; -+ -+struct crtc_mixer_params { -+ bool sub_sampling; -+ enum crtc_stereo_mixer_mode mode; -+}; -+ -+enum pipe_lock_control { -+ PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, -+ PIPE_LOCK_CONTROL_BLENDER = 1 << 1, -+ PIPE_LOCK_CONTROL_SCL = 1 << 2, -+ PIPE_LOCK_CONTROL_SURFACE = 1 << 3, -+ PIPE_LOCK_CONTROL_MODE = 1 << 4 -+}; -+ -+enum blender_mode { -+ BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ -+ BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */ -+ BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */ -+ BLENDER_MODE_STEREO -+}; -+ -+enum blender_type { -+ BLENDER_TYPE_NON_SINGLE_PIPE = 0, -+ BLENDER_TYPE_SB_SINGLE_PIPE, -+ BLENDER_TYPE_TB_SINGLE_PIPE -+}; -+ -+enum dc_memory_sleep_state { -+ DC_MEMORY_SLEEP_DISABLE = 0, -+ DC_MEMORY_LIGHT_SLEEP, -+ DC_MEMORY_DEEP_SLEEP, -+ DC_MEMORY_SHUTDOWN -+}; -+enum { -+ DCE110_PIPE_UPDATE_PENDING_DELAY = 1000, -+ DCE110_PIPE_UPDATE_PENDING_CHECKCOUNT = 5000 -+}; -+ -+static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { -+{ -+ .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .blnd_offset = (mmBLND0_BLND_CONTROL - mmBLND0_BLND_CONTROL), -+ .crtc_offset = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), -+ .dcp_offset = (mmDCP0_DVMM_PTE_CONTROL - mmDCP0_DVMM_PTE_CONTROL), -+}, -+{ -+ .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .blnd_offset = (mmBLND1_BLND_CONTROL - mmBLND0_BLND_CONTROL), -+ .crtc_offset = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), -+ .dcp_offset = (mmDCP1_DVMM_PTE_CONTROL - mmDCP0_DVMM_PTE_CONTROL), -+}, -+{ -+ .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .blnd_offset = (mmBLND2_BLND_CONTROL - mmBLND0_BLND_CONTROL), -+ .crtc_offset = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), -+ .dcp_offset = (mmDCP2_DVMM_PTE_CONTROL - mmDCP0_DVMM_PTE_CONTROL), -+} -+}; -+ -+#define HW_REG_DCFE(reg, id)\ -+ (reg + reg_offsets[id].dcfe_offset) -+ -+#define HW_REG_BLND(reg, id)\ -+ (reg + reg_offsets[id].blnd_offset) -+ -+#define HW_REG_CRTC(reg, id)\ -+ (reg + reg_offsets[id].crtc_offset) -+ -+#define HW_REG_DCP(reg, id)\ -+ (reg + reg_offsets[id].dcp_offset) -+ -+ -+static void init_pte(struct dc_context *ctx); -+ -+/******************************************************************************* -+ * Private definitions -+ ******************************************************************************/ -+ -+static void dce110_enable_display_pipe_clock_gating( -+ struct dc_context *ctx, -+ bool clock_gating) -+{ -+ /*TODO*/ -+} -+ -+static bool dce110_enable_display_power_gating( -+ struct dc_context *ctx, -+ uint8_t controller_id, -+ struct bios_parser *bp, -+ enum pipe_gating_control power_gating) -+{ -+ enum bp_result bp_result = BP_RESULT_OK; -+ enum bp_pipe_control_action cntl; -+ -+ if (power_gating == PIPE_GATING_CONTROL_INIT) -+ cntl = ASIC_PIPE_INIT; -+ else if (power_gating == PIPE_GATING_CONTROL_ENABLE) -+ cntl = ASIC_PIPE_ENABLE; -+ else -+ cntl = ASIC_PIPE_DISABLE; -+ -+ if (!(power_gating == PIPE_GATING_CONTROL_INIT && -+ (controller_id + 1) != CONTROLLER_ID_D0)) -+ bp_result = dal_bios_parser_enable_disp_power_gating( -+ bp, controller_id + 1, cntl); -+ -+ if (power_gating != PIPE_GATING_CONTROL_ENABLE) -+ init_pte(ctx); -+ -+ if (bp_result == BP_RESULT_OK) -+ return true; -+ else -+ return false; -+} -+ -+ -+static bool set_gamma_ramp( -+ struct input_pixel_processor *ipp, -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *ramp, -+ const struct gamma_parameters *params) -+{ -+ /*Power on LUT memory*/ -+ dce110_opp_power_on_regamma_lut(opp, true); -+ -+ if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8 || -+ params->selected_gamma_lut == GRAPHICS_GAMMA_LUT_LEGACY) { -+ /* do legacy DCP for 256 colors if we are requested to do so */ -+ dce110_ipp_set_legacy_input_gamma_ramp( -+ ipp, ramp, params); -+ -+ dce110_ipp_set_legacy_input_gamma_mode(ipp, true); -+ -+ /* set bypass */ -+ dce110_ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED); -+ -+ dce110_ipp_set_degamma(ipp, params, true); -+ -+ dce110_opp_set_regamma(opp, ramp, params, true); -+ } else if (params->selected_gamma_lut == -+ GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA) { -+ if (!dce110_opp_map_legacy_and_regamma_hw_to_x_user( -+ opp, ramp, params)) { -+ BREAK_TO_DEBUGGER(); -+ /* invalid parameters or bug */ -+ return false; -+ } -+ -+ /* do legacy DCP for 256 colors if we are requested to do so */ -+ dce110_ipp_set_legacy_input_gamma_ramp( -+ ipp, ramp, params); -+ -+ dce110_ipp_set_legacy_input_gamma_mode(ipp, true); -+ -+ /* set bypass */ -+ dce110_ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED); -+ } else { -+ dce110_ipp_set_legacy_input_gamma_mode(ipp, false); -+ -+ dce110_ipp_program_prescale(ipp, params->surface_pixel_format); -+ -+ /* Do degamma step : remove the given gamma value from FB. -+ * For FP16 or no degamma do by pass */ -+ dce110_ipp_set_degamma(ipp, params, false); -+ -+ dce110_opp_set_regamma(opp, ramp, params, false); -+ } -+ -+ /*re-enable low power mode for LUT memory*/ -+ dce110_opp_power_on_regamma_lut(opp, false); -+ -+ return true; -+} -+ -+static enum dc_status bios_parser_crtc_source_select( -+ struct core_stream *stream) -+{ -+ /* call VBIOS table to set CRTC source for the HW -+ * encoder block -+ * note: video bios clears all FMT setting here. */ -+ -+ struct bp_crtc_source_select crtc_source_select = {0}; -+ const struct core_sink *sink = stream->sink; -+ crtc_source_select.engine_id = stream->stream_enc->id; -+ crtc_source_select.controller_id = stream->controller_idx + 1; -+ /*TODO: Need to un-hardcode color depth, dp_audio and account for -+ * the case where signal and sink signal is different (translator -+ * encoder)*/ -+ crtc_source_select.signal = sink->public.sink_signal; -+ crtc_source_select.enable_dp_audio = false; -+ crtc_source_select.sink_signal = sink->public.sink_signal; -+ crtc_source_select.display_output_bit_depth -+ = PANEL_8BIT_COLOR; -+ -+ if (BP_RESULT_OK != dal_bios_parser_crtc_source_select( -+ dal_adapter_service_get_bios_parser(sink->link->adapter_srv), -+ &crtc_source_select)) { -+ return DC_ERROR_UNEXPECTED; -+ } -+ return DC_OK; -+} -+ -+static enum color_space surface_color_to_color_space( -+ struct plane_colorimetry *colorimetry) -+{ -+ enum color_space color_space = COLOR_SPACE_UNKNOWN; -+ -+ switch (colorimetry->color_space) { -+ case SURFACE_COLOR_SPACE_SRGB: -+ case SURFACE_COLOR_SPACE_XRRGB: -+ if (colorimetry->limited_range) -+ color_space = COLOR_SPACE_SRGB_LIMITED_RANGE; -+ else -+ color_space = COLOR_SPACE_SRGB_FULL_RANGE; -+ break; -+ case SURFACE_COLOR_SPACE_BT601: -+ case SURFACE_COLOR_SPACE_XVYCC_BT601: -+ color_space = COLOR_SPACE_YCBCR601; -+ break; -+ case SURFACE_COLOR_SPACE_BT709: -+ case SURFACE_COLOR_SPACE_XVYCC_BT709: -+ color_space = COLOR_SPACE_YCBCR709; -+ break; -+ } -+ -+ return color_space; -+} -+ -+/*******************************FMT**************************************/ -+static void program_fmt( -+ struct output_pixel_processor *opp, -+ struct bit_depth_reduction_params *fmt_bit_depth, -+ struct clamping_and_pixel_encoding_params *clamping) -+{ -+ /* dithering is affected by <CrtcSourceSelect>, hence should be -+ * programmed afterwards */ -+ -+ dce110_opp_program_bit_depth_reduction( -+ opp, -+ fmt_bit_depth); -+ -+ dce110_opp_program_clamping_and_pixel_encoding( -+ opp, -+ clamping); -+ -+ return; -+} -+ -+/***************************PIPE_CONTROL***********************************/ -+static void enable_fe_clock( -+ struct dc_context *ctx, uint8_t controller_id, bool enable) -+{ -+ uint32_t value = 0; -+ uint32_t addr; -+ -+ /*TODO: proper offset*/ -+ addr = HW_REG_DCFE(mmDCFE_CLOCK_CONTROL, controller_id); -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ enable, -+ DCFE_CLOCK_CONTROL, -+ DCFE_CLOCK_ENABLE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+/* -+static void enable_stereo_mixer( -+ struct dc_context *ctx, -+ const struct crtc_mixer_params *params) -+{ -+ TODO -+} -+*/ -+static void disable_stereo_mixer( -+ struct dc_context *ctx) -+{ -+ /*TODO*/ -+} -+ -+static void 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 = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ addr = mmDVMM_PTE_REQ; -+ value = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+} -+ -+/** -+ ***************************************************************************** -+ * Function: enable_disp_power_gating -+ * -+ * @brief -+ * enable or disable power gating -+ * -+ * @param [in] enum pipe_gating_control power_gating true - power down, -+ * false - power up -+ ***************************************************************************** -+ */ -+ -+ -+/* this is a workaround for hw bug - it is a trigger on r/w */ -+ -+static void trigger_write_crtc_h_blank_start_end( -+ struct dc_context *ctx, -+ uint8_t controller_id) -+{ -+ uint32_t value; -+ uint32_t addr; -+ -+ addr = HW_REG_CRTC(mmCRTC_H_BLANK_START_END, controller_id); -+ value = dal_read_reg(ctx, addr); -+ dal_write_reg(ctx, addr, value); -+} -+ -+static bool pipe_control_lock( -+ struct dc_context *ctx, -+ uint8_t controller_idx, -+ uint32_t control_mask, -+ bool lock) -+{ -+ uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx); -+ uint32_t value = dal_read_reg(ctx, addr); -+ bool need_to_wait = false; -+ -+ if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) -+ set_reg_field_value( -+ value, -+ lock, -+ BLND_V_UPDATE_LOCK, -+ BLND_DCP_GRPH_V_UPDATE_LOCK); -+ -+ if (control_mask & PIPE_LOCK_CONTROL_SCL) -+ set_reg_field_value( -+ value, -+ lock, -+ BLND_V_UPDATE_LOCK, -+ BLND_SCL_V_UPDATE_LOCK); -+ -+ if (control_mask & PIPE_LOCK_CONTROL_SURFACE) -+ set_reg_field_value( -+ value, -+ lock, -+ BLND_V_UPDATE_LOCK, -+ BLND_DCP_GRPH_SURF_V_UPDATE_LOCK); -+ -+ if (control_mask & PIPE_LOCK_CONTROL_BLENDER) { -+ set_reg_field_value( -+ value, -+ lock, -+ BLND_V_UPDATE_LOCK, -+ BLND_BLND_V_UPDATE_LOCK); -+ need_to_wait = true; -+ } -+ -+ if (control_mask & PIPE_LOCK_CONTROL_MODE) -+ set_reg_field_value( -+ value, -+ lock, -+ BLND_V_UPDATE_LOCK, -+ BLND_V_UPDATE_LOCK_MODE); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ if (!lock && need_to_wait) { -+ uint8_t counter = 0; -+ const uint8_t counter_limit = 100; -+ const uint16_t delay_us = 1000; -+ -+ uint8_t pipe_pending; -+ -+ addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS, -+ controller_idx); -+ -+ while (counter < counter_limit) { -+ value = dal_read_reg(ctx, addr); -+ -+ pipe_pending = 0; -+ -+ if (control_mask & PIPE_LOCK_CONTROL_BLENDER) { -+ pipe_pending |= -+ get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ BLND_BLNDC_UPDATE_PENDING); -+ pipe_pending |= get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ BLND_BLNDO_UPDATE_PENDING); -+ } -+ -+ if (control_mask & PIPE_LOCK_CONTROL_SCL) { -+ pipe_pending |= -+ get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ SCL_BLNDC_UPDATE_PENDING); -+ pipe_pending |= -+ get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ SCL_BLNDO_UPDATE_PENDING); -+ } -+ if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) { -+ pipe_pending |= -+ get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ DCP_BLNDC_GRPH_UPDATE_PENDING); -+ pipe_pending |= -+ get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ DCP_BLNDO_GRPH_UPDATE_PENDING); -+ } -+ if (control_mask & PIPE_LOCK_CONTROL_SURFACE) { -+ pipe_pending |= get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ DCP_BLNDC_GRPH_SURF_UPDATE_PENDING); -+ pipe_pending |= get_reg_field_value( -+ value, -+ BLND_REG_UPDATE_STATUS, -+ DCP_BLNDO_GRPH_SURF_UPDATE_PENDING); -+ } -+ -+ if (pipe_pending == 0) -+ break; -+ -+ counter++; -+ dc_service_delay_in_microseconds(ctx, delay_us); -+ } -+ -+ if (counter == counter_limit) { -+ dal_logger_write( -+ ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: wait for update exceeded (wait %d us)\n", -+ __func__, -+ counter * delay_us); -+ dal_logger_write( -+ ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: control %d, remain value %x\n", -+ __func__, -+ control_mask, -+ value); -+ } else { -+ /* OK. */ -+ } -+ } -+ -+ if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) -+ trigger_write_crtc_h_blank_start_end(ctx, controller_idx); -+ -+ return true; -+} -+ -+static void set_blender_mode( -+ struct dc_context *ctx, -+ uint8_t controller_id, -+ enum blender_mode mode) -+{ -+ uint32_t value; -+ uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id); -+ uint32_t blnd_mode; -+ uint32_t feedthrough = 0; -+ -+ switch (mode) { -+ case BLENDER_MODE_OTHER_PIPE: -+ feedthrough = 0; -+ blnd_mode = 1; -+ break; -+ case BLENDER_MODE_BLENDING: -+ feedthrough = 0; -+ blnd_mode = 2; -+ break; -+ case BLENDER_MODE_CURRENT_PIPE: -+ default: -+ feedthrough = 1; -+ blnd_mode = 0; -+ break; -+ } -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ feedthrough, -+ BLND_CONTROL, -+ BLND_FEEDTHROUGH_EN); -+ -+ set_reg_field_value( -+ value, -+ blnd_mode, -+ BLND_CONTROL, -+ BLND_MODE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+/**************************************************************************/ -+static void update_bios_scratch_critical_state(struct adapter_service *as, -+ bool state) -+{ -+ dal_bios_parser_set_scratch_critical_state( -+ dal_adapter_service_get_bios_parser(as), -+ state); -+} -+ -+static void update_info_frame(struct core_stream *stream) -+{ -+ dce110_stream_encoder_update_info_packets( -+ stream->stream_enc, -+ stream->signal, -+ &stream->encoder_info_frame); -+} -+ -+ -+static void enable_stream(struct core_stream *stream) -+{ -+ enum lane_count lane_count = LANE_COUNT_ONE; -+ -+ struct dc_crtc_timing *timing = &stream->public.timing; -+ struct core_link *link = stream->sink->link; -+ -+ /* 1. update AVI info frame (HDMI, DP) -+ * we always need to update info frame -+ */ -+ uint32_t active_total_with_borders; -+ uint32_t early_control = 0; -+ struct timing_generator *tg = stream->tg; -+ -+ update_info_frame(stream); -+ /* enable early control to avoid corruption on DP monitor*/ -+ active_total_with_borders = -+ timing->h_addressable -+ + timing->h_border_left -+ + timing->h_border_right; -+ -+ early_control = active_total_with_borders % lane_count; -+ -+ if (early_control == 0) -+ early_control = lane_count; -+ -+ dce110_timing_generator_set_early_control(tg, early_control); -+ -+ /* enable audio only within mode set */ -+ if (stream->audio != NULL) { -+ dal_audio_enable_output( -+ stream->audio, -+ stream->stream_enc->id, -+ stream->signal); -+ } -+ -+ /* For MST, there are multiply stream go to only one link. -+ * connect DIG back_end to front_end while enable_stream and -+ * disconnect them during disable_stream -+ * BY this, it is logic clean to separate stream and link */ -+ dce110_link_encoder_connect_dig_be_to_fe(link->link_enc, -+ stream->stream_enc->id, true); -+ -+} -+ -+static void disable_stream(struct core_stream *stream) -+{ -+ struct core_link *link = stream->sink->link; -+ -+ dce110_stream_encoder_stop_info_packets( -+ stream->stream_enc, -+ stream->stream_enc->id, -+ stream->signal); -+ -+ if (stream->audio) { -+ /* mute audio */ -+ dal_audio_mute(stream->audio, stream->stream_enc->id, -+ stream->signal); -+ -+ /* TODO: notify audio driver for if audio modes list changed -+ * add audio mode list change flag */ -+ /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, -+ * stream->stream_engine_id); -+ */ -+ } -+ -+ /* blank at encoder level */ -+ dce110_stream_encoder_blank(stream->stream_enc, stream->signal); -+ dce110_link_encoder_connect_dig_be_to_fe( -+ link->link_enc, -+ stream->stream_enc->id, -+ false); -+ -+} -+ -+static void unblank_stream(struct core_stream *stream, -+ struct link_settings *link_settings) -+{ -+ struct encoder_unblank_param params = { { 0 } }; -+ -+ /* only 3 items below are used by unblank */ -+ params.crtc_timing.pixel_clock = -+ stream->public.timing.pix_clk_khz; -+ params.link_settings.link_rate = link_settings->link_rate; -+ params.signal = stream->signal; -+ dce110_stream_encoder_unblank( -+ stream->stream_enc, ¶ms); -+} -+ -+static enum color_space get_output_color_space( -+ const struct dc_crtc_timing *dc_crtc_timing) -+{ -+ enum color_space color_space = COLOR_SPACE_SRGB_FULL_RANGE; -+ -+ switch (dc_crtc_timing->pixel_encoding) { -+ case PIXEL_ENCODING_YCBCR422: -+ case PIXEL_ENCODING_YCBCR444: -+ case PIXEL_ENCODING_YCBCR420: -+ { -+ if ((dc_crtc_timing->timing_standard == -+ TIMING_STANDARD_CEA770) || -+ (dc_crtc_timing->timing_standard == -+ TIMING_STANDARD_CEA861)) { -+ if (dc_crtc_timing->pix_clk_khz > 27030) { -+ if (dc_crtc_timing->flags.Y_ONLY) -+ color_space = -+ COLOR_SPACE_YCBCR709_YONLY; -+ else -+ color_space = COLOR_SPACE_YCBCR709; -+ } else { -+ if (dc_crtc_timing->flags.Y_ONLY) -+ color_space = -+ COLOR_SPACE_YCBCR601_YONLY; -+ else -+ color_space = COLOR_SPACE_YCBCR601; -+ } -+ } -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ return color_space; -+} -+ -+static enum dc_status allocate_mst_payload(struct core_stream *stream) -+{ -+ struct link_encoder *link_encoder = stream->sink->link->link_enc; -+ struct stream_encoder *stream_encoder = stream->stream_enc; -+ struct dp_mst_stream_allocation_table table; -+ struct fixed31_32 avg_time_slots_per_mtp; -+ -+ /* TODO: remove hardcode */ -+ table.stream_count = 1; -+ table.stream_allocations[0].engine = stream_encoder->id; -+ -+ dc_helpers_dp_mst_write_payload_allocation_table( -+ stream->ctx, -+ &stream->sink->public, -+ &table.stream_allocations[0], -+ true); -+ -+ dce110_link_encoder_update_mst_stream_allocation_table( -+ link_encoder, -+ &table, -+ false); -+ -+ dc_helpers_dp_mst_poll_for_allocation_change_trigger( -+ stream->ctx, -+ &stream->sink->public); -+ -+ dc_helpers_dp_mst_send_payload_allocation( -+ stream->ctx, -+ &stream->sink->public, -+ true); -+ -+ avg_time_slots_per_mtp = dal_fixed31_32_from_fraction( -+ table.stream_allocations[0].pbn, -+ table.stream_allocations[0].pbn_per_slot); -+ -+ dce110_link_encoder_set_mst_bandwidth( -+ link_encoder, -+ stream_encoder->id, -+ avg_time_slots_per_mtp); -+ -+ return DC_OK; -+ -+} -+ -+static enum dc_status deallocate_mst_payload(struct core_stream *stream) -+{ -+ struct link_encoder *link_encoder = stream->sink->link->link_enc; -+ struct stream_encoder *stream_encoder = stream->stream_enc; -+ struct dp_mst_stream_allocation_table table; -+ struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); -+ -+ /* TODO: remove hardcode */ -+ table.stream_count = 1; -+ table.stream_allocations[0].slot_count = 0; -+ -+ dce110_link_encoder_set_mst_bandwidth( -+ link_encoder, -+ stream_encoder->id, -+ avg_time_slots_per_mtp); -+ -+ dc_helpers_dp_mst_write_payload_allocation_table( -+ stream->ctx, -+ &stream->sink->public, -+ &table.stream_allocations[0], -+ false); -+ -+ dce110_link_encoder_update_mst_stream_allocation_table( -+ link_encoder, -+ &table, -+ false); -+ -+ dc_helpers_dp_mst_poll_for_allocation_change_trigger( -+ stream->ctx, -+ &stream->sink->public); -+ -+ dc_helpers_dp_mst_send_payload_allocation( -+ stream->ctx, -+ &stream->sink->public, -+ false); -+ -+ -+ return DC_OK; -+ -+} -+ -+static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx, -+ struct validate_context *context, -+ const struct dc *dc) -+{ -+ struct core_stream *stream = -+ context->res_ctx.controller_ctx[controller_idx].stream; -+ -+ struct output_pixel_processor *opp = -+ context->res_ctx.pool.opps[controller_idx]; -+ bool timing_changed = context->res_ctx.controller_ctx[controller_idx] -+ .flags.timing_changed; -+ enum color_space color_space; -+ -+ if (timing_changed) { -+ -+ disable_stream(stream); -+ core_link_disable(stream); -+ -+ /*TODO: AUTO check if timing changed*/ -+ if (false == dal_clock_source_program_pix_clk( -+ stream->clock_source, -+ &stream->pix_clk_params, -+ &stream->pll_settings)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ -+ -+ if (false == dce110_timing_generator_program_timing_generator( -+ stream->tg, -+ &stream->public.timing)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ } -+ -+ /*TODO: mst support - use total stream count*/ -+ dce110_allocate_dmif_buffer(stream->mi, -+ &stream->public.timing, -+ context->target_count); -+ -+ if (timing_changed) { -+ if (false == dce110_timing_generator_enable_crtc( -+ stream->tg)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ } -+ -+ if (DC_OK != bios_parser_crtc_source_select(stream)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ -+ dce110_opp_set_dyn_expansion( -+ opp, -+ COLOR_SPACE_YCBCR601, -+ stream->public.timing.display_color_depth, -+ stream->sink->public.sink_signal); -+ -+ program_fmt( -+ opp, -+ &stream->fmt_bit_depth, -+ &stream->clamping); -+ -+ dce110_link_encoder_setup( -+ stream->sink->link->link_enc, -+ stream->signal); -+ if (ENCODER_RESULT_OK != dce110_stream_encoder_setup( -+ stream->stream_enc, -+ &stream->public.timing, -+ stream->signal, -+ stream->audio != NULL)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ -+ if (stream->audio != NULL) { -+ if (AUDIO_RESULT_OK != dal_audio_setup( -+ stream->audio, -+ &stream->audio_output, -+ &stream->public.audio_info)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ } -+ -+ /* Setup audio rate clock source */ -+ if (stream->audio != NULL) -+ dal_audio_setup_audio_wall_dto( -+ stream->audio, -+ stream->signal, -+ &stream->audio_output.crtc_info, -+ &stream->audio_output.pll_info); -+ -+ /* program blank color */ -+ color_space = get_output_color_space( -+ &stream->public.timing); -+ -+ dce110_timing_generator_program_blank_color( -+ context->res_ctx.pool.timing_generators[controller_idx], -+ color_space); -+ -+ if (timing_changed) { -+ enable_stream(stream); -+ -+ if (DC_OK != core_link_enable(stream)) { -+ BREAK_TO_DEBUGGER(); -+ return DC_ERROR_UNEXPECTED; -+ } -+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) -+ allocate_mst_payload(stream); -+ -+ } -+ -+ unblank_stream(stream, &stream->sink->link->cur_link_settings); -+ -+ return DC_OK; -+} -+ -+ -+/******************************************************************************/ -+ -+static void power_down_encoders(struct validate_context *context) -+{ -+ int i; -+ struct core_target *target; -+ struct core_stream *stream; -+ -+ for (i = 0; i < context->target_count; i++) { -+ target = context->targets[i]; -+ stream = target->streams[0]; -+ core_link_disable(stream); -+ } -+} -+ -+static void power_down_controllers(struct validate_context *context) -+{ -+ int i; -+ struct core_target *target; -+ struct core_stream *stream; -+ -+ for (i = 0; i < context->target_count; i++) { -+ target = context->targets[i]; -+ stream = target->streams[0]; -+ -+ dce110_timing_generator_disable_crtc(stream->tg); -+ } -+} -+ -+static void power_down_clock_sources(struct validate_context *context) -+{ -+ int i; -+ struct core_target *target; -+ struct core_stream *stream; -+ -+ for (i = 0; i < context->target_count; i++) { -+ target = context->targets[i]; -+ stream = target->streams[0]; -+ -+ if (false == dal_clock_source_power_down_pll( -+ stream->clock_source, -+ stream->controller_idx + 1)) { -+ dal_error( -+ "Failed to power down pll! (clk src index=%d)\n", -+ i); -+ } -+ } -+} -+ -+static void power_down_all_hw_blocks(struct validate_context *context) -+{ -+ power_down_encoders(context); -+ -+ power_down_controllers(context); -+ -+ power_down_clock_sources(context); -+} -+ -+static void disable_vga_and_power_gate_all_controllers( -+ struct validate_context *context) -+{ -+ int i; -+ struct core_target *target; -+ struct core_stream *stream; -+ struct timing_generator *tg; -+ struct bios_parser *bp; -+ struct dc_context *ctx; -+ uint8_t controller_id; -+ -+ bp = dal_adapter_service_get_bios_parser( -+ context->res_ctx.pool.adapter_srv); -+ -+ for (i = 0; i < context->target_count; i++) { -+ target = context->targets[i]; -+ stream = target->streams[0]; -+ tg = stream->tg; -+ ctx = stream->ctx; -+ controller_id = stream->controller_idx; -+ -+ dce110_timing_generator_disable_vga(tg); -+ -+ /* Enable CLOCK gating for each pipe BEFORE controller -+ * powergating. */ -+ dce110_enable_display_pipe_clock_gating(ctx, -+ true); -+ dce110_enable_display_power_gating(ctx, controller_id, bp, -+ PIPE_GATING_CONTROL_ENABLE); -+ } -+} -+ -+/** -+ * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: -+ * 1. Power down all DC HW blocks -+ * 2. Disable VGA engine on all controllers -+ * 3. Enable power gating for controller -+ * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) -+ */ -+static void enable_accelerated_mode(struct validate_context *context) -+{ -+ struct bios_parser *bp; -+ -+ bp = dal_adapter_service_get_bios_parser( -+ context->res_ctx.pool.adapter_srv); -+ -+ power_down_all_hw_blocks(context); -+ -+ disable_vga_and_power_gate_all_controllers(context); -+ -+ dal_bios_parser_set_scratch_acc_mode_change(bp); -+} -+ -+#if 0 -+static enum clocks_state get_required_clocks_state( -+ struct display_clock *display_clock, -+ struct state_dependent_clocks *req_state_dep_clks) -+{ -+ enum clocks_state clocks_required_state; -+ enum clocks_state dp_link_required_state; -+ enum clocks_state overall_required_state; -+ -+ clocks_required_state = dal_display_clock_get_required_clocks_state( -+ display_clock, req_state_dep_clks); -+ -+ dp_link_required_state = CLOCKS_STATE_ULTRA_LOW; -+ -+ /* overall required state is the max of required state for clocks -+ * (pixel, display clock) and the required state for DP link. */ -+ overall_required_state = -+ clocks_required_state > dp_link_required_state ? -+ clocks_required_state : dp_link_required_state; -+ -+ /* return the min required state */ -+ return overall_required_state; -+} -+ -+static bool dc_pre_clock_change( -+ struct dc_context *ctx, -+ struct minimum_clocks_calculation_result *min_clk_in, -+ enum clocks_state required_clocks_state, -+ struct power_to_dal_info *output) -+{ -+ struct dal_to_power_info input = {0}; -+ -+ input.min_deep_sleep_sclk = min_clk_in->min_deep_sleep_sclk; -+ input.min_mclk = min_clk_in->min_mclk_khz; -+ input.min_sclk = min_clk_in->min_sclk_khz; -+ -+ switch (required_clocks_state) { -+ case CLOCKS_STATE_ULTRA_LOW: -+ input.required_clock = PP_CLOCKS_STATE_ULTRA_LOW; -+ break; -+ case CLOCKS_STATE_LOW: -+ input.required_clock = PP_CLOCKS_STATE_LOW; -+ break; -+ case CLOCKS_STATE_NOMINAL: -+ input.required_clock = PP_CLOCKS_STATE_NOMINAL; -+ break; -+ case CLOCKS_STATE_PERFORMANCE: -+ input.required_clock = PP_CLOCKS_STATE_PERFORMANCE; -+ break; -+ default: -+ input.required_clock = PP_CLOCKS_STATE_NOMINAL; -+ break; -+ } -+ -+ if (!dc_service_pp_pre_dce_clock_change(ctx, &input, output)) { -+ dal_error("DC: dc_service_pp_pre_dce_clock_change failed!\n"); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool dc_set_clocks_and_clock_state ( -+ struct validate_context *context) -+{ -+ struct power_to_dal_info output = {0}; -+ -+ struct display_clock *disp_clk = context->res_ctx.pool.display_clock; -+ struct dc_context *ctx = context->targets[0]->ctx; -+ -+ -+ if (!dc_pre_clock_change( -+ ctx, -+ &context->res_ctx.min_clocks, -+ get_required_clocks_state( -+ context->res_ctx.pool.display_clock, -+ &context->res_ctx.state_clocks), -+ &output)) { -+ /* "output" was not updated by PPLib. -+ * DAL will use default values for set mode. -+ * -+ * Do NOT fail this call. */ -+ return true; -+ } -+ -+ /* PPLib accepted the "clock state" that we need, that means we -+ * can store it as minimum state because PPLib guarantees not go below -+ * that state. -+ * -+ * Update the clock state here (prior to setting Pixel clock, -+ * DVO clock, or Display clock) */ -+ if (!dal_display_clock_set_min_clocks_state( -+ disp_clk, context->res_ctx.required_clocks_state)) { -+ BREAK_TO_DEBUGGER(); -+ dal_error("DC: failed to set minimum clock state!\n"); -+ } -+ -+ -+ /*bm_clk_info.max_mclk_khz = output.max_mclk; -+ bm_clk_info.min_mclk_khz = output.min_mclk; -+ bm_clk_info.max_sclk_khz = output.max_sclk; -+ bm_clk_info.min_sclk_khz = output.min_sclk;*/ -+ -+ /* Now let Bandwidth Manager know about values we got from PPLib. */ -+ /*dal_bandwidth_manager_set_dynamic_clock_info(bw_mgr, &bm_clk_info);*/ -+ -+ return true; -+} -+#endif -+ -+/** -+ * Call display_engine_clock_dce80 to perform the Dclk programming. -+ */ -+static void set_display_clock(struct validate_context *context) -+{ -+ /* Program the display engine clock. -+ * Check DFS bypass mode support or not. DFSbypass feature is only when -+ * BIOS GPU info table reports support. */ -+ -+ if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { -+ /*TODO: set_display_clock_dfs_bypass( -+ hws, -+ path_set, -+ context->res_ctx.pool.display_clock, -+ context->res_ctx.min_clocks.min_dclk_khz);*/ -+ } else -+ dal_display_clock_set_clock(context->res_ctx.pool.display_clock, -+ context->bw_results.dispclk); -+ -+ /* TODO: When changing display engine clock, DMCU WaitLoop must be -+ * reconfigured in order to maintain the same delays within DMCU -+ * programming sequences. */ -+ -+ /* TODO: Start GTC counter */ -+} -+ -+static void set_displaymarks( -+ const struct dc *dc, struct validate_context *context) -+{ -+ uint8_t i, j; -+ uint8_t total_streams = 0; -+ uint8_t target_count = context->target_count; -+ -+ for (i = 0; i < target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ -+ dce110_program_nbp_watermark( -+ stream->mi, -+ context->bw_results -+ .nbp_state_change_watermark[total_streams]); -+ -+ dce110_program_stutter_watermark( -+ stream->mi, -+ context->bw_results -+ .stutter_exit_watermark[total_streams]); -+ -+ dce110_program_urgency_watermark( -+ stream->mi, -+ context->bw_results -+ .urgent_watermark[total_streams], -+ stream->public.timing.h_total, -+ stream->public.timing.pix_clk_khz, -+ 1000 * dc->bw_vbios.blackout_duration -+ .value >> 24); -+ total_streams++; -+ } -+ } -+} -+ -+static void set_safe_displaymarks(struct validate_context *context) -+{ -+ uint8_t i, j; -+ uint8_t target_count = context->target_count; -+ -+ for (i = 0; i < target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ -+ dce110_program_safe_display_marks(stream->mi); -+ } -+ } -+} -+ -+static void dce110_program_bw(struct dc *dc, struct validate_context *context) -+{ -+ set_safe_displaymarks(&dc->current_context); -+ /*TODO: when pplib works*/ -+ /*dc_set_clocks_and_clock_state(context);*/ -+ -+ set_display_clock(&dc->current_context); -+ set_displaymarks(dc, &dc->current_context); -+} -+ -+/*TODO: break out clock sources like timing gen/ encoder*/ -+static void dce110_switch_dp_clk_src( -+ const struct dc_context *ctx, -+ const struct core_stream *stream) -+{ -+ uint32_t pixel_rate_cntl_value; -+ uint32_t addr; -+ enum clock_source_id id = dal_clock_source_get_id(stream->clock_source); -+ -+ /*TODO: proper offset*/ -+ addr = mmCRTC0_PIXEL_RATE_CNTL + stream->controller_idx * -+ (mmCRTC1_PIXEL_RATE_CNTL - mmCRTC0_PIXEL_RATE_CNTL); -+ -+ pixel_rate_cntl_value = dal_read_reg(ctx, addr); -+ -+ if (id == CLOCK_SOURCE_ID_EXTERNAL) { -+ -+ if (!get_reg_field_value(pixel_rate_cntl_value, -+ CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE)) { -+ -+ set_reg_field_value(pixel_rate_cntl_value, 1, -+ CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE); -+ } -+ -+ } else { -+ set_reg_field_value(pixel_rate_cntl_value, -+ 0, -+ CRTC0_PIXEL_RATE_CNTL, -+ DP_DTO0_ENABLE); -+ -+ set_reg_field_value(pixel_rate_cntl_value, -+ id - 1, -+ CRTC0_PIXEL_RATE_CNTL, -+ CRTC0_PIXEL_RATE_SOURCE); -+ } -+ dal_write_reg(ctx, addr, pixel_rate_cntl_value); -+} -+ -+static void switch_dp_clock_sources( -+ const struct dc_context *ctx, -+ struct validate_context *val_context) -+{ -+ uint8_t i, j; -+ for (i = 0; i < val_context->target_count; i++) { -+ struct core_target *target = val_context->targets[i]; -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ -+ if (dc_is_dp_signal(stream->signal)) { -+ struct clock_source *clk_src = -+ find_used_clk_src_for_sharing( -+ val_context, stream); -+ -+ if (clk_src != stream->clock_source) { -+ unreference_clock_source( -+ &val_context->res_ctx, -+ stream->clock_source); -+ stream->clock_source = clk_src; -+ reference_clock_source( -+ &val_context->res_ctx, clk_src); -+ dce110_switch_dp_clk_src(ctx, stream); -+ } -+ } -+ } -+ } -+} -+ -+/******************************************************************************* -+ * Public functions -+ ******************************************************************************/ -+ -+/*TODO: const validate_context*/ -+static enum dc_status apply_ctx_to_hw( -+ const struct dc *dc, -+ struct validate_context *context) -+{ -+ enum dc_status status; -+ uint8_t i; -+ struct resource_pool *pool = &context->res_ctx.pool; -+ -+ update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv, -+ true); -+ set_safe_displaymarks(context); -+ /*TODO: when pplib works*/ -+ /*dc_set_clocks_and_clock_state(context);*/ -+ -+ set_display_clock(context); -+ -+ for (i = 0; i < pool->controller_count; i++) { -+ struct controller_ctx *ctlr_ctx -+ = &context->res_ctx.controller_ctx[i]; -+ if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream) -+ continue; -+ -+ status = apply_single_controller_ctx_to_hw( -+ i, -+ context, -+ dc); -+ -+ if (DC_OK != status) -+ return status; -+ } -+ set_displaymarks(dc, context); -+ -+ update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv, -+ false); -+ -+ switch_dp_clock_sources(dc->ctx, context); -+ -+ return DC_OK; -+} -+ -+ -+/******************************************************************************* -+ * Front End programming -+ ******************************************************************************/ -+ -+static bool setup_line_buffer_pixel_depth( -+ const struct core_stream *stream, -+ enum lb_pixel_depth depth, -+ bool blank) -+{ -+ enum lb_pixel_depth current_depth; -+ -+ struct timing_generator *tg = stream->tg; -+ struct transform *xfm = stream->xfm; -+ -+ if (!dce110_transform_get_current_pixel_storage_depth( -+ xfm, -+ ¤t_depth)) -+ return false; -+ -+ if (current_depth != depth) { -+ if (blank) -+ dce110_timing_generator_wait_for_vblank(tg); -+ -+ return dce110_transform_set_pixel_storage_depth(xfm, depth); -+ } -+ -+ return false; -+} -+ -+static void hw_sequencer_build_scaler_parameter_plane( -+ const struct core_stream *stream, -+ struct scaler_data *scaler_data) -+{ -+ /*TODO: per pipe not per stream*/ -+ /*TODO: get from feature from adapterservice*/ -+ scaler_data->flags.bits.SHOW_COLOURED_BORDER = false; -+ -+ scaler_data->flags.bits.SHOULD_PROGRAM_ALPHA = 1; -+ -+ scaler_data->flags.bits.SHOULD_PROGRAM_VIEWPORT = 0; -+ -+ scaler_data->flags.bits.SHOULD_UNLOCK = 0; -+ -+ scaler_data->flags.bits.INTERLACED = 0; -+ -+ scaler_data->dal_pixel_format = stream->format; -+ -+ scaler_data->taps = stream->taps; -+ -+ scaler_data->viewport = stream->viewport; -+ -+ scaler_data->overscan = stream->overscan; -+ -+ scaler_data->ratios = &stream->ratios; -+ -+ /*TODO rotation and adjustment */ -+ scaler_data->h_sharpness = 0; -+ scaler_data->v_sharpness = 0; -+ -+} -+ -+static void set_default_colors( -+ struct input_pixel_processor *ipp, -+ struct output_pixel_processor *opp, -+ enum pixel_format format, -+ enum color_space input_color_space, -+ enum color_space output_color_space, -+ enum dc_color_depth color_depth) -+{ -+ struct default_adjustment default_adjust = { 0 }; -+ -+ default_adjust.force_hw_default = false; -+ default_adjust.color_space = output_color_space; -+ default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; -+ default_adjust.surface_pixel_format = format; -+ -+ /* display color depth */ -+ default_adjust.color_depth = color_depth; -+ -+ /* Lb color depth */ -+ default_adjust.lb_color_depth = LB_PIXEL_DEPTH_24BPP; -+ /*dal_hw_sequencer_translate_to_lb_color_depth( -+ build_params-> -+ line_buffer_params[path_id][plane_id].depth);*/ -+ -+ dce110_opp_set_csc_default(opp, &default_adjust); -+} -+ -+static void program_scaler( -+ uint8_t controller_idx, -+ struct timing_generator *tg, -+ struct transform *xfm, -+ const struct core_surface *surface, -+ const struct core_stream *stream) -+{ -+ struct scaler_data scaler_data = { { 0 } }; -+ -+ hw_sequencer_build_scaler_parameter_plane( -+ stream, -+ &scaler_data); -+ -+ setup_line_buffer_pixel_depth( -+ stream, -+ LB_PIXEL_DEPTH_24BPP, -+ false); -+ -+ dce110_timing_generator_set_overscan_color_black( -+ tg, -+ surface->public.colorimetry.color_space); -+ -+ dce110_transform_set_scaler(xfm, &scaler_data); -+ -+ dce110_transform_update_viewport( -+ xfm, -+ &scaler_data.viewport, -+ false); -+} -+ -+ -+ -+static void configure_locking(struct dc_context *ctx, uint8_t controller_id) -+{ -+ /* main controller should be in mode 0 (master pipe) */ -+ pipe_control_lock( -+ ctx, -+ controller_id, -+ PIPE_LOCK_CONTROL_MODE, -+ false); -+ -+ /* TODO: for MPO finish the non-root controllers */ -+} -+ -+/** -+ * Program the Front End of the Pipe. -+ * The Back End was already programmed by Set Mode. -+ */ -+static bool set_plane_config( -+ struct core_surface *surface, -+ struct core_target *target) -+{ -+ const struct dc_crtc_timing *dc_crtc_timing = -+ &target->streams[0]->public.timing; -+ struct mem_input *mi = target->streams[0]->mi; -+ struct input_pixel_processor *ipp = target->streams[0]->ipp; -+ struct timing_generator *tg = target->streams[0]->tg; -+ struct transform *xfm = target->streams[0]->xfm; -+ struct output_pixel_processor *opp = target->streams[0]->opp; -+ struct dc_context *ctx = target->streams[0]->ctx; -+ uint8_t controller_idx = target->streams[0]->controller_idx; -+ -+ /* TODO: Clean up change, possibly change to use same type */ -+ enum color_space input_color_space = -+ surface_color_to_color_space(&(surface->public.colorimetry)); -+ -+ configure_locking(ctx, controller_idx); -+ -+ /* While a non-root controller is programmed we -+ * have to lock the root controller. */ -+ pipe_control_lock( -+ ctx, -+ controller_idx, -+ PIPE_LOCK_CONTROL_GRAPHICS | -+ PIPE_LOCK_CONTROL_SCL | -+ PIPE_LOCK_CONTROL_BLENDER | -+ PIPE_LOCK_CONTROL_SURFACE, -+ true); -+ -+ dce110_program_pix_dur(mi, dc_crtc_timing->pix_clk_khz); -+ -+ dce110_timing_generator_program_blanking(tg, dc_crtc_timing); -+ -+ enable_fe_clock(ctx, controller_idx, true); -+ -+ set_default_colors( -+ ipp, -+ opp, -+ target->streams[0]->format, -+ input_color_space, -+ get_output_color_space(dc_crtc_timing), -+ dc_crtc_timing->display_color_depth); -+ -+ /* program Scaler */ -+ program_scaler( -+ controller_idx, tg, xfm, surface, target->streams[0]); -+ -+ set_blender_mode( -+ ctx, -+ controller_idx, -+ BLENDER_MODE_CURRENT_PIPE); -+ -+#if 0 -+ program_alpha_mode( -+ crtc, -+ &pl_cfg->attributes.blend_flags, -+ path_mode->mode.timing.pixel_encoding); -+#endif -+ -+ dce110_mem_input_program_surface_config( -+ mi, -+ &surface->public); -+ -+ pipe_control_lock( -+ ctx, -+ controller_idx, -+ PIPE_LOCK_CONTROL_GRAPHICS | -+ PIPE_LOCK_CONTROL_SCL | -+ PIPE_LOCK_CONTROL_BLENDER | -+ PIPE_LOCK_CONTROL_SURFACE, -+ false); -+ -+ return true; -+} -+ -+static bool update_plane_address( -+ const struct core_surface *surface, -+ struct core_target *target) -+{ -+ struct dc_context *ctx = target->streams[0]->ctx; -+ struct mem_input *mi = target->streams[0]->mi; -+ uint8_t controller_id = target->streams[0]->controller_idx; -+ -+ /* TODO: crtc should be per surface, NOT per-target */ -+ pipe_control_lock( -+ ctx, -+ controller_id, -+ PIPE_LOCK_CONTROL_SURFACE, -+ true); -+ -+ if (false == dce110_mem_input_program_surface_flip_and_addr( -+ mi, &surface->public.address, surface->public.flip_immediate)) -+ return false; -+ -+ pipe_control_lock( -+ ctx, -+ controller_id, -+ PIPE_LOCK_CONTROL_SURFACE, -+ false); -+ -+ return true; -+} -+ -+static void reset_single_stream_hw_ctx(struct core_stream *stream, -+ struct validate_context *context) -+{ -+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) -+ deallocate_mst_payload(stream); -+ -+ disable_stream(stream); -+ if (stream->audio) { -+ dal_audio_disable_output(stream->audio, -+ stream->stream_enc->id, -+ stream->signal); -+ stream->audio = NULL; -+ } -+ -+ core_link_disable(stream); -+ dce110_timing_generator_blank_crtc(stream->tg); -+ dce110_timing_generator_disable_crtc(stream->tg); -+ dce110_deallocate_dmif_buffer(stream->mi, context->target_count); -+ dce110_transform_set_scaler_bypass(stream->xfm); -+ disable_stereo_mixer(stream->ctx); -+ unreference_clock_source(&context->res_ctx, stream->clock_source); -+} -+ -+static void reset_hw_ctx(struct dc *dc, -+ struct validate_context *context, -+ uint8_t target_count) -+{ -+ uint8_t i; -+ /* look up the targets that have been removed since last commit */ -+ for (i = 0; i < dc->current_context.target_count; i++) { -+ uint8_t controller_idx = dc->current_context.targets[i]-> -+ streams[0]->controller_idx; -+ -+ if (context->res_ctx.controller_ctx[controller_idx].stream && -+ !context->res_ctx.controller_ctx[controller_idx] -+ .flags.timing_changed) -+ continue; -+ -+ reset_single_stream_hw_ctx( -+ dc->current_context.targets[i]->streams[0], -+ &dc->current_context); -+ } -+} -+ -+static void power_down(struct validate_context *context) -+{ -+ power_down_all_hw_blocks(context); -+ disable_vga_and_power_gate_all_controllers(context); -+ -+} -+ -+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 (!dce110_timing_generator_is_counter_moving(tg)) { -+ DC_ERROR("TG counter is not moving!\n"); -+ break; -+ } -+ -+ if (dce110_timing_generator_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. */ -+ dce110_timing_generator_wait_for_vactive(tg); -+ dce110_timing_generator_wait_for_vblank(tg); -+ } -+ -+ if (false == rc) -+ DC_ERROR("GSL: Timeout on reset trigger!\n"); -+ -+ return rc; -+} -+ -+/* Enable timing synchronization for a group of Timing Generators. */ -+static void enable_timing_synchronization( -+ struct dc_context *dc_ctx, -+ uint32_t timing_generator_num, -+ struct timing_generator *tgs[]) -+{ -+ struct dcp_gsl_params gsl_params = { 0 }; -+ struct trigger_params trigger_params; -+ uint32_t i; -+ -+ DC_SYNC_INFO("GSL: Setting-up...\n"); -+ -+ gsl_params.gsl_group = SYNC_SOURCE_GSL_GROUP0; -+ gsl_params.gsl_purpose = DCP_GSL_PURPOSE_SURFACE_FLIP; -+ -+ for (i = 0; i < timing_generator_num; i++) { -+ /* Designate a single TG in the group as a master. -+ * Since HW doesn't care which one, we always assign -+ * the 1st one in the group. */ -+ gsl_params.timing_server = (0 == i ? true : false); -+ -+ dce110_timing_generator_setup_global_swap_lock(tgs[i], -+ &gsl_params); -+ } -+ -+ /* Reset slave controllers on master VSync */ -+ DC_SYNC_INFO("GSL: enabling trigger-reset\n"); -+ dc_service_memset(&trigger_params, 0, sizeof(trigger_params)); -+ -+ trigger_params.edge = TRIGGER_EDGE_DEFAULT; -+ trigger_params.source = SYNC_SOURCE_GSL_GROUP0; -+ -+ for (i = 1 /* skip the master */; i < timing_generator_num; i++) { -+ dce110_timing_generator_enable_reset_trigger(tgs[i], -+ &trigger_params); -+ -+ DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); -+ wait_for_reset_trigger_to_occur(dc_ctx, tgs[i]); -+ -+ /* Regardless of success of the wait above, remove the reset or -+ * the driver will start timing out on Display requests. */ -+ DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); -+ dce110_timing_generator_disable_reset_trigger(tgs[i]); -+ } -+ -+ /* GSL Vblank synchronization is a one time sync mechanism, assumption -+ * is that the sync'ed displays will not drift out of sync over time*/ -+ DC_SYNC_INFO("GSL: Restoring register states.\n"); -+ for (i = 0; i < timing_generator_num; i++) -+ dce110_timing_generator_tear_down_global_swap_lock(tgs[i]); -+ -+ DC_SYNC_INFO("GSL: Set-up complete.\n"); -+} -+ -+ -+static const struct hw_sequencer_funcs dce110_funcs = { -+ .apply_ctx_to_hw = apply_ctx_to_hw, -+ .reset_hw_ctx = reset_hw_ctx, -+ .set_plane_config = set_plane_config, -+ .update_plane_address = update_plane_address, -+ .enable_memory_requests = dce110_timing_generator_unblank_crtc, -+ .disable_memory_requests = dce110_timing_generator_blank_crtc, -+ .cursor_set_attributes = dce110_ipp_cursor_set_attributes, -+ .cursor_set_position = dce110_ipp_cursor_set_position, -+ .set_gamma_ramp = set_gamma_ramp, -+ .power_down = power_down, -+ .enable_accelerated_mode = enable_accelerated_mode, -+ .get_crtc_positions = dce110_timing_generator_get_crtc_positions, -+ .get_vblank_counter = dce110_timing_generator_get_vblank_counter, -+ .enable_timing_synchronization = enable_timing_synchronization, -+ .disable_vga = dce110_timing_generator_disable_vga, -+ .encoder_create = dce110_link_encoder_create, -+ .encoder_destroy = dce110_link_encoder_destroy, -+ .encoder_power_up = dce110_link_encoder_power_up, -+ .encoder_enable_output = dce110_link_encoder_enable_output, -+ .encoder_disable_output = dce110_link_encoder_disable_output, -+ .encoder_set_dp_phy_pattern = dce110_link_encoder_set_dp_phy_pattern, -+ .encoder_dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, -+ .encoder_set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, -+ .clock_gating_power_up = dal_dc_clock_gating_dce110_power_up, -+ .transform_power_up = dce110_transform_power_up, -+ .construct_resource_pool = dce110_construct_resource_pool, -+ .destruct_resource_pool = dce110_destruct_resource_pool, -+ .validate_with_context = dce110_validate_with_context, -+ .validate_bandwidth = dce110_validate_bandwidth, -+ .set_afmt_memory_power_state = dce110_set_afmt_memory_power_state, -+ .enable_display_pipe_clock_gating = dce110_enable_display_pipe_clock_gating, -+ .enable_display_power_gating = dce110_enable_display_power_gating, -+ .program_bw = dce110_program_bw -+}; -+ -+bool dce110_hw_sequencer_construct(struct dc *dc) -+{ -+ dc->hwss = dce110_funcs; -+ -+ return true; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h -new file mode 100644 -index 0000000..def54df ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h -@@ -0,0 +1,36 @@ -+/* -+* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_HWSS_DCE110_H__ -+#define __DC_HWSS_DCE110_H__ -+ -+#include "core_types.h" -+ -+struct dc; -+ -+bool dce110_hw_sequencer_construct(struct dc *dc); -+ -+#endif /* __DC_HWSS_DCE110_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c -new file mode 100644 -index 0000000..04105ed ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c -@@ -0,0 +1,85 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 dce110_ipp_reg_offsets 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), -+} -+}; -+ -+bool dce110_ipp_construct( -+ struct dce110_ipp* ipp, -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ if ((inst < 1) || (inst > ARRAY_SIZE(reg_offsets))) -+ return false; -+ -+ ipp->base.ctx = ctx; -+ -+ ipp->base.inst = inst; -+ -+ ipp->offsets = reg_offsets[inst-1]; -+ -+ return true; -+} -+ -+void dce110_ipp_destroy(struct input_pixel_processor **ipp) -+{ -+ dc_service_free((*ipp)->ctx, TO_DCE110_IPP(*ipp)); -+ *ipp = NULL; -+} -+ -+struct input_pixel_processor *dce110_ipp_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct dce110_ipp *ipp = -+ dc_service_alloc(ctx, sizeof(struct dce110_ipp)); -+ -+ if (!ipp) -+ return NULL; -+ -+ if (dce110_ipp_construct(ipp, ctx, inst)) -+ return &ipp->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, ipp); -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h -new file mode 100644 -index 0000000..1da42ff ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.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 __DC_IPP_DCE110_H__ -+#define __DC_IPP_DCE110_H__ -+ -+#include "inc/ipp.h" -+ -+#define TO_DCE110_IPP(input_pixel_processor)\ -+ container_of(input_pixel_processor, struct dce110_ipp, base) -+ -+struct dce110_ipp_reg_offsets { -+ uint32_t dcp_offset; -+}; -+ -+struct dce110_ipp { -+ struct input_pixel_processor base; -+ struct dce110_ipp_reg_offsets offsets; -+ struct dev_c_lut saved_palette[RGB_256X3X16]; -+}; -+ -+bool dce110_ipp_construct( -+ struct dce110_ipp* ipp, -+ struct dc_context *ctx, -+ enum controller_id id); -+ -+void dce110_ipp_destroy(struct input_pixel_processor **ipp); -+ -+struct input_pixel_processor *dce110_ipp_create( -+ struct dc_context *ctx, -+ enum controller_id id); -+ -+/* CURSOR RELATED */ -+bool dce110_ipp_cursor_set_position( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_position *position); -+ -+bool dce110_ipp_cursor_set_attributes( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_attributes *attributes); -+ -+/* DEGAMMA RELATED */ -+bool dce110_ipp_set_degamma( -+ struct input_pixel_processor *ipp, -+ const struct gamma_parameters *params, -+ bool force_bypass); -+ -+void dce110_ipp_program_prescale( -+ struct input_pixel_processor *ipp, -+ enum pixel_format pixel_format); -+ -+void dce110_ipp_set_legacy_input_gamma_mode( -+ struct input_pixel_processor *ipp, -+ bool is_legacy); -+ -+bool dce110_ipp_set_legacy_input_gamma_ramp( -+ struct input_pixel_processor *ipp, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params); -+ -+bool dce110_ipp_set_palette( -+ struct input_pixel_processor *ipp, -+ const struct dev_c_lut *palette, -+ uint32_t start, -+ uint32_t length, -+ enum pixel_format surface_pixel_format); -+ -+#endif /*__DC_IPP_DCE110_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c -new file mode 100644 -index 0000000..08b7940 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c -@@ -0,0 +1,256 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/logger_interface.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "dce110_ipp.h" -+ -+#define CURSOR_COLOR_BLACK 0x00000000 -+#define CURSOR_COLOR_WHITE 0xFFFFFFFF -+ -+#define DCP_REG(reg)\ -+ (reg + ipp110->offsets.dcp_offset) -+ -+static void enable( -+ struct dce110_ipp *ipp110, -+ bool enable); -+ -+static void lock( -+ struct dce110_ipp *ipp110, -+ bool enable); -+ -+static void program_position( -+ struct dce110_ipp *ipp110, -+ uint32_t x, -+ uint32_t y); -+ -+static bool program_control( -+ struct dce110_ipp *ipp110, -+ enum dc_cursor_color_format color_format, -+ bool enable_magnification, -+ bool inverse_transparent_clamping); -+ -+static void program_hotspot( -+ struct dce110_ipp *ipp110, -+ uint32_t x, -+ uint32_t y); -+ -+static void program_size( -+ struct dce110_ipp *ipp110, -+ uint32_t width, -+ uint32_t height); -+ -+static void program_address( -+ struct dce110_ipp *ipp110, -+ PHYSICAL_ADDRESS_LOC address); -+ -+ -+bool dce110_ipp_cursor_set_position( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_position *position) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ -+ /* lock cursor registers */ -+ lock(ipp110, true); -+ -+ /* Flag passed in structure differentiates cursor enable/disable. */ -+ /* Update if it differs from cached state. */ -+ enable(ipp110, position->enable); -+ -+ program_position(ipp110, position->x, position->y); -+ -+ if (position->hot_spot_enable) -+ program_hotspot( -+ ipp110, -+ position->x_origin, -+ position->y_origin); -+ -+ /* unlock cursor registers */ -+ lock(ipp110, false); -+ -+ return true; -+} -+ -+bool dce110_ipp_cursor_set_attributes( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_attributes *attributes) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ /* Lock cursor registers */ -+ lock(ipp110, true); -+ -+ /* Program cursor control */ -+ program_control( -+ ipp110, -+ attributes->color_format, -+ attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, -+ attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); -+ -+ /* Program hot spot coordinates */ -+ program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); -+ -+ /* -+ * Program cursor size -- NOTE: HW spec specifies that HW register -+ * stores size as (height - 1, width - 1) -+ */ -+ program_size(ipp110, attributes->width, attributes->height); -+ -+ /* Program cursor surface address */ -+ program_address(ipp110, attributes->address); -+ -+ /* Unlock Cursor registers. */ -+ lock(ipp110, false); -+ -+ return true; -+} -+ -+static void enable( -+ struct dce110_ipp *ipp110, bool enable) -+{ -+ uint32_t value = 0; -+ uint32_t addr = DCP_REG(mmCUR_CONTROL); -+ -+ value = dal_read_reg(ipp110->base.ctx, addr); -+ set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); -+ dal_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 = dal_read_reg(ipp110->base.ctx, addr); -+ set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); -+ dal_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 = dal_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); -+ dal_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); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ if (color_format == CURSOR_MODE_MONO) { -+ addr = DCP_REG(mmCUR_COLOR1); -+ dal_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); -+ addr = DCP_REG(mmCUR_COLOR2); -+ dal_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 = dal_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); -+ dal_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 = dal_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); -+ dal_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 */ -+ -+ dal_write_reg(ipp110->base.ctx, addr, address.high_part); -+ -+ addr = DCP_REG(mmCUR_SURFACE_ADDRESS); -+ dal_write_reg(ipp110->base.ctx, addr, address.low_part); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c -new file mode 100644 -index 0000000..f2e8ef4 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c -@@ -0,0 +1,877 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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" -+ -+#define DCP_REG(reg)\ -+ (reg + ipp110->offsets.dcp_offset) -+ -+enum { -+ MAX_INPUT_LUT_ENTRY = 256 -+}; -+ -+/* CALCULATION OPERATIONS*/ -+static void convert_256_lut_entries_to_gxo_format( -+ const struct gamma_ramp_rgb256x3x16 *lut, -+ struct dev_c_lut16 *gamma) -+{ -+ uint32_t i = 0; -+ -+ ASSERT(lut); -+ ASSERT(gamma); -+ -+ do { -+ gamma->red = lut->red[i]; -+ gamma->green = lut->green[i]; -+ gamma->blue = lut->blue[i]; -+ -+ ++gamma; -+ ++i; -+ } while (i != MAX_INPUT_LUT_ENTRY); -+} -+ -+static void convert_udx_gamma_entries_to_gxo_format( -+ const struct gamma_ramp_dxgi_1 *lut, -+ struct dev_c_lut16 *gamma) -+{ -+ /* TODO here we deal with DXGI gamma table, -+ * originally, values was expressed as 'float', -+ * now values expressed as 'dal_fixed20_12'. */ -+} -+ -+/*PROTOTYPE DECLARATIONS*/ -+static void set_lut_inc( -+ struct dce110_ipp *ipp110, -+ uint8_t inc, -+ bool is_float, -+ bool is_signed); -+ -+static void select_lut(struct dce110_ipp *ipp110); -+ -+static void program_black_offsets( -+ struct dce110_ipp *ipp110, -+ struct dev_c_lut16 *offset); -+ -+static void program_white_offsets( -+ struct dce110_ipp *ipp110, -+ struct dev_c_lut16 *offset); -+ -+static void program_black_white_offset( -+ struct dce110_ipp *ipp110, -+ enum pixel_format surface_pixel_format); -+ -+static void program_lut_gamma( -+ struct dce110_ipp *ipp110, -+ const struct dev_c_lut16 *gamma, -+ const struct gamma_parameters *params); -+ -+static void program_prescale( -+ struct dce110_ipp *ipp110, -+ enum pixel_format pixel_format); -+ -+static void set_legacy_input_gamma_mode( -+ struct dce110_ipp *ipp110, -+ bool is_legacy); -+ -+static bool set_legacy_input_gamma_ramp_rgb256x3x16( -+ struct dce110_ipp *ipp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params); -+ -+static bool set_legacy_input_gamma_ramp_dxgi1( -+ struct dce110_ipp *ipp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params); -+ -+static bool set_default_gamma( -+ struct dce110_ipp *ipp110, -+ enum pixel_format surface_pixel_format); -+ -+static void set_degamma( -+ struct dce110_ipp *ipp110, -+ const struct gamma_parameters *params, -+ bool force_bypass); -+ -+bool dce110_ipp_set_legacy_input_gamma_ramp( -+ struct input_pixel_processor *ipp, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ -+ switch (gamma_ramp->type) { -+ case GAMMA_RAMP_RBG256X3X16: -+ return set_legacy_input_gamma_ramp_rgb256x3x16( -+ ipp110, gamma_ramp, params); -+ case GAMMA_RAMP_DXGI_1: -+ return set_legacy_input_gamma_ramp_dxgi1( -+ ipp110, gamma_ramp, params); -+ default: -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+} -+ -+bool dce110_ipp_set_palette( -+ struct input_pixel_processor *ipp, -+ const struct dev_c_lut *palette, -+ uint32_t start, -+ uint32_t length, -+ enum pixel_format surface_pixel_format) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ uint32_t i; -+ -+ if (((start + length) > MAX_INPUT_LUT_ENTRY) || (NULL == palette)) { -+ BREAK_TO_DEBUGGER(); -+ /* wrong input */ -+ return false; -+ } -+ -+ for (i = start; i < start + length; i++) { -+ ipp110->saved_palette[i] = palette[i]; -+ ipp110->saved_palette[i] = palette[i]; -+ ipp110->saved_palette[i] = palette[i]; -+ } -+ -+ return set_default_gamma(ipp110, surface_pixel_format); -+} -+ -+bool dce110_ipp_set_degamma( -+ struct input_pixel_processor *ipp, -+ const struct gamma_parameters *params, -+ bool force_bypass) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ -+ set_degamma(ipp110, params, force_bypass); -+ -+ return true; -+} -+ -+void dce110_ipp_program_prescale( -+ struct input_pixel_processor *ipp, -+ enum pixel_format pixel_format) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ -+ program_prescale(ipp110, pixel_format); -+} -+ -+void dce110_ipp_set_legacy_input_gamma_mode( -+ struct input_pixel_processor *ipp, -+ bool is_legacy) -+{ -+ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); -+ -+ set_legacy_input_gamma_mode(ipp110, is_legacy); -+} -+ -+static void set_lut_inc( -+ struct dce110_ipp *ipp110, -+ uint8_t inc, -+ bool is_float, -+ bool is_signed) -+{ -+ const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); -+ -+ uint32_t value = dal_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); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+} -+ -+static void 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 = dal_read_reg(ipp110->base.ctx, addr); -+ -+ /* enable all */ -+ set_reg_field_value( -+ value, -+ 0x7, -+ DC_LUT_WRITE_EN_MASK, -+ DC_LUT_WRITE_EN_MASK); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ } -+ -+ { -+ const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); -+ -+ value = dal_read_reg(ipp110->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DC_LUT_RW_MODE, -+ DC_LUT_RW_MODE); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ } -+ -+ { -+ const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); -+ -+ value = dal_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); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ } -+ -+ { -+ const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); -+ -+ value = dal_read_reg(ipp110->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DC_LUT_RW_INDEX, -+ DC_LUT_RW_INDEX); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ } -+} -+ -+static void program_black_offsets( -+ struct dce110_ipp *ipp110, -+ struct dev_c_lut16 *offset) -+{ -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_BLACK_OFFSET_RED), -+ offset->red); -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_BLACK_OFFSET_GREEN), -+ offset->green); -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_BLACK_OFFSET_BLUE), -+ offset->blue); -+} -+ -+static void program_white_offsets( -+ struct dce110_ipp *ipp110, -+ struct dev_c_lut16 *offset) -+{ -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_WHITE_OFFSET_RED), -+ offset->red); -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_WHITE_OFFSET_GREEN), -+ offset->green); -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmDC_LUT_WHITE_OFFSET_BLUE), -+ offset->blue); -+} -+ -+static void program_black_white_offset( -+ struct dce110_ipp *ipp110, -+ enum pixel_format surface_pixel_format) -+{ -+ struct dev_c_lut16 black_offset; -+ struct dev_c_lut16 white_offset; -+ -+ /* get black offset */ -+ -+ switch (surface_pixel_format) { -+ case PIXEL_FORMAT_FP16: -+ /* sRGB gamut, [0.0...1.0] */ -+ black_offset.red = 0; -+ black_offset.green = 0; -+ black_offset.blue = 0; -+ break; -+ -+ case PIXEL_FORMAT_ARGB2101010_XRBIAS: -+ /* [-1.0...3.0] */ -+ black_offset.red = 0x100; -+ black_offset.green = 0x100; -+ black_offset.blue = 0x100; -+ break; -+ -+ default: -+ black_offset.red = 0; -+ black_offset.green = 0; -+ black_offset.blue = 0; -+ } -+ -+ /* get white offset */ -+ -+ switch (surface_pixel_format) { -+ case PIXEL_FORMAT_FP16: -+ white_offset.red = 0x3BFF; -+ white_offset.green = 0x3BFF; -+ white_offset.blue = 0x3BFF; -+ break; -+ -+ case PIXEL_FORMAT_ARGB2101010_XRBIAS: -+ white_offset.red = 0x37E; -+ white_offset.green = 0x37E; -+ white_offset.blue = 0x37E; -+ break; -+ -+ case PIXEL_FORMAT_ARGB8888: -+ white_offset.red = 0xFF; -+ white_offset.green = 0xFF; -+ white_offset.blue = 0xFF; -+ break; -+ -+ default: -+ white_offset.red = 0x3FF; -+ white_offset.green = 0x3FF; -+ white_offset.blue = 0x3FF; -+ } -+ -+ program_black_offsets(ipp110, &black_offset); -+ program_white_offsets(ipp110, &white_offset); -+} -+ -+static void program_lut_gamma( -+ struct dce110_ipp *ipp110, -+ const struct dev_c_lut16 *gamma, -+ const struct gamma_parameters *params) -+{ -+ uint32_t i = 0; -+ uint32_t value = 0; -+ uint32_t addr; -+ -+ { -+ uint8_t max_tries = 10; -+ uint8_t counter = 0; -+ -+ /* Power on LUT memory */ -+ value = dal_read_reg( -+ ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DCFE_MEM_PWR_CTRL, -+ DCP_REGAMMA_MEM_PWR_DIS); -+ -+ dal_write_reg( -+ ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); -+ -+ while (counter < max_tries) { -+ value = -+ dal_read_reg( -+ ipp110->base.ctx, -+ DCP_REG(mmDCFE_MEM_PWR_STATUS)); -+ -+ if (get_reg_field_value( -+ value, -+ DCFE_MEM_PWR_STATUS, -+ DCP_REGAMMA_MEM_PWR_STATE) == 0) -+ break; -+ -+ ++counter; -+ } -+ -+ if (counter == max_tries) { -+ dal_logger_write(ipp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: regamma lut was not powered on in a timely manner, programming still proceeds\n", -+ __func__); -+ } -+ } -+ -+ program_black_white_offset(ipp110, params->surface_pixel_format); -+ -+ select_lut(ipp110); -+ -+ if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8) { -+ addr = DCP_REG(mmDC_LUT_SEQ_COLOR); -+ -+ do { -+ struct dev_c_lut *index = -+ ipp110->saved_palette + i; -+ -+ set_reg_field_value( -+ value, -+ gamma[index->red].red, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ -+ set_reg_field_value( -+ value, -+ gamma[index->green].green, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ -+ set_reg_field_value( -+ value, -+ gamma[index->blue].blue, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ ++i; -+ } while (i != RGB_256X3X16); -+ } else { -+ addr = DCP_REG(mmDC_LUT_SEQ_COLOR); -+ -+ do { -+ set_reg_field_value( -+ value, -+ gamma[i].red, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ -+ set_reg_field_value( -+ value, -+ gamma[i].green, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ -+ set_reg_field_value( -+ value, -+ gamma[i].blue, -+ DC_LUT_SEQ_COLOR, -+ DC_LUT_SEQ_COLOR); -+ dal_write_reg(ipp110->base.ctx, addr, value); -+ -+ ++i; -+ } while (i != RGB_256X3X16); -+ } -+ -+ /* we are done with DCP LUT memory; re-enable low power mode */ -+ value = dal_read_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DCFE_MEM_PWR_CTRL, -+ DCP_REGAMMA_MEM_PWR_DIS); -+ -+ dal_write_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); -+} -+ -+static void program_prescale( -+ struct dce110_ipp *ipp110, -+ enum pixel_format pixel_format) -+{ -+ uint32_t prescale_control; -+ uint32_t prescale_values_grph_r = 0; -+ uint32_t prescale_values_grph_g = 0; -+ uint32_t prescale_values_grph_b = 0; -+ -+ uint32_t prescale_num; -+ uint32_t prescale_denom = 1; -+ uint16_t prescale_hw; -+ uint32_t bias_num = 0; -+ uint32_t bias_denom = 1; -+ uint16_t bias_hw; -+ -+ const uint32_t addr_control = DCP_REG(mmPRESCALE_GRPH_CONTROL); -+ -+ prescale_control = dal_read_reg(ipp110->base.ctx, addr_control); -+ -+ set_reg_field_value( -+ prescale_control, -+ 0, -+ PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_BYPASS); -+ -+ switch (pixel_format) { -+ case PIXEL_FORMAT_RGB565: -+ prescale_num = 64; -+ prescale_denom = 63; -+ break; -+ -+ case PIXEL_FORMAT_ARGB8888: -+ /* This function should only be called when using regamma -+ * and bypassing legacy INPUT GAMMA LUT (function name is -+ * misleading) -+ */ -+ prescale_num = 256; -+ prescale_denom = 255; -+ break; -+ -+ case PIXEL_FORMAT_ARGB2101010: -+ prescale_num = 1024; -+ prescale_denom = 1023; -+ break; -+ -+ case PIXEL_FORMAT_ARGB2101010_XRBIAS: -+ prescale_num = 1024; -+ prescale_denom = 510; -+ bias_num = 384; -+ bias_denom = 1024; -+ break; -+ -+ case PIXEL_FORMAT_FP16: -+ prescale_num = 1; -+ break; -+ -+ default: -+ prescale_num = 1; -+ -+ set_reg_field_value( -+ prescale_control, -+ 1, -+ PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_BYPASS); -+ } -+ -+ prescale_hw = fixed_point_to_int_frac( -+ dal_fixed31_32_from_fraction(prescale_num, prescale_denom), -+ 2, 13); -+ -+ bias_hw = fixed_point_to_int_frac( -+ dal_fixed31_32_from_fraction(bias_num, bias_denom), -+ 2, 13); -+ -+ -+ set_reg_field_value( -+ prescale_values_grph_r, -+ prescale_hw, -+ PRESCALE_VALUES_GRPH_R, -+ GRPH_PRESCALE_SCALE_R); -+ -+ set_reg_field_value( -+ prescale_values_grph_r, -+ bias_hw, -+ PRESCALE_VALUES_GRPH_R, -+ GRPH_PRESCALE_BIAS_R); -+ -+ -+ set_reg_field_value( -+ prescale_values_grph_g, -+ prescale_hw, -+ PRESCALE_VALUES_GRPH_G, -+ GRPH_PRESCALE_SCALE_G); -+ -+ set_reg_field_value( -+ prescale_values_grph_g, -+ bias_hw, -+ PRESCALE_VALUES_GRPH_G, -+ GRPH_PRESCALE_BIAS_G); -+ -+ -+ set_reg_field_value( -+ prescale_values_grph_b, -+ prescale_hw, -+ PRESCALE_VALUES_GRPH_B, -+ GRPH_PRESCALE_SCALE_B); -+ -+ set_reg_field_value( -+ prescale_values_grph_b, -+ bias_hw, -+ PRESCALE_VALUES_GRPH_B, -+ GRPH_PRESCALE_BIAS_B); -+ -+ dal_write_reg(ipp110->base.ctx, -+ addr_control, prescale_control); -+ -+ { -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmPRESCALE_VALUES_GRPH_R), -+ prescale_values_grph_r); -+ } -+ -+ { -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmPRESCALE_VALUES_GRPH_G), -+ prescale_values_grph_g); -+ } -+ -+ { -+ dal_write_reg(ipp110->base.ctx, -+ DCP_REG(mmPRESCALE_VALUES_GRPH_B), -+ prescale_values_grph_b); -+ } -+} -+ -+static void set_legacy_input_gamma_mode( -+ struct dce110_ipp *ipp110, -+ bool is_legacy) -+{ -+ const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); -+ uint32_t value = dal_read_reg(ipp110->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ !is_legacy, -+ INPUT_GAMMA_CONTROL, -+ GRPH_INPUT_GAMMA_MODE); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+} -+ -+static bool set_legacy_input_gamma_ramp_rgb256x3x16( -+ struct dce110_ipp *ipp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ struct dev_c_lut16 *gamma16 = -+ dc_service_alloc( -+ ipp110->base.ctx, -+ sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); -+ -+ if (!gamma16) -+ return false; -+ -+ convert_256_lut_entries_to_gxo_format( -+ &gamma_ramp->gamma_ramp_rgb256x3x16, gamma16); -+ -+ if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && -+ (params->surface_pixel_format != -+ PIXEL_FORMAT_ARGB2101010_XRBIAS) && -+ (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { -+ program_lut_gamma(ipp110, gamma16, params); -+ dc_service_free(ipp110->base.ctx, gamma16); -+ return true; -+ } -+ -+ /* TODO process DirectX-specific formats*/ -+ dc_service_free(ipp110->base.ctx, gamma16); -+ return false; -+} -+ -+static bool set_legacy_input_gamma_ramp_dxgi1( -+ struct dce110_ipp *ipp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ struct dev_c_lut16 *gamma16 = -+ dc_service_alloc( -+ ipp110->base.ctx, -+ sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); -+ -+ if (!gamma16) -+ return false; -+ -+ convert_udx_gamma_entries_to_gxo_format( -+ &gamma_ramp->gamma_ramp_dxgi1, gamma16); -+ -+ if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && -+ (params->surface_pixel_format != -+ PIXEL_FORMAT_ARGB2101010_XRBIAS) && -+ (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { -+ program_lut_gamma(ipp110, gamma16, params); -+ dc_service_free(ipp110->base.ctx, gamma16); -+ return true; -+ } -+ -+ /* TODO process DirectX-specific formats*/ -+ dc_service_free(ipp110->base.ctx, gamma16); -+ return false; -+} -+ -+static bool set_default_gamma( -+ struct dce110_ipp *ipp110, -+ enum pixel_format surface_pixel_format) -+{ -+ uint32_t i; -+ -+ struct dev_c_lut16 *gamma16 = NULL; -+ struct gamma_parameters *params = NULL; -+ -+ gamma16 = dc_service_alloc( -+ ipp110->base.ctx, -+ sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); -+ -+ if (!gamma16) -+ return false; -+ -+ params = dc_service_alloc(ipp110->base.ctx, sizeof(*params)); -+ -+ if (!params) { -+ dc_service_free(ipp110->base.ctx, gamma16); -+ return false; -+ } -+ -+ for (i = 0; i < MAX_INPUT_LUT_ENTRY; i++) { -+ gamma16[i].red = gamma16[i].green = -+ gamma16[i].blue = (uint16_t) (i << 8); -+ } -+ -+ params->surface_pixel_format = surface_pixel_format; -+ params->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_HW; -+ params->degamma_adjust_type = GRAPHICS_DEGAMMA_ADJUST_HW; -+ params->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA; -+ params->disable_adjustments = false; -+ -+ params->regamma.features.value = 0; -+ -+ params->regamma.features.bits.GAMMA_RAMP_ARRAY = 0; -+ params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1; -+ params->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1; -+ -+ for (i = 0; i < 3; i++) { -+ params->regamma.gamma_coeff.a0[i] = 31308; -+ params->regamma.gamma_coeff.a1[i] = 12920; -+ params->regamma.gamma_coeff.a2[i] = 55; -+ params->regamma.gamma_coeff.a3[i] = 55; -+ params->regamma.gamma_coeff.gamma[i] = 2400; -+ -+ } -+ -+ program_lut_gamma(ipp110, gamma16, params); -+ -+ dc_service_free(ipp110->base.ctx, gamma16); -+ dc_service_free(ipp110->base.ctx, params); -+ -+ return true; -+} -+ -+static void set_degamma( -+ struct dce110_ipp *ipp110, -+ const struct gamma_parameters *params, -+ bool force_bypass) -+{ -+ uint32_t value; -+ const uint32_t addr = DCP_REG(mmDEGAMMA_CONTROL); -+ uint32_t degamma_type = -+ params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB == 1 ? -+ 1 : 2; -+ -+ value = dal_read_reg(ipp110->base.ctx, addr); -+ -+ /* if by pass - no degamma -+ * when legacy and regamma LUT's we do degamma */ -+ if (params->degamma_adjust_type == GRAPHICS_DEGAMMA_ADJUST_BYPASS || -+ (params->surface_pixel_format == PIXEL_FORMAT_FP16 && -+ params->selected_gamma_lut == -+ GRAPHICS_GAMMA_LUT_REGAMMA)) -+ degamma_type = 0; -+ -+ if (force_bypass) -+ degamma_type = 0; -+ -+ set_reg_field_value( -+ value, -+ degamma_type, -+ DEGAMMA_CONTROL, -+ GRPH_DEGAMMA_MODE); -+ -+ set_reg_field_value( -+ value, -+ degamma_type, -+ DEGAMMA_CONTROL, -+ CURSOR_DEGAMMA_MODE); -+ -+ set_reg_field_value( -+ value, -+ degamma_type, -+ DEGAMMA_CONTROL, -+ CURSOR2_DEGAMMA_MODE); -+ -+ dal_write_reg(ipp110->base.ctx, addr, value); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c -new file mode 100644 -index 0000000..0297bd3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c -@@ -0,0 +1,2049 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "core_types.h" -+#include "link_encoder_types.h" -+#include "dce110_link_encoder.h" -+#include "i2caux_interface.h" -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "dce/dce_11_0_enum.h" -+ -+#define DELAY_AFTER_PIXEL_FORMAT_CHANGE 0 /* ms */ -+/* For current ASICs pixel clock - 600MHz */ -+#define MAX_ENCODER_CLK 600000 -+ -+#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 600000 -+ -+#define DEFAULT_AUX_MAX_DATA_SIZE 16 -+#define AUX_MAX_DEFER_WRITE_RETRY 20 -+/* -+ * @brief -+ * Trigger Source Select -+ * ASIC-dependent, actual values for register programming -+ */ -+#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0 -+#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1 -+#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2 -+#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4 -+ -+/* all values are in milliseconds */ -+/* For eDP, after power-up/power/down, -+ * 300/500 msec max. delay from LCDVCC to black video generation */ -+#define PANEL_POWER_UP_TIMEOUT 300 -+#define PANEL_POWER_DOWN_TIMEOUT 500 -+#define HPD_CHECK_INTERVAL 10 -+ -+/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ -+#define TMDS_MIN_PIXEL_CLOCK 25000 -+/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ -+#define TMDS_MAX_PIXEL_CLOCK 165000 -+/* For current ASICs pixel clock - 600MHz */ -+#define MAX_ENCODER_CLOCK 600000 -+ -+enum { -+ DP_MST_UPDATE_MAX_RETRY = 50 -+}; -+ -+#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 -+ -+ -+static const uint32_t fe_engine_offsets[] = { -+ mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+}; -+ -+ -+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 void enable_phy_bypass_mode( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ bool enable) -+{ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ const uint32_t addr = mmDP_DPHY_CNTL + be_addr_offset; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, enable, DP_DPHY_CNTL, DPHY_BYPASS); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void disable_prbs_symbols( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ bool disable) -+{ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ const uint32_t addr = mmDP_DPHY_CNTL + be_addr_offset; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, disable, -+ DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0); -+ -+ set_reg_field_value(value, disable, -+ DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1); -+ -+ set_reg_field_value(value, disable, -+ DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2); -+ -+ set_reg_field_value(value, disable, -+ DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void disable_prbs_mode( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset) -+{ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ const uint32_t addr = mmDP_DPHY_PRBS_CNTL + be_addr_offset; -+ uint32_t value; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, 0, DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void program_pattern_symbols( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ uint16_t pattern_symbols[8]) -+{ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ addr = mmDP_DPHY_SYM0 + be_addr_offset; -+ -+ value = 0; -+ set_reg_field_value(value, pattern_symbols[0], -+ DP_DPHY_SYM0, DPHY_SYM1); -+ set_reg_field_value(value, pattern_symbols[1], -+ DP_DPHY_SYM0, DPHY_SYM2); -+ set_reg_field_value(value, pattern_symbols[2], -+ DP_DPHY_SYM0, DPHY_SYM3); -+ dal_write_reg(ctx, addr, value); -+ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ addr = mmDP_DPHY_SYM1 + be_addr_offset; -+ -+ value = 0; -+ set_reg_field_value(value, pattern_symbols[3], -+ DP_DPHY_SYM1, DPHY_SYM4); -+ set_reg_field_value(value, pattern_symbols[4], -+ DP_DPHY_SYM1, DPHY_SYM5); -+ set_reg_field_value(value, pattern_symbols[5], -+ DP_DPHY_SYM1, DPHY_SYM6); -+ dal_write_reg(ctx, addr, value); -+ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ addr = mmDP_DPHY_SYM2 + be_addr_offset; -+ value = 0; -+ set_reg_field_value(value, pattern_symbols[6], -+ DP_DPHY_SYM2, DPHY_SYM7); -+ set_reg_field_value(value, pattern_symbols[6], -+ DP_DPHY_SYM2, DPHY_SYM8); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void set_dp_phy_pattern_d102( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset) -+{ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, false); -+ -+ /* For 10-bit PRBS or debug symbols -+ * please use the following sequence: */ -+ -+ /* Enable debug symbols on the lanes */ -+ -+ disable_prbs_symbols(ctx, be_addr_offset, true); -+ -+ /* Disable PRBS mode, -+ * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ -+ -+ disable_prbs_mode(ctx, be_addr_offset); -+ -+ /* Program debug symbols to be output */ -+ { -+ uint16_t pattern_symbols[8] = { -+ 0x2AA, 0x2AA, 0x2AA, 0x2AA, -+ 0x2AA, 0x2AA, 0x2AA, 0x2AA -+ }; -+ -+ program_pattern_symbols(ctx, -+ be_addr_offset, pattern_symbols); -+ } -+ -+ /* Enable phy bypass mode to enable the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, true); -+} -+ -+static void set_link_training_complete( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ bool complete) -+{ -+ /* This register resides in DP back end block; -+ * transmitter is used for the offset */ -+ -+ const uint32_t addr = mmDP_LINK_CNTL + be_addr_offset; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, complete, -+ DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void set_dp_phy_pattern_training_pattern( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ uint32_t index) -+{ -+ /* Write Training Pattern */ -+ -+ dal_write_reg(ctx, -+ mmDP_DPHY_TRAINING_PATTERN_SEL + be_addr_offset, index); -+ -+ /* Set HW Register Training Complete to false */ -+ -+ set_link_training_complete(ctx, be_addr_offset, false); -+ -+ /* Disable PHY Bypass mode to output Training Pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, false); -+ -+ /* Disable PRBS mode, -+ * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ -+ -+ disable_prbs_mode(ctx, be_addr_offset); -+} -+ -+static void set_dp_phy_pattern_symbol_error( -+ struct dc_context *ctx, -+ const int32_t addr_offset) -+{ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, addr_offset, false); -+ -+ /* program correct panel mode*/ -+ { -+ const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + addr_offset; -+ uint32_t value = 0x0; -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* A PRBS23 pattern is used for most DP electrical measurements. */ -+ -+ /* Enable PRBS symbols on the lanes */ -+ -+ disable_prbs_symbols(ctx, addr_offset, false); -+ -+ /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ -+ { -+ const uint32_t addr = mmDP_DPHY_PRBS_CNTL + addr_offset; -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, 1, -+ DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL); -+ set_reg_field_value(value, 1, -+ DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN); -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* Enable phy bypass mode to enable the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, addr_offset, true); -+} -+ -+static void set_dp_phy_pattern_prbs7( -+ struct dc_context *ctx, -+ const int32_t addr_offset) -+{ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, addr_offset, false); -+ -+ /* A PRBS7 pattern is used for most DP electrical measurements. */ -+ -+ /* Enable PRBS symbols on the lanes */ -+ -+ disable_prbs_symbols(ctx, addr_offset, false); -+ -+ /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ -+ { -+ const uint32_t addr = mmDP_DPHY_PRBS_CNTL + addr_offset; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL); -+ -+ set_reg_field_value(value, 1, -+ DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* Enable phy bypass mode to enable the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, addr_offset, true); -+} -+ -+static void set_dp_phy_pattern_80bit_custom( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ const uint8_t *pattern) -+{ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, false); -+ -+ /* Enable debug symbols on the lanes */ -+ -+ disable_prbs_symbols(ctx, be_addr_offset, true); -+ -+ /* Enable PHY bypass mode to enable the test pattern */ -+ /* TODO is it really needed ? */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, 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(ctx, -+ be_addr_offset, pattern_symbols); -+ } -+ -+ /* Enable phy bypass mode to enable the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, true); -+} -+ -+void dce110_link_encoder_setup( -+ struct link_encoder *enc, -+ enum signal_type signal) -+{ -+ const uint32_t addr = mmDIG_BE_CNTL + enc->be_engine_offset; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ -+ switch (signal) { -+ case SIGNAL_TYPE_EDP: -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ /* DP SST */ -+ set_reg_field_value(value, 0, DIG_BE_CNTL, DIG_MODE); -+ break; -+ case SIGNAL_TYPE_LVDS: -+ /* LVDS */ -+ set_reg_field_value(value, 1, DIG_BE_CNTL, DIG_MODE); -+ break; -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ /* TMDS-DVI */ -+ set_reg_field_value(value, 2, DIG_BE_CNTL, DIG_MODE); -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ /* TMDS-HDMI */ -+ set_reg_field_value(value, 3, DIG_BE_CNTL, DIG_MODE); -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ /* DP MST */ -+ set_reg_field_value(value, 5, DIG_BE_CNTL, DIG_MODE); -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ /* invalid mode ! */ -+ break; -+ } -+ -+ dal_write_reg(enc->ctx, addr, value); -+} -+ -+static void set_dp_phy_pattern_hbr2_compliance( -+ struct link_encoder *enc, -+ const int32_t be_addr_offset) -+{ -+ /*const int32_t fe_addr_offset = fe_engine_offsets[param->engine]; -+ const int32_t be_addr_offset = enc->be_engine_offset;*/ -+ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* previously there is a register DP_HBR2_EYE_PATTERN -+ * that is enabled to get the pattern. -+ * But it does not work with the latest spec change, -+ * so we are programming the following registers manually. -+ * -+ * The following settings have been confirmed -+ * by Nick Chorney and Sandra Liu */ -+ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(enc->ctx, be_addr_offset, false); -+ -+ /* Setup DIG encoder in DP SST mode */ -+ -+ dce110_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); -+ -+ /* program correct panel mode*/ -+ { -+ const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + be_addr_offset; -+ uint32_t value = 0x0; -+ dal_write_reg(enc->ctx, addr, value); -+ } -+ -+ /* no vbid after BS (SR) -+ * DP_LINK_FRAMING_CNTL changed history Sandra Liu -+ * 11000260 / 11000104 / 110000FC */ -+ -+ /* TODO DP_LINK_FRAMING_CNTL should always use hardware default value -+ * output except output hbr2_compliance pattern for physical PHY -+ * measurement. This is not normal usage case. SW should reset this -+ * register to hardware default value after end use of HBR2 eye -+ */ -+ BREAK_TO_DEBUGGER(); -+ /* TODO: do we still need this, find out at compliance test -+ addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; -+ -+ value = dal_read_reg(enc->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(enc->ctx, addr, value); -+ */ -+ -+ /*TODO add support for this test pattern -+ * support_dp_hbr2_eye_pattern -+ */ -+ -+ /* set link training complete */ -+ set_link_training_complete(enc->ctx, be_addr_offset, true); -+ /* do not enable video stream */ -+ addr = mmDP_VID_STREAM_CNTL + be_addr_offset; -+ -+ value = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE); -+ -+ dal_write_reg(enc->ctx, addr, value); -+ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(enc->ctx, be_addr_offset, false); -+} -+ -+static void set_dp_phy_pattern_passthrough_mode( -+ struct dc_context *ctx, -+ const int32_t be_addr_offset, -+ enum dp_panel_mode panel_mode) -+{ -+ -+ /* program correct panel mode */ -+ { -+ const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + be_addr_offset; -+ -+ uint32_t value; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ switch (panel_mode) { -+ case DP_PANEL_MODE_EDP: -+ value = 0x1; -+ break; -+ case DP_PANEL_MODE_SPECIAL: -+ value = 0x11; -+ break; -+ default: -+ value = 0x0; -+ break; -+ } -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* set link training complete */ -+ -+ set_link_training_complete(ctx, be_addr_offset, true); -+ -+ /* Disable PHY Bypass mode to setup the test pattern */ -+ -+ enable_phy_bypass_mode(ctx, be_addr_offset, false); -+ -+ /* Disable PRBS mode, -+ * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ -+ -+ disable_prbs_mode(ctx, be_addr_offset); -+} -+ -+static void construct( -+ struct link_encoder *enc, -+ const struct encoder_init_data *init_data) -+{ -+ struct graphics_object_encoder_cap_info enc_cap_info = {0}; -+ -+ enc->ctx = init_data->ctx; -+ enc->id = init_data->encoder; -+ -+ enc->hpd_source = init_data->hpd_source; -+ enc->connector = init_data->connector; -+ enc->input_signals = SIGNAL_TYPE_ALL; -+ -+ enc->adapter_service = init_data->adapter_service; -+ -+ enc->preferred_engine = ENGINE_ID_UNKNOWN; -+ -+ enc->features.flags.raw = 0; -+ -+ enc->transmitter = translate_encoder_to_transmitter( -+ init_data->encoder); -+ -+ enc->features.flags.bits.IS_AUDIO_CAPABLE = true; -+ -+ enc->features.max_pixel_clock = DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ; -+ -+ /* set the flag to indicate whether driver poll the I2C data pin -+ * while doing the DP sink detect */ -+ -+ if (dal_adapter_service_is_feature_supported( -+ FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) -+ enc->features.flags.bits.DP_SINK_DETECT_POLL_DATA_PIN = true; -+ -+ enc->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 */ -+ -+ switch (enc->transmitter) { -+ case TRANSMITTER_UNIPHY_A: -+ enc->preferred_engine = ENGINE_ID_DIGA; -+ enc->transmitter_offset = 0; -+ enc->be_engine_offset = 0; -+ break; -+ case TRANSMITTER_UNIPHY_B: -+ enc->preferred_engine = ENGINE_ID_DIGB; -+ -+ enc->transmitter_offset = -+ mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL1 - -+ mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL1; -+ enc->be_engine_offset = -+ mmDIG1_DIG_BE_CNTL - mmDIG0_DIG_BE_CNTL; -+ break; -+ case TRANSMITTER_UNIPHY_C: -+ enc->preferred_engine = ENGINE_ID_DIGC; -+ enc->transmitter_offset = -+ mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL1 - -+ mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL1; -+ enc->be_engine_offset = -+ mmDIG2_DIG_BE_CNTL - mmDIG0_DIG_BE_CNTL; -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ enc->preferred_engine = ENGINE_ID_UNKNOWN; -+ enc->transmitter_offset = 0; -+ enc->be_engine_offset = 0; -+ } -+ -+ dal_logger_write(init_data->ctx->logger, -+ LOG_MAJOR_I2C_AUX, -+ LOG_MINOR_I2C_AUX_CFG, -+ "Using channel: %s [%d]\n", -+ DECODE_CHANNEL_ID(init_data->channel), -+ init_data->channel); -+ -+ switch (init_data->channel) { -+ case CHANNEL_ID_DDC1: -+ enc->aux_channel_offset = 0; -+ break; -+ case CHANNEL_ID_DDC2: -+ enc->aux_channel_offset = -+ mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; -+ break; -+ case CHANNEL_ID_DDC3: -+ enc->aux_channel_offset = -+ mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; -+ break; -+ default: -+ /* check BIOS object table ! */ -+ dal_logger_write(init_data->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_ENCODER, -+ "%s: Invalid channel ID\n", -+ __func__); -+ enc->aux_channel_offset = 0; -+ } -+ -+ /* Override features with DCE-specific values */ -+ if (dal_adapter_service_get_encoder_cap_info(enc->adapter_service, -+ enc->id, &enc_cap_info)) -+ enc->features.flags.bits.IS_HBR2_CAPABLE = -+ enc_cap_info.dp_hbr2_cap; -+ -+ /* test pattern 3 support */ -+ enc->features.flags.bits.IS_TPS3_CAPABLE = true; -+ enc->features.max_deep_color = COLOR_DEPTH_121212; -+ -+ enc->features.flags.bits.IS_Y_ONLY_CAPABLE = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_SUPPORT_DP_Y_ONLY); -+ -+ enc->features.flags.bits.IS_YCBCR_CAPABLE = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_SUPPORT_DP_YUV); -+} -+ -+struct link_encoder *dce110_link_encoder_create( -+ const struct encoder_init_data *init) -+{ -+ struct link_encoder *enc = -+ dc_service_alloc(init->ctx, sizeof(struct link_encoder)); -+ -+ if (!enc) -+ goto enc_create_fail; -+ -+ construct(enc, init); -+ -+ return enc; -+ -+enc_create_fail: -+ return NULL; -+} -+ -+void dce110_link_encoder_destroy(struct link_encoder **enc) -+{ -+ struct link_encoder *encoder = *enc; -+ dc_service_free(encoder->ctx, encoder); -+ *enc = NULL; -+} -+ -+void dce110_link_encoder_set_dp_phy_pattern( -+ struct link_encoder *enc, -+ const struct encoder_set_dp_phy_pattern_param *param) -+{ -+ const int32_t offset = enc->be_engine_offset; -+ -+ -+ switch (param->dp_phy_pattern) { -+ case DP_TEST_PATTERN_TRAINING_PATTERN1: -+ set_dp_phy_pattern_training_pattern(enc->ctx, -+ offset, 0); -+ break; -+ case DP_TEST_PATTERN_TRAINING_PATTERN2: -+ set_dp_phy_pattern_training_pattern(enc->ctx, -+ offset, 1); -+ break; -+ case DP_TEST_PATTERN_TRAINING_PATTERN3: -+ set_dp_phy_pattern_training_pattern(enc->ctx, -+ offset, 2); -+ break; -+ case DP_TEST_PATTERN_D102: -+ set_dp_phy_pattern_d102(enc->ctx, offset); -+ break; -+ case DP_TEST_PATTERN_SYMBOL_ERROR: -+ set_dp_phy_pattern_symbol_error(enc->ctx, offset); -+ break; -+ case DP_TEST_PATTERN_PRBS7: -+ set_dp_phy_pattern_prbs7(enc->ctx, offset); -+ break; -+ case DP_TEST_PATTERN_80BIT_CUSTOM: -+ set_dp_phy_pattern_80bit_custom( -+ enc->ctx, -+ offset, param->custom_pattern); -+ break; -+ case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: -+ set_dp_phy_pattern_hbr2_compliance( -+ enc, offset); -+ break; -+ case DP_TEST_PATTERN_VIDEO_MODE: { -+ set_dp_phy_pattern_passthrough_mode( -+ enc->ctx, -+ offset, -+ param->dp_panel_mode); -+ break; -+ } -+ -+ -+ default: -+ /* invalid phy pattern */ -+ ASSERT_CRITICAL(false); -+ break; -+ } -+} -+ -+enum encoder_result dce110_link_encoder_dp_set_lane_settings( -+ struct link_encoder *enc, -+ const struct link_training_settings *link_settings) -+{ -+ 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 ENCODER_RESULT_ERROR; -+ } -+ -+ cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; -+ cntl.transmitter = enc->transmitter; -+ cntl.connector_obj_id = enc->connector; -+ cntl.lanes_number = link_settings->link_settings.lane_count; -+ cntl.hpd_sel = enc->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 */ -+ -+ dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ enc->adapter_service), &cntl); -+ } -+ -+ return ENCODER_RESULT_OK; -+} -+ -+/* 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; -+ default: -+ ASSERT_CRITICAL(false); -+ return DCE110_DIG_FE_SOURCE_SELECT_INVALID; -+ } -+} -+ -+static void configure_encoder( -+ struct link_encoder *enc, -+ enum engine_id engine, -+ const struct link_settings *link_settings) -+{ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* set number of lanes */ -+ addr = mmDP_CONFIG + enc->be_engine_offset; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, link_settings->lane_count - LANE_COUNT_ONE, -+ DP_CONFIG, DP_UDI_LANES); -+ dal_write_reg(enc->ctx, addr, value); -+ -+} -+ -+static bool is_panel_powered_on(struct link_encoder *link_enc) -+{ -+ uint32_t value; -+ bool ret; -+ -+ value = dal_read_reg(link_enc->ctx, -+ mmLVTMA_PWRSEQ_STATE); -+ -+ ret = get_reg_field_value(value, -+ LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R); -+ -+ return ret == 1; -+} -+ -+/* -+ * @brief -+ * eDP only. Control the power of the eDP panel. -+ */ -+static enum encoder_result link_encoder_edp_power_control( -+ struct link_encoder *link_enc, -+ bool power_up) -+{ -+ struct bp_transmitter_control cntl = { 0 }; -+ enum bp_result bp_result; -+ -+ if (dal_graphics_object_id_get_connector_id(link_enc->connector) != -+ CONNECTOR_ID_EDP) { -+ BREAK_TO_DEBUGGER(); -+ return ENCODER_RESULT_ERROR; -+ } -+ -+ if ((power_up && !is_panel_powered_on(link_enc)) || -+ (!power_up && is_panel_powered_on(link_enc))) { -+ -+ /* Send VBIOS command to prompt eDP panel power */ -+ -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: Panel Power action: %s\n", -+ __func__, (power_up ? "On":"Off")); -+ -+ cntl.action = power_up ? -+ TRANSMITTER_CONTROL_POWER_ON : -+ TRANSMITTER_CONTROL_POWER_OFF; -+ cntl.transmitter = link_enc->transmitter; -+ cntl.connector_obj_id = link_enc->connector; -+ cntl.coherent = false; -+ cntl.lanes_number = LANE_COUNT_FOUR; -+ cntl.hpd_sel = link_enc->hpd_source; -+ -+ bp_result = dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ link_enc->adapter_service), &cntl); -+ -+ if (BP_RESULT_OK != bp_result) { -+ -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: Panel Power bp_result: %d\n", -+ __func__, bp_result); -+ } -+ } else { -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: Skipping Panel Power action: %s\n", -+ __func__, (power_up ? "On":"Off")); -+ } -+ -+ return ENCODER_RESULT_OK; -+} -+ -+/* -+ * @brief -+ * eDP only. -+ */ -+static void link_encoder_edp_wait_for_hpd_ready( -+ struct link_encoder *link_enc, -+ struct graphics_object_id connector, -+ bool power_up) -+{ -+ struct adapter_service *as = link_enc->adapter_service; -+ struct irq *hpd; -+ bool edp_hpd_high = false; -+ uint32_t time_elapsed = 0; -+ uint32_t timeout = power_up ? -+ PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; -+ -+ if (dal_graphics_object_id_get_connector_id(connector) != -+ CONNECTOR_ID_EDP) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ if (!power_up && dal_adapter_service_is_feature_supported( -+ FEATURE_NO_HPD_LOW_POLLING_VCC_OFF)) -+ /* from KV, we will not HPD low after turning off VCC - -+ * instead, we will check the SW timer in power_up(). */ -+ return; -+ -+ /* when we power on/off the eDP panel, -+ * we need to wait until SENSE bit is high/low */ -+ -+ /* obtain HPD */ -+ -+ hpd = dal_adapter_service_obtain_hpd_irq(as, connector); -+ -+ if (!hpd) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ dal_irq_open(hpd); -+ -+ /* wait until timeout or panel detected */ -+ -+ do { -+ uint32_t detected = 0; -+ -+ dal_irq_get_value(hpd, &detected); -+ -+ if (!(detected ^ power_up)) { -+ edp_hpd_high = true; -+ break; -+ } -+ -+ dc_service_sleep_in_milliseconds(link_enc->ctx, HPD_CHECK_INTERVAL); -+ -+ time_elapsed += HPD_CHECK_INTERVAL; -+ } while (time_elapsed < timeout); -+ -+ dal_irq_close(hpd); -+ -+ dal_adapter_service_release_irq(as, hpd); -+ -+ if (false == edp_hpd_high) { -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: wait timed out!\n", __func__); -+ } -+} -+ -+static void aux_initialize( -+ struct link_encoder *link_enc, -+ enum hpd_source_id hpd_source) -+{ -+ uint32_t addr = mmAUX_CONTROL + link_enc->aux_channel_offset; -+ -+ uint32_t value = dal_read_reg(link_enc->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); -+ dal_write_reg(link_enc->ctx, addr, value); -+ -+ addr = mmAUX_DPHY_RX_CONTROL0 + link_enc->aux_channel_offset; -+ value = dal_read_reg(link_enc->ctx, addr); -+ -+ /* 1/4 window (the maximum allowed) */ -+ set_reg_field_value(value, 1, -+ AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW); -+ dal_write_reg(link_enc->ctx, -+ mmAUX_DPHY_RX_CONTROL0 + link_enc->aux_channel_offset, -+ value); -+ -+} -+ -+/*todo: cloned in stream enc, fix*/ -+static bool is_panel_backlight_on(struct link_encoder *link_enc) -+{ -+ uint32_t value; -+ -+ value = dal_read_reg(link_enc->ctx, mmLVTMA_PWRSEQ_CNTL); -+ -+ return get_reg_field_value(value, LVTMA_PWRSEQ_CNTL, LVTMA_BLON); -+} -+ -+/*todo: cloned in stream enc, fix*/ -+/* -+ * @brief -+ * eDP only. Control the backlight of the eDP panel -+ */ -+static enum encoder_result link_encoder_edp_backlight_control( -+ struct link_encoder *link_enc, -+ bool enable) -+{ -+ struct bp_transmitter_control cntl = { 0 }; -+ -+ if (dal_graphics_object_id_get_connector_id(link_enc->connector) -+ != CONNECTOR_ID_EDP) { -+ BREAK_TO_DEBUGGER(); -+ return ENCODER_RESULT_ERROR; -+ } -+ -+ if (enable && is_panel_backlight_on(link_enc)) { -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: panel already powered up. Do nothing.\n", -+ __func__); -+ return ENCODER_RESULT_OK; -+ } -+ -+ if (!enable && !is_panel_powered_on(link_enc)) { -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: panel already powered down. Do nothing.\n", -+ __func__); -+ return ENCODER_RESULT_OK; -+ } -+ -+ /* Send VBIOS command to control eDP panel backlight */ -+ -+ dal_logger_write(link_enc->ctx->logger, -+ LOG_MAJOR_HW_TRACE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ "%s: backlight action: %s\n", -+ __func__, (enable ? "On":"Off")); -+ -+ cntl.action = enable ? -+ TRANSMITTER_CONTROL_BACKLIGHT_ON : -+ TRANSMITTER_CONTROL_BACKLIGHT_OFF; -+ /*cntl.engine_id = ctx->engine;*/ -+ cntl.transmitter = link_enc->transmitter; -+ cntl.connector_obj_id = link_enc->connector; -+ /*todo: unhardcode*/ -+ cntl.lanes_number = LANE_COUNT_FOUR; -+ cntl.hpd_sel = link_enc->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); */ -+ -+ dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ link_enc->adapter_service), &cntl); -+ -+ return ENCODER_RESULT_OK; -+} -+ -+/* -+ * @brief -+ * Configure digital transmitter and enable both encoder and transmitter -+ * Actual output will be available after calling unblank() -+ */ -+enum encoder_result dce110_link_encoder_enable_output( -+ struct link_encoder *enc, -+ const struct link_settings *link_settings, -+ enum engine_id engine, -+ enum clock_source_id clock_source, -+ enum signal_type signal, -+ enum dc_color_depth color_depth, -+ uint32_t pixel_clock) -+{ -+ struct bp_transmitter_control cntl = { 0 }; -+ -+ if (enc->connector.id == CONNECTOR_ID_EDP) { -+ /* power up eDP panel */ -+ -+ link_encoder_edp_power_control( -+ enc, true); -+ -+ link_encoder_edp_wait_for_hpd_ready( -+ enc, enc->connector, true); -+ -+ /* have to turn off the backlight -+ * before power down eDP panel */ -+ link_encoder_edp_backlight_control( -+ enc, true); -+ } -+ -+ /* 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. */ -+ if (dc_is_dp_signal(signal)) -+ configure_encoder(enc, engine, link_settings); -+ -+ cntl.action = TRANSMITTER_CONTROL_ENABLE; -+ cntl.engine_id = engine; -+ cntl.transmitter = enc->transmitter; -+ cntl.pll_id = clock_source; -+ cntl.signal = signal; -+ cntl.lanes_number = link_settings->lane_count; -+ cntl.hpd_sel = enc->hpd_source; -+ if (dc_is_dp_signal(signal)) -+ cntl.pixel_clock = link_settings->link_rate -+ * LINK_RATE_REF_FREQ_IN_KHZ; -+ else -+ cntl.pixel_clock = pixel_clock; -+ cntl.color_depth = color_depth; -+ -+ if (DELAY_AFTER_PIXEL_FORMAT_CHANGE) -+ dc_service_sleep_in_milliseconds( -+ enc->ctx, -+ DELAY_AFTER_PIXEL_FORMAT_CHANGE); -+ -+ dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ enc->adapter_service), -+ &cntl); -+ -+ return ENCODER_RESULT_OK; -+} -+ -+static bool is_dig_enabled(const struct link_encoder *link_enc) -+{ -+ uint32_t value; -+ -+ value = dal_read_reg(link_enc->ctx, -+ mmDIG_BE_EN_CNTL + link_enc->be_engine_offset); -+ -+ return get_reg_field_value(value, DIG_BE_EN_CNTL, DIG_ENABLE); -+} -+ -+static void link_encoder_disable(struct link_encoder *link_enc) -+{ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* reset training pattern */ -+ addr = mmDP_DPHY_TRAINING_PATTERN_SEL + link_enc->be_engine_offset; -+ value = dal_read_reg(link_enc->ctx, addr); -+ set_reg_field_value(value, 0, -+ DP_DPHY_TRAINING_PATTERN_SEL, -+ DPHY_TRAINING_PATTERN_SEL); -+ dal_write_reg(link_enc->ctx, addr, value); -+ -+ /* reset training complete */ -+ addr = mmDP_LINK_CNTL + link_enc->be_engine_offset; -+ value = dal_read_reg(link_enc->ctx, addr); -+ set_reg_field_value(value, 0, DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE); -+ dal_write_reg(link_enc->ctx, addr, value); -+ -+ /* reset panel mode */ -+ addr = mmDP_DPHY_INTERNAL_CTRL + link_enc->be_engine_offset; -+ value = 0; -+ dal_write_reg(link_enc->ctx, addr, value); -+} -+ -+/* -+ * @brief -+ * Disable transmitter and its encoder -+ */ -+enum encoder_result dce110_link_encoder_disable_output( -+ struct link_encoder *link_enc, -+ enum signal_type signal) -+{ -+ struct bp_transmitter_control cntl = { 0 }; -+ -+ if (link_enc->connector.id == CONNECTOR_ID_EDP) { -+ /* have to turn off the backlight -+ * before power down eDP panel */ -+ link_encoder_edp_backlight_control( -+ link_enc, false); -+ } -+ -+ if (!is_dig_enabled(link_enc) && -+ dal_adapter_service_should_optimize(link_enc->adapter_service, -+ OF_SKIP_POWER_DOWN_INACTIVE_ENCODER)) { -+ return ENCODER_RESULT_OK; -+ } -+ /* 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 = link_enc->transmitter; -+ cntl.hpd_sel = link_enc->hpd_source; -+ cntl.signal = signal; -+ cntl.connector_obj_id = link_enc->connector; -+ -+ dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ link_enc->adapter_service), &cntl); -+ -+ /* disable encoder */ -+ if (dc_is_dp_signal(signal)) -+ link_encoder_disable(link_enc); -+ -+ if (link_enc->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); */ -+ } -+ -+ return ENCODER_RESULT_OK; -+} -+ -+static void hpd_initialize( -+ struct link_encoder *enc, -+ enum hpd_source_id hpd_source) -+{ -+ /* Associate HPD with DIG_BE */ -+ const uint32_t addr = mmDIG_BE_CNTL + enc->be_engine_offset; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value(value, hpd_source, DIG_BE_CNTL, DIG_HPD_SELECT); -+ dal_write_reg(enc->ctx, addr, value); -+} -+ -+enum encoder_result dce110_link_encoder_power_up( -+ struct link_encoder *enc) -+{ -+ struct bp_transmitter_control cntl = { 0 }; -+ -+ enum bp_result result; -+ -+ cntl.action = TRANSMITTER_CONTROL_INIT; -+ cntl.engine_id = ENGINE_ID_UNKNOWN; -+ cntl.transmitter = enc->transmitter; -+ cntl.connector_obj_id = enc->connector; -+ cntl.lanes_number = LANE_COUNT_FOUR; -+ cntl.coherent = false; -+ cntl.hpd_sel = enc->hpd_source; -+ -+ result = dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ enc->adapter_service), -+ &cntl); -+ -+ if (result != BP_RESULT_OK) { -+ dal_logger_write(enc->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_ENCODER, -+ "%s: Failed to execute VBIOS command table!\n", -+ __func__); -+ BREAK_TO_DEBUGGER(); -+ return ENCODER_RESULT_ERROR; -+ } -+ -+ if (enc->connector.id == CONNECTOR_ID_LVDS) { -+ cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; -+ -+ result = dal_bios_parser_transmitter_control( -+ dal_adapter_service_get_bios_parser( -+ enc->adapter_service), -+ &cntl); -+ ASSERT(result == BP_RESULT_OK); -+ -+ } else if (enc->connector.id == CONNECTOR_ID_EDP) { -+ link_encoder_edp_power_control(enc, true); -+ -+ link_encoder_edp_wait_for_hpd_ready( -+ enc, enc->connector, true); -+ -+ } -+ aux_initialize(enc, enc->hpd_source); -+ -+ /* 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(enc, enc->hpd_source); -+ -+ return ENCODER_RESULT_OK; -+} -+ -+ -+static bool validate_dvi_output( -+ const struct link_encoder *enc, -+ 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 (enc->features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) -+ max_pixel_clock = enc->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 = enc->features.max_pixel_clock; -+ -+ /* DVI only support RGB pixel encoding */ -+ if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) -+ return false; -+ -+ if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) -+ return false; -+ -+ if (crtc_timing->pix_clk_khz > max_pixel_clock) -+ return false; -+ -+ /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ -+ switch (crtc_timing->display_color_depth) { -+ case COLOR_DEPTH_666: -+ case COLOR_DEPTH_888: -+ break; -+ case COLOR_DEPTH_101010: -+ case COLOR_DEPTH_161616: -+ if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) -+ return false; -+ break; -+ default: -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool validate_hdmi_output( -+ const struct link_encoder *enc, -+ const struct dc_crtc_timing *crtc_timing, -+ uint32_t max_tmds_clk_from_edid_in_mhz, -+ enum dc_color_depth max_hdmi_deep_color, -+ uint32_t max_hdmi_pixel_clock) -+{ -+ enum dc_color_depth max_deep_color = max_hdmi_deep_color; -+ -+ /* expressed in KHz */ -+ uint32_t pixel_clock = 0; -+ -+ if (max_deep_color > enc->features.max_deep_color) -+ max_deep_color = enc->features.max_deep_color; -+ -+ if (max_deep_color < crtc_timing->display_color_depth) -+ return false; -+ -+ if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) -+ return false; -+ -+ switch (crtc_timing->display_color_depth) { -+ case COLOR_DEPTH_666: -+ pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 2; -+ break; -+ case COLOR_DEPTH_888: -+ pixel_clock = crtc_timing->pix_clk_khz; -+ break; -+ case COLOR_DEPTH_101010: -+ pixel_clock = (crtc_timing->pix_clk_khz * 10) >> 3; -+ break; -+ case COLOR_DEPTH_121212: -+ pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 1; -+ break; -+ case COLOR_DEPTH_161616: -+ pixel_clock = crtc_timing->pix_clk_khz << 1; -+ break; -+ default: -+ break; -+ } -+ -+ if (max_tmds_clk_from_edid_in_mhz > 0) -+ if (pixel_clock > max_tmds_clk_from_edid_in_mhz * 1000) -+ return false; -+ -+ if ((pixel_clock == 0) || -+ (pixel_clock > max_hdmi_pixel_clock) || -+ (pixel_clock > enc->features.max_pixel_clock)) -+ return false; -+ -+ /* -+ * Restriction: allow non-CE mode (IT mode) to support RGB only. -+ * When it is IT mode, the format mode will be 0, -+ * but currently the code is broken, -+ * VIDEO FORMAT is always 0 in validatepathMode(). -+ * Due to overscan change - need fix there and test the impact - to do. -+ */ -+ if (crtc_timing->timing_standard != TIMING_STANDARD_CEA861 && -+ crtc_timing->timing_standard != TIMING_STANDARD_HDMI) -+ if (crtc_timing->pixel_encoding != -+ PIXEL_ENCODING_RGB) -+ return false; -+ -+ return true; -+} -+ -+static bool validate_rgb_output( -+ const struct link_encoder *enc, -+ const struct dc_crtc_timing *crtc_timing) -+{ -+ if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) -+ return false; -+ -+ if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) -+ return false; -+ -+ return true; -+} -+ -+static bool validate_dp_output( -+ const struct link_encoder *enc, -+ const struct dc_crtc_timing *crtc_timing) -+{ -+ if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) -+ return false; -+ -+ /* default RGB only */ -+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) -+ return true; -+ -+ if (enc->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 && -+ enc->features.flags.bits.IS_YCBCR_CAPABLE && -+ crtc_timing->display_color_depth != COLOR_DEPTH_666) -+ return true; -+ -+ return false; -+} -+ -+static bool validate_wireless_output( -+ const struct link_encoder *enc, -+ const struct dc_crtc_timing *crtc_timing) -+{ -+ if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) -+ return false; -+ -+ /* Wireless only supports YCbCr444 */ -+ if (crtc_timing->pixel_encoding == -+ PIXEL_ENCODING_YCBCR444) -+ return true; -+ -+ return false; -+} -+ -+enum encoder_result dce110_link_encoder_validate_output_with_stream( -+ struct link_encoder *enc, -+ const struct core_stream *stream) -+{ -+ bool is_valid; -+ -+ switch (stream->signal) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ is_valid = validate_dvi_output( -+ enc, -+ stream->sink->link->public.connector_signal, -+ stream->signal, -+ &stream->public.timing); -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ is_valid = validate_hdmi_output( -+ enc, -+ &stream->public.timing, -+ stream->max_tmds_clk_from_edid_in_mhz, -+ stream->max_hdmi_deep_color, -+ stream->max_hdmi_pixel_clock); -+ break; -+ case SIGNAL_TYPE_RGB: -+ is_valid = validate_rgb_output( -+ enc, &stream->public.timing); -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ is_valid = validate_dp_output( -+ enc, &stream->public.timing); -+ break; -+ case SIGNAL_TYPE_WIRELESS: -+ is_valid = validate_wireless_output( -+ enc, &stream->public.timing); -+ break; -+ default: -+ is_valid = true; -+ break; -+ } -+ -+ return is_valid ? ENCODER_RESULT_OK : ENCODER_RESULT_ERROR; -+} -+ -+/* -+ * get_supported_stream_engines -+ * -+ * @brief -+ * get a list of supported engine -+ * -+ * @param -+ * const struct encoder_impl *enc - not used. -+ * -+ * @return -+ * list of engines with supported ones enabled. -+ */ -+union supported_stream_engines dce110_get_supported_stream_engines( -+ const struct link_encoder *enc) -+{ -+ union supported_stream_engines result = {.u_all = 0}; -+ -+ result.engine.ENGINE_ID_DIGA = 1; -+ result.engine.ENGINE_ID_DIGB = 1; -+ result.engine.ENGINE_ID_DIGC = 1; -+ -+ if (enc->connector.id == CONNECTOR_ID_EDP /*|| wireless*/) -+ result.u_all = (1 << enc->preferred_engine); -+ -+ return result; -+} -+ -+void dce110_link_encoder_set_lcd_backlight_level( -+ struct link_encoder *enc, -+ uint32_t level) -+{ -+ struct dc_context *ctx = enc->ctx; -+ -+ const uint32_t backlight_update_pending_max_retry = 1000; -+ -+ uint32_t backlight; -+ uint32_t backlight_period; -+ uint32_t backlight_lock; -+ -+ uint32_t i; -+ uint32_t backlight_24bit; -+ uint32_t backlight_17bit; -+ uint32_t backlight_16bit; -+ uint32_t masked_pwm_period; -+ uint8_t rounding_bit; -+ uint8_t bit_count; -+ uint64_t active_duty_cycle; -+ -+ backlight = dal_read_reg(ctx, mmBL_PWM_CNTL); -+ backlight_period = dal_read_reg(ctx, mmBL_PWM_PERIOD_CNTL); -+ backlight_lock = dal_read_reg(ctx, mmBL_PWM_GRP1_REG_LOCK); -+ -+ /* -+ * 1. Convert 8-bit value to 17 bit U1.16 format -+ * (1 integer, 16 fractional bits) -+ */ -+ -+ /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, -+ * effectively multiplying value by 256/255 -+ * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF -+ */ -+ backlight_24bit = level * 0x10101; -+ -+ /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 -+ * used for rounding, take most significant bit of fraction for -+ * rounding, e.g. for 0xEFEFEF, rounding bit is 1 -+ */ -+ rounding_bit = (backlight_24bit >> 7) & 1; -+ -+ /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit -+ * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 -+ */ -+ backlight_17bit = (backlight_24bit >> 8) + rounding_bit; -+ -+ /* -+ * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight -+ * active duty cycle <= backlight period -+ */ -+ -+ /* 2.1 Apply bitmask for backlight period value based on value of BITCNT -+ */ -+ { -+ uint32_t pwm_period_bitcnt = get_reg_field_value( -+ backlight_period, -+ BL_PWM_PERIOD_CNTL, -+ BL_PWM_PERIOD_BITCNT); -+ if (pwm_period_bitcnt == 0) -+ bit_count = 16; -+ else -+ bit_count = pwm_period_bitcnt; -+ } -+ -+ /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ -+ masked_pwm_period = -+ get_reg_field_value( -+ backlight_period, -+ BL_PWM_PERIOD_CNTL, -+ BL_PWM_PERIOD) & ((1 << bit_count) - 1); -+ -+ /* 2.2 Calculate integer active duty cycle required upper 16 bits -+ * contain integer component, lower 16 bits contain fractional component -+ * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 -+ */ -+ active_duty_cycle = backlight_17bit * masked_pwm_period; -+ -+ /* 2.3 Calculate 16 bit active duty cycle from integer and fractional -+ * components shift by bitCount then mask 16 bits and add rounding bit -+ * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 -+ */ -+ backlight_16bit = active_duty_cycle >> bit_count; -+ backlight_16bit &= 0xFFFF; -+ backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; -+ set_reg_field_value( -+ backlight, -+ backlight_16bit, -+ BL_PWM_CNTL, -+ BL_ACTIVE_INT_FRAC_CNT); -+ -+ /* -+ * 3. Program register with updated value -+ */ -+ -+ /* 3.1 Lock group 2 backlight registers */ -+ set_reg_field_value( -+ backlight_lock, -+ 1, -+ BL_PWM_GRP1_REG_LOCK, -+ BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN); -+ set_reg_field_value( -+ backlight_lock, -+ 1, -+ BL_PWM_GRP1_REG_LOCK, -+ BL_PWM_GRP1_REG_LOCK); -+ dal_write_reg(ctx, mmBL_PWM_GRP1_REG_LOCK, backlight_lock); -+ -+ /* 3.2 Write new active duty cycle */ -+ dal_write_reg(ctx, mmBL_PWM_CNTL, backlight); -+ -+ /* 3.3 Unlock group 2 backlight registers */ -+ set_reg_field_value( -+ backlight_lock, -+ 0, -+ BL_PWM_GRP1_REG_LOCK, -+ BL_PWM_GRP1_REG_LOCK); -+ dal_write_reg(ctx, mmBL_PWM_GRP1_REG_LOCK, backlight_lock); -+ -+ /* 5.4.4 Wait for pending bit to be cleared */ -+ for (i = 0; i < backlight_update_pending_max_retry; ++i) { -+ backlight_lock = dal_read_reg(ctx, mmBL_PWM_GRP1_REG_LOCK); -+ if (!get_reg_field_value( -+ backlight_lock, -+ BL_PWM_GRP1_REG_LOCK, -+ BL_PWM_GRP1_REG_UPDATE_PENDING)) -+ break; -+ -+ dc_service_delay_in_microseconds(ctx, 10); -+ } -+} -+ -+/*TODO: move to correct dce specific file*/ -+/** -+* set_afmt_memory_power_state -+* -+* @brief -+* Power up audio formatter memory that is mapped to specified DIG -+*/ -+void dce110_set_afmt_memory_power_state( -+ const struct dc_context *ctx, -+ enum engine_id id, -+ bool enable) -+{ -+ uint32_t value; -+ uint32_t mem_pwr_force; -+ -+ value = dal_read_reg(ctx, mmDCO_MEM_PWR_CTRL); -+ -+ if (enable) -+ mem_pwr_force = 0; -+ else -+ mem_pwr_force = 3; -+ -+ /* force shutdown mode for appropriate AFMT memory */ -+ switch (id) { -+ case ENGINE_ID_DIGA: -+ set_reg_field_value( -+ value, -+ mem_pwr_force, -+ DCO_MEM_PWR_CTRL, -+ HDMI0_MEM_PWR_FORCE); -+ break; -+ case ENGINE_ID_DIGB: -+ set_reg_field_value( -+ value, -+ mem_pwr_force, -+ DCO_MEM_PWR_CTRL, -+ HDMI1_MEM_PWR_FORCE); -+ break; -+ case ENGINE_ID_DIGC: -+ set_reg_field_value( -+ value, -+ mem_pwr_force, -+ DCO_MEM_PWR_CTRL, -+ HDMI2_MEM_PWR_FORCE); -+ break; -+ default: -+ dal_logger_write( -+ ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_ENCODER, -+ "%s: Invalid Engine Id\n", -+ __func__); -+ break; -+ } -+ -+ dal_write_reg(ctx, mmDCO_MEM_PWR_CTRL, value); -+} -+ -+void dce110_link_encoder_update_mst_stream_allocation_table( -+ struct link_encoder *enc, -+ const struct dp_mst_stream_allocation_table *table, -+ bool is_removal) -+{ -+ int32_t addr_offset = enc->be_engine_offset; -+ uint32_t value0; -+ uint32_t value1; -+ 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 */ -+ -+ value0 = dal_read_reg(enc->ctx, mmDP_MSE_SAT0 + addr_offset); -+ value1 = dal_read_reg(enc->ctx, mmDP_MSE_SAT1 + addr_offset); -+ -+ if (table->stream_count >= 1) { -+ set_reg_field_value( -+ value0, -+ table->stream_allocations[0].engine, -+ DP_MSE_SAT0, -+ DP_MSE_SAT_SRC0); -+ -+ set_reg_field_value( -+ value0, -+ table->stream_allocations[0].slot_count, -+ DP_MSE_SAT0, -+ DP_MSE_SAT_SLOT_COUNT0); -+ } -+ -+ if (table->stream_count >= 2) { -+ set_reg_field_value( -+ value0, -+ table->stream_allocations[1].engine, -+ DP_MSE_SAT0, -+ DP_MSE_SAT_SRC1); -+ -+ set_reg_field_value( -+ value0, -+ table->stream_allocations[1].slot_count, -+ DP_MSE_SAT0, -+ DP_MSE_SAT_SLOT_COUNT1); -+ } -+ -+ if (table->stream_count >= 3) { -+ set_reg_field_value( -+ value1, -+ table->stream_allocations[2].engine, -+ DP_MSE_SAT1, -+ DP_MSE_SAT_SRC2); -+ -+ set_reg_field_value( -+ value1, -+ table->stream_allocations[2].slot_count, -+ DP_MSE_SAT1, -+ DP_MSE_SAT_SLOT_COUNT2); -+ } -+ -+ /* update ASIC MSE stream allocation table */ -+ dal_write_reg(enc->ctx, mmDP_MSE_SAT0 + addr_offset, value0); -+ dal_write_reg(enc->ctx, mmDP_MSE_SAT1 + addr_offset, value1); -+ -+ /* --- wait for transaction finish */ -+ -+ /* send allocation change trigger (ACT) ? -+ * this step first sends the ACT, -+ * then double buffers the SAT into the hardware -+ * making the new allocation active on the DP MST mode link */ -+ -+ value0 = dal_read_reg(enc->ctx, mmDP_MSE_SAT_UPDATE + addr_offset); -+ -+ /* DP_MSE_SAT_UPDATE: -+ * 0 - No Action -+ * 1 - Update SAT with trigger -+ * 2 - Update SAT without trigger */ -+ -+ set_reg_field_value( -+ value0, -+ 1, -+ DP_MSE_SAT_UPDATE, -+ DP_MSE_SAT_UPDATE); -+ -+ dal_write_reg(enc->ctx, mmDP_MSE_SAT_UPDATE + addr_offset, value0); -+ -+ /* wait for update to complete -+ * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) -+ * then wait for the transmission -+ * of at least 16 MTP headers on immediate local link. -+ * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 -+ * a value of 1 indicates that DP MST mode -+ * is in the 16 MTP keepout region after a VC has been added. -+ * MST stream bandwidth (VC rate) can be configured -+ * after this bit is cleared */ -+ -+ do { -+ dc_service_delay_in_microseconds(enc->ctx, 10); -+ -+ value0 = dal_read_reg(enc->ctx, -+ mmDP_MSE_SAT_UPDATE + addr_offset); -+ -+ value1 = get_reg_field_value( -+ value0, -+ DP_MSE_SAT_UPDATE, -+ DP_MSE_16_MTP_KEEPOUT); -+ -+ /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ -+ if (value1) -+ break; -+ ++retries; -+ } while (retries < DP_MST_UPDATE_MAX_RETRY); -+ -+ /* TODO should not need. clean this after light up -+ * if (is_removal) -+ * dal_write_reg(enc->ctx, addr, value); -+ */ -+} -+ -+void dce110_link_encoder_set_mst_bandwidth( -+ struct link_encoder *enc, -+ enum engine_id engine, -+ struct fixed31_32 avg_time_slots_per_mtp) -+{ -+ 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)); -+ -+ { -+ const uint32_t addr = mmDP_MSE_RATE_CNTL + -+ fe_engine_offsets[engine]; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ x, -+ DP_MSE_RATE_CNTL, -+ DP_MSE_RATE_X); -+ -+ set_reg_field_value( -+ value, -+ y, -+ DP_MSE_RATE_CNTL, -+ DP_MSE_RATE_Y); -+ -+ dal_write_reg(enc->ctx, addr, value); -+ } -+ -+ /* wait for update to be completed on the link -+ * i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) -+ * is reset to 0 (not pending) */ -+ { -+ const uint32_t addr = mmDP_MSE_RATE_UPDATE + -+ fe_engine_offsets[engine]; -+ uint32_t value, field; -+ uint32_t retries = 0; -+ -+ do { -+ value = dal_read_reg(enc->ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ DP_MSE_RATE_UPDATE, -+ DP_MSE_RATE_UPDATE_PENDING); -+ -+ if (!(field & -+ DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK)) -+ break; -+ -+ dc_service_delay_in_microseconds(enc->ctx, 10); -+ -+ ++retries; -+ } while (retries < DP_MST_UPDATE_MAX_RETRY); -+ } -+} -+ -+void dce110_link_encoder_connect_dig_be_to_fe( -+ struct link_encoder *enc, -+ enum engine_id engine, -+ bool connect) -+{ -+ uint32_t addr; -+ uint32_t value; -+ uint32_t field; -+ -+ if (engine != ENGINE_ID_UNKNOWN) { -+ addr = mmDIG_BE_CNTL + enc->be_engine_offset; -+ value = dal_read_reg(enc->ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ DIG_BE_CNTL, -+ DIG_FE_SOURCE_SELECT); -+ -+ if (connect) -+ field |= get_frontend_source(engine); -+ else -+ field &= ~get_frontend_source(engine); -+ -+ set_reg_field_value( -+ value, -+ field, -+ DIG_BE_CNTL, -+ DIG_FE_SOURCE_SELECT); -+ dal_write_reg(enc->ctx, addr, value); -+ } -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h -new file mode 100644 -index 0000000..4331bf0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h -@@ -0,0 +1,91 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_LINK_ENCODER__DCE110_H__ -+#define __DC_LINK_ENCODER__DCE110_H__ -+ -+struct link_encoder *dce110_link_encoder_create( -+ const struct encoder_init_data *init); -+void dce110_link_encoder_destroy(struct link_encoder **enc); -+ -+void dce110_link_encoder_set_dp_phy_pattern( -+ struct link_encoder *enc, -+ const struct encoder_set_dp_phy_pattern_param *param); -+ -+enum encoder_result dce110_link_encoder_power_up(struct link_encoder *enc); -+ -+enum encoder_result dce110_link_encoder_dp_set_lane_settings( -+ struct link_encoder *enc, -+ const struct link_training_settings *link_settings); -+ -+union supported_stream_engines dce110_get_supported_stream_engines( -+ const struct link_encoder *enc); -+ -+enum encoder_result dce110_link_encoder_validate_output_with_stream( -+ struct link_encoder *enc, -+ const struct core_stream *stream); -+ -+void dce110_link_encoder_set_lcd_backlight_level( -+ struct link_encoder *enc, -+ uint32_t level); -+ -+void dce110_link_encoder_setup( -+ struct link_encoder *enc, -+ enum signal_type signal); -+ -+enum encoder_result dce110_link_encoder_enable_output( -+ struct link_encoder *enc, -+ const struct link_settings *link_settings, -+ enum engine_id engine, -+ enum clock_source_id clock_source, -+ enum signal_type signal, -+ enum dc_color_depth color_depth, -+ uint32_t pixel_clock); -+ -+enum encoder_result dce110_link_encoder_disable_output( -+ struct link_encoder *link_enc, -+ enum signal_type signal); -+ -+void dce110_set_afmt_memory_power_state( -+ const struct dc_context *ctx, -+ enum engine_id id, -+ bool enable); -+ -+void dce110_link_encoder_update_mst_stream_allocation_table( -+ struct link_encoder *enc, -+ const struct dp_mst_stream_allocation_table *table, -+ bool is_removal); -+ -+void dce110_link_encoder_set_mst_bandwidth( -+ struct link_encoder *enc, -+ enum engine_id engine, -+ struct fixed31_32 avg_time_slots_per_mtp); -+ -+void dce110_link_encoder_connect_dig_be_to_fe( -+ struct link_encoder *enc, -+ enum engine_id engine, -+ bool connect); -+ -+#endif /* __DC_LINK_ENCODER__DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c -new file mode 100644 -index 0000000..7391a0a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c -@@ -0,0 +1,969 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+/* TODO: this needs to be looked at, used by Stella's workaround*/ -+#include "gmc/gmc_8_2_d.h" -+#include "gmc/gmc_8_2_sh_mask.h" -+ -+#include "include/logger_interface.h" -+#include "adapter_service_interface.h" -+#include "inc/bandwidth_calcs.h" -+ -+#include "dce110_mem_input.h" -+ -+#define MAX_WATERMARK 0xFFFF -+#define SAFE_NBP_MARK 0x7FFF -+ -+#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -+#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -+#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) -+ -+static const struct dce110_mem_input_reg_offsets reg_offsets[] = { -+{ -+ .dcp = 0, -+ .dmif = 0, -+ .pipe = 0, -+}, -+{ -+ .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL -+ - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - mmPIPE0_DMIF_BUFFER_CONTROL), -+}, -+{ -+ .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL -+ - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), -+ .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - mmPIPE0_DMIF_BUFFER_CONTROL), -+} -+}; -+ -+static void set_flip_control( -+ struct dce110_mem_input *mem_input110, -+ bool immediate) -+{ -+ uint32_t value = 0; -+ -+ value = dal_read_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_FLIP_CONTROL)); -+ set_reg_field_value(value, 0, -+ GRPH_FLIP_CONTROL, -+ GRPH_SURFACE_UPDATE_IMMEDIATE_EN); -+ set_reg_field_value(value, 0, -+ GRPH_FLIP_CONTROL, -+ GRPH_SURFACE_UPDATE_H_RETRACE_EN); -+ if (immediate == true) -+ set_reg_field_value(value, 1, -+ GRPH_FLIP_CONTROL, -+ GRPH_SURFACE_UPDATE_IMMEDIATE_EN); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_FLIP_CONTROL), -+ value); -+} -+ -+static void program_sec_addr( -+ struct dce110_mem_input *mem_input110, -+ PHYSICAL_ADDRESS_LOC address) -+{ -+ uint32_t value = 0; -+ uint32_t temp = 0; -+ /*high register MUST be programmed first*/ -+ temp = address.high_part & -+GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; -+ -+ set_reg_field_value(value, temp, -+ GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, -+ GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), -+ value); -+ -+ temp = 0; -+ value = 0; -+ temp = address.low_part >> -+ GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; -+ -+ set_reg_field_value(value, temp, -+ GRPH_SECONDARY_SURFACE_ADDRESS, -+ GRPH_SECONDARY_SURFACE_ADDRESS); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), -+ value); -+} -+ -+static void program_pri_addr( -+ struct dce110_mem_input *mem_input110, -+ PHYSICAL_ADDRESS_LOC address) -+{ -+ uint32_t value = 0; -+ uint32_t temp = 0; -+ -+ /*high register MUST be programmed first*/ -+ temp = address.high_part & -+GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; -+ -+ set_reg_field_value(value, temp, -+ GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, -+ GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), -+ value); -+ -+ temp = 0; -+ value = 0; -+ temp = address.low_part >> -+ GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; -+ -+ set_reg_field_value(value, temp, -+ GRPH_PRIMARY_SURFACE_ADDRESS, -+ GRPH_PRIMARY_SURFACE_ADDRESS); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), -+ value); -+} -+ -+static void program_addr( -+ struct dce110_mem_input *mem_input110, -+ const struct dc_plane_address *addr) -+{ -+ switch (addr->type) { -+ case PLN_ADDR_TYPE_GRAPHICS: -+ program_pri_addr( -+ mem_input110, -+ addr->grph.addr); -+ break; -+ case PLN_ADDR_TYPE_GRPH_STEREO: -+ program_pri_addr( -+ mem_input110, -+ addr->grph_stereo.left_addr); -+ program_sec_addr( -+ mem_input110, -+ addr->grph_stereo.right_addr); -+ break; -+ case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: -+ case PLN_ADDR_TYPE_VIDEO_INTERLACED: -+ case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE_STEREO: -+ case PLN_ADDR_TYPE_VIDEO_INTERLACED_STEREO: -+ default: -+ /* not supported */ -+ BREAK_TO_DEBUGGER(); -+ } -+} -+ -+static void enable(struct dce110_mem_input *mem_input110) -+{ -+ uint32_t value = 0; -+ -+ value = dal_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_ENABLE)); -+ set_reg_field_value(value, 1, GRPH_ENABLE, GRPH_ENABLE); -+ dal_write_reg(mem_input110->base.ctx, -+ DCP_REG(mmGRPH_ENABLE), -+ value); -+} -+ -+static void program_tiling( -+ struct dce110_mem_input *mem_input110, -+ const union plane_tiling_info *info, -+ const enum surface_pixel_format pixel_format) -+{ -+ uint32_t value = 0; -+ -+ value = dal_read_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_CONTROL)); -+ -+ set_reg_field_value(value, info->grph.NUM_BANKS, -+ GRPH_CONTROL, GRPH_NUM_BANKS); -+ -+ set_reg_field_value(value, info->grph.BANK_WIDTH, -+ GRPH_CONTROL, GRPH_BANK_WIDTH); -+ -+ set_reg_field_value(value, info->grph.BANK_HEIGHT, -+ GRPH_CONTROL, GRPH_BANK_HEIGHT); -+ -+ set_reg_field_value(value, info->grph.TILE_ASPECT, -+ GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT); -+ -+ set_reg_field_value(value, info->grph.TILE_SPLIT, -+ GRPH_CONTROL, GRPH_TILE_SPLIT); -+ -+ set_reg_field_value(value, info->grph.TILE_MODE, -+ GRPH_CONTROL, GRPH_MICRO_TILE_MODE); -+ -+ set_reg_field_value(value, info->grph.PIPE_CONFIG, -+ GRPH_CONTROL, GRPH_PIPE_CONFIG); -+ -+ set_reg_field_value(value, info->grph.ARRAY_MODE, -+ GRPH_CONTROL, GRPH_ARRAY_MODE); -+ -+ set_reg_field_value(value, 1, -+ GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); -+ -+ set_reg_field_value(value, 0, -+ GRPH_CONTROL, GRPH_Z); -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_CONTROL), -+ value); -+} -+ -+static void program_size_and_rotation( -+ struct dce110_mem_input *mem_input110, -+ enum dc_rotation_angle rotation, -+ const union plane_size *plane_size) -+{ -+ uint32_t value = 0; -+ union plane_size local_size = *plane_size; -+ -+ if (rotation == ROTATION_ANGLE_90 || -+ rotation == ROTATION_ANGLE_270) { -+ -+ uint32_t swap; -+ -+ swap = local_size.grph.surface_size.x; -+ local_size.grph.surface_size.x = -+ local_size.grph.surface_size.y; -+ local_size.grph.surface_size.y = swap; -+ -+ swap = local_size.grph.surface_size.width; -+ local_size.grph.surface_size.width = -+ local_size.grph.surface_size.height; -+ local_size.grph.surface_size.height = swap; -+ } -+ -+ set_reg_field_value(value, local_size.grph.surface_size.x, -+ GRPH_X_START, GRPH_X_START); -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_X_START), -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, local_size.grph.surface_size.y, -+ GRPH_Y_START, GRPH_Y_START); -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_Y_START), -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, local_size.grph.surface_size.width, -+ GRPH_X_END, GRPH_X_END); -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_X_END), -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, local_size.grph.surface_size.height, -+ GRPH_Y_END, GRPH_Y_END); -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_Y_END), -+ value); -+ -+ value = 0; -+ set_reg_field_value(value, local_size.grph.surface_pitch, -+ GRPH_PITCH, GRPH_PITCH); -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_PITCH), -+ value); -+ -+ -+ value = 0; -+ switch (rotation) { -+ case ROTATION_ANGLE_90: -+ set_reg_field_value(value, 3, -+ HW_ROTATION, GRPH_ROTATION_ANGLE); -+ break; -+ case ROTATION_ANGLE_180: -+ set_reg_field_value(value, 2, -+ HW_ROTATION, GRPH_ROTATION_ANGLE); -+ break; -+ case ROTATION_ANGLE_270: -+ set_reg_field_value(value, 1, -+ HW_ROTATION, GRPH_ROTATION_ANGLE); -+ break; -+ default: -+ set_reg_field_value(value, 0, -+ HW_ROTATION, GRPH_ROTATION_ANGLE); -+ break; -+ } -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmHW_ROTATION), -+ value); -+} -+ -+static void program_pixel_format( -+ struct dce110_mem_input *mem_input110, -+ enum surface_pixel_format format) -+{ -+ if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && -+ format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { -+ uint32_t value = 0; -+ -+ /* handle colour twizzle formats, swapping R and B */ -+ if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || -+ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || -+ format == -+ SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || -+ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { -+ set_reg_field_value( -+ value, 2, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR); -+ set_reg_field_value( -+ value, 2, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR); -+ } -+ -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_SWAP_CNTL), -+ value); -+ -+ -+ value = dal_read_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_CONTROL)); -+ -+ switch (format) { -+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: -+ set_reg_field_value( -+ value, 0, GRPH_CONTROL, GRPH_DEPTH); -+ set_reg_field_value( -+ value, 0, GRPH_CONTROL, GRPH_FORMAT); -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565: -+ set_reg_field_value( -+ value, 1, GRPH_CONTROL, GRPH_DEPTH); -+ set_reg_field_value( -+ value, 1, GRPH_CONTROL, GRPH_FORMAT); -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: -+ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: -+ set_reg_field_value( -+ value, 2, GRPH_CONTROL, GRPH_DEPTH); -+ set_reg_field_value( -+ value, 0, GRPH_CONTROL, GRPH_FORMAT); -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: -+ set_reg_field_value( -+ value, 2, GRPH_CONTROL, GRPH_DEPTH); -+ set_reg_field_value( -+ value, 1, GRPH_CONTROL, GRPH_FORMAT); -+ break; -+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: -+ set_reg_field_value( -+ value, 3, GRPH_CONTROL, GRPH_DEPTH); -+ set_reg_field_value( -+ value, 0, GRPH_CONTROL, GRPH_FORMAT); -+ break; -+ default: -+ break; -+ } -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmGRPH_CONTROL), -+ value); -+ -+ /*TODO [hwentlan] MOVE THIS TO CONTROLLER GAMMA!!!!!*/ -+ value = dal_read_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmPRESCALE_GRPH_CONTROL)); -+ -+ if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { -+ set_reg_field_value( -+ value, 1, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_SELECT); -+ set_reg_field_value( -+ value, 1, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_R_SIGN); -+ set_reg_field_value( -+ value, 1, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_G_SIGN); -+ set_reg_field_value( -+ value, 1, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_B_SIGN); -+ } else { -+ set_reg_field_value( -+ value, 0, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_SELECT); -+ set_reg_field_value( -+ value, 0, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_R_SIGN); -+ set_reg_field_value( -+ value, 0, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_G_SIGN); -+ set_reg_field_value( -+ value, 0, PRESCALE_GRPH_CONTROL, -+ GRPH_PRESCALE_B_SIGN); -+ } -+ dal_write_reg( -+ mem_input110->base.ctx, -+ DCP_REG(mmPRESCALE_GRPH_CONTROL), -+ value); -+ } -+} -+ -+bool dce110_mem_input_program_surface_flip_and_addr( -+ struct mem_input *mem_input, -+ const struct dc_plane_address *address, -+ bool flip_immediate) -+{ -+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); -+ -+ set_flip_control(mem_input110, flip_immediate); -+ program_addr(mem_input110, -+ address); -+ -+ return true; -+} -+ -+bool dce110_mem_input_program_surface_config( -+ struct mem_input *mem_input, -+ const struct dc_surface *surface) -+{ -+ struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); -+ -+ enable(mem_input110); -+ program_tiling(mem_input110, &surface->tiling_info, surface->format); -+ program_size_and_rotation(mem_input110, -+ surface->rotation, &surface->plane_size); -+ program_pixel_format(mem_input110, surface->format); -+ -+ return true; -+} -+ -+static void program_urgency_watermark( -+ const struct dc_context *ctx, -+ const uint32_t offset, -+ struct bw_watermarks marks_low, -+ uint32_t total_dest_line_time_ns) -+{ -+ /* register value */ -+ uint32_t urgency_cntl = 0; -+ uint32_t wm_mask_cntl = 0; -+ -+ uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; -+ uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ -+ /*Write mask to enable reading/writing of watermark set A*/ -+ wm_mask_cntl = dal_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dal_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dal_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); -+ dal_write_reg(ctx, urgency_addr, urgency_cntl); -+ -+ -+ /*Write mask to enable reading/writing of watermark set B*/ -+ wm_mask_cntl = dal_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ URGENCY_WATERMARK_MASK); -+ dal_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ urgency_cntl = dal_read_reg(ctx, urgency_addr); -+ -+ set_reg_field_value(urgency_cntl, -+ marks_low.b_mark, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_LOW_WATERMARK); -+ -+ set_reg_field_value(urgency_cntl, -+ total_dest_line_time_ns, -+ DPG_PIPE_URGENCY_CONTROL, -+ URGENCY_HIGH_WATERMARK); -+ dal_write_reg(ctx, urgency_addr, urgency_cntl); -+} -+ -+void dce110_program_stutter_watermark( -+ struct mem_input *mi, -+ struct bw_watermarks marks) -+{ -+ const struct dc_context *ctx = mi->ctx; -+ const uint32_t offset = TO_DCE110_MEM_INPUT(mi)->offsets.dmif; -+ /* 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 = dal_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dal_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dal_read_reg(ctx, stutter_addr); -+ -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set A*/ -+ set_reg_field_value(stutter_cntl, -+ marks.a_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dal_write_reg(ctx, stutter_addr, stutter_cntl); -+ -+ /*Write mask to enable reading/writing of watermark set B*/ -+ wm_mask_cntl = dal_read_reg(ctx, wm_addr); -+ set_reg_field_value(wm_mask_cntl, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); -+ dal_write_reg(ctx, wm_addr, wm_mask_cntl); -+ -+ stutter_cntl = dal_read_reg(ctx, stutter_addr); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_ENABLE); -+ set_reg_field_value(stutter_cntl, -+ 1, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_IGNORE_FBC); -+ -+ /*Write watermark set B*/ -+ set_reg_field_value(stutter_cntl, -+ marks.b_mark, -+ DPG_PIPE_STUTTER_CONTROL, -+ STUTTER_EXIT_SELF_REFRESH_WATERMARK); -+ dal_write_reg(ctx, stutter_addr, stutter_cntl); -+} -+ -+void dce110_program_nbp_watermark( -+ struct mem_input *mi, -+ struct bw_watermarks marks) -+{ -+ const struct dc_context *ctx = mi->ctx; -+ const uint32_t offset = TO_DCE110_MEM_INPUT(mi)->offsets.dmif; -+ uint32_t value; -+ uint32_t addr; -+ /* Write mask to enable reading/writing of watermark set A */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dal_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); -+ dal_write_reg(ctx, addr, value); -+ -+ /* Write watermark set A */ -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.a_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dal_write_reg(ctx, addr, value); -+ -+ /* Write mask to enable reading/writing of watermark set B */ -+ addr = offset + mmDPG_WATERMARK_MASK_CONTROL; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ 2, -+ DPG_WATERMARK_MASK_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK_MASK); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; -+ value = dal_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); -+ dal_write_reg(ctx, addr, value); -+ -+ /* Write watermark set B */ -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ marks.b_mark, -+ DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, -+ NB_PSTATE_CHANGE_WATERMARK); -+ dal_write_reg(ctx, addr, value); -+} -+ -+void dce110_program_safe_display_marks(struct mem_input *mi) -+{ -+ struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); -+ struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK }; -+ struct bw_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK }; -+ -+ program_urgency_watermark( -+ mi->ctx, bm_dce110->offsets.dmif, max_marks, MAX_WATERMARK); -+ dce110_program_stutter_watermark(mi, max_marks); -+ dce110_program_nbp_watermark(mi, nbp_marks); -+ -+} -+ -+void dce110_program_urgency_watermark( -+ struct mem_input *mi, -+ struct bw_watermarks marks, -+ uint32_t h_total, -+ uint32_t pixel_clk_in_khz, -+ uint32_t pstate_blackout_duration_ns) -+{ -+ struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); -+ uint32_t total_dest_line_time_ns = 1000000ULL * h_total -+ / pixel_clk_in_khz + pstate_blackout_duration_ns; -+ -+ program_urgency_watermark( -+ mi->ctx, -+ bm_dce110->offsets.dmif, -+ marks, -+ total_dest_line_time_ns); -+} -+ -+static uint32_t get_dmif_switch_time_us(struct dc_crtc_timing *timing) -+{ -+ uint32_t frame_time; -+ uint32_t pixels_per_second; -+ uint32_t pixels_per_frame; -+ uint32_t refresh_rate; -+ const uint32_t us_in_sec = 1000000; -+ const uint32_t min_single_frame_time_us = 30000; -+ /*return double of frame time*/ -+ const uint32_t single_frame_time_multiplier = 2; -+ -+ if (timing == NULL) -+ return single_frame_time_multiplier * min_single_frame_time_us; -+ -+ /*TODO: should we use pixel format normalized pixel clock here?*/ -+ pixels_per_second = timing->pix_clk_khz * 1000; -+ pixels_per_frame = timing->h_total * timing->v_total; -+ -+ if (!pixels_per_second || !pixels_per_frame) { -+ /* avoid division by zero */ -+ ASSERT(pixels_per_frame); -+ ASSERT(pixels_per_second); -+ return single_frame_time_multiplier * min_single_frame_time_us; -+ } -+ -+ refresh_rate = pixels_per_second / pixels_per_frame; -+ -+ if (!refresh_rate) { -+ /* avoid division by zero*/ -+ ASSERT(refresh_rate); -+ return single_frame_time_multiplier * min_single_frame_time_us; -+ } -+ -+ frame_time = us_in_sec / refresh_rate; -+ -+ if (frame_time < min_single_frame_time_us) -+ frame_time = min_single_frame_time_us; -+ -+ frame_time *= single_frame_time_multiplier; -+ -+ return frame_time; -+} -+ -+void dce110_allocate_dmif_buffer( -+ struct mem_input *mi, -+ struct dc_crtc_timing *timing, -+ uint32_t paths_num) -+{ -+ const uint32_t retry_delay = 10; -+ uint32_t retry_count = get_dmif_switch_time_us(timing) / retry_delay; -+ -+ struct dce110_mem_input *bm110 = TO_DCE110_MEM_INPUT(mi); -+ uint32_t addr = bm110->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL; -+ uint32_t value; -+ uint32_t field; -+ -+ if (bm110->supported_stutter_mode -+ & STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION) -+ goto register_underflow_int; -+ -+ /*Allocate DMIF buffer*/ -+ value = dal_read_reg(mi->ctx, addr); -+ field = get_reg_field_value( -+ value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); -+ if (field == 2) -+ goto register_underflow_int; -+ -+ set_reg_field_value( -+ value, -+ 2, -+ PIPE0_DMIF_BUFFER_CONTROL, -+ DMIF_BUFFERS_ALLOCATED); -+ -+ dal_write_reg(mi->ctx, addr, value); -+ -+ do { -+ value = dal_read_reg(mi->ctx, addr); -+ field = get_reg_field_value( -+ value, -+ PIPE0_DMIF_BUFFER_CONTROL, -+ DMIF_BUFFERS_ALLOCATION_COMPLETED); -+ -+ if (field) -+ break; -+ -+ dc_service_delay_in_microseconds(mi->ctx, retry_delay); -+ retry_count--; -+ -+ } while (retry_count > 0); -+ -+ if (field == 0) -+ dal_logger_write(mi->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: DMIF allocation failed", -+ __func__); -+ -+ /* -+ * Stella Wong proposed the following change -+ * -+ * Value of mcHubRdReqDmifLimit.ENABLE: -+ * 00 - disable DMIF rdreq limit -+ * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0 -+ * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1 -+ * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent -+ */ -+ addr = mmMC_HUB_RDREQ_DMIF_LIMIT; -+ value = dal_read_reg(mi->ctx, addr); -+ if (paths_num > 1) -+ set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); -+ else -+ set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); -+ dal_write_reg(mi->ctx, addr, value); -+ -+register_underflow_int: -+ /*todo*/; -+ /*register_interrupt(bm110, irq_source, ctrl_id);*/ -+} -+ -+static void deallocate_dmif_buffer_helper( -+ struct dc_context *ctx, uint32_t offset) -+{ -+ uint32_t value; -+ uint32_t count = 0xBB8; /* max retry count */ -+ -+ value = dal_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); -+ -+ if (!get_reg_field_value( -+ value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED)) -+ return; -+ -+ set_reg_field_value( -+ value, 0, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); -+ -+ dal_write_reg( -+ ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset, value); -+ -+ do { -+ value = dal_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); -+ dc_service_delay_in_microseconds(ctx, 10); -+ count--; -+ } while (count > 0 && -+ !get_reg_field_value( -+ value, -+ PIPE0_DMIF_BUFFER_CONTROL, -+ DMIF_BUFFERS_ALLOCATION_COMPLETED)); -+} -+ -+void dce110_deallocate_dmif_buffer(struct mem_input *mi, uint32_t paths_num) -+{ -+ struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); -+ uint32_t value; -+ -+ if (!(bm_dce110->supported_stutter_mode & -+ STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)) { -+ -+ /* De-allocate DMIF buffer first */ -+ if (mmPIPE0_DMIF_BUFFER_CONTROL + bm_dce110->offsets.pipe != 0) -+ deallocate_dmif_buffer_helper( -+ mi->ctx, bm_dce110->offsets.pipe); -+ } -+ -+ /* TODO: unregister underflow interrupt -+ unregisterInterrupt(); -+ */ -+ -+ /* Value of mcHubRdReqDmifLimit.ENABLE. -+ * 00 - disable dmif rdreq limit -+ * 01 - enable dmif rdreq limit, disable by dmif stall=1||urg!=0 -+ * 02 - enable dmif rdreq limit, disable by dmif stall=1 -+ * 03 - force enable dmif rdreq limit, ignore dmif stall/urgent -+ * Stella Wong proposed this change. */ -+ value = dal_read_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT); -+ if (paths_num > 1) -+ set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); -+ else -+ set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); -+ -+ dal_write_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT, value); -+} -+ -+void dce110_program_pix_dur(struct mem_input *mi, uint32_t pix_clk_khz) -+{ -+ uint64_t pix_dur; -+ uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 -+ + TO_DCE110_MEM_INPUT(mi)->offsets.dmif; -+ uint32_t value = dal_read_reg(mi->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); -+ -+ dal_write_reg(mi->ctx, addr, value); -+} -+ -+/*****************************************/ -+/* Constructor, Destructor */ -+/*****************************************/ -+ -+bool dce110_mem_input_construct( -+ struct dce110_mem_input *mem_input110, -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ if ((inst < 1) || (inst > ARRAY_SIZE(reg_offsets))) -+ return false; -+ -+ mem_input110->base.ctx = ctx; -+ -+ mem_input110->base.inst = inst; -+ -+ mem_input110->offsets = reg_offsets[inst - 1]; -+ -+ mem_input110->supported_stutter_mode = 0; -+ dal_adapter_service_get_feature_value(FEATURE_STUTTER_MODE, -+ &(mem_input110->supported_stutter_mode), -+ sizeof(mem_input110->supported_stutter_mode)); -+ -+ return true; -+} -+ -+void dce110_mem_input_destroy(struct mem_input **mem_input) -+{ -+ dc_service_free((*mem_input)->ctx, TO_DCE110_MEM_INPUT(*mem_input)); -+ *mem_input = NULL; -+} -+ -+struct mem_input *dce110_mem_input_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct dce110_mem_input *mem_input110 = -+ dc_service_alloc(ctx, sizeof(struct dce110_mem_input)); -+ -+ if (!mem_input110) -+ return NULL; -+ -+ if (dce110_mem_input_construct(mem_input110, -+ ctx, inst)) -+ return &mem_input110->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, mem_input110); -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h -new file mode 100644 -index 0000000..9c6d278 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h -@@ -0,0 +1,88 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_MEM_INPUT_DCE110_H__ -+#define __DC_MEM_INPUT_DCE110_H__ -+ -+#include "inc/mem_input.h" -+ -+#define TO_DCE110_MEM_INPUT(mi)\ -+ container_of(mi, struct dce110_mem_input, base) -+ -+struct dce110_mem_input_reg_offsets { -+ uint32_t dcp; -+ uint32_t dmif; -+ uint32_t pipe; -+}; -+ -+struct dce110_mem_input { -+ struct mem_input base; -+ struct dce110_mem_input_reg_offsets offsets; -+ uint32_t supported_stutter_mode; -+}; -+ -+struct mem_input *dce110_mem_input_create( -+ struct dc_context *ctx, -+ uint32_t inst); -+ -+void dce110_mem_input_destroy(struct mem_input **mem_input); -+ -+bool dce110_mem_input_program_surface_flip_and_addr( -+ struct mem_input *mem_input, -+ const struct dc_plane_address *address, -+ bool flip_immediate); -+ -+bool dce110_mem_input_program_surface_config( -+ struct mem_input *mem_input, -+ const struct dc_surface *surface); -+ -+void dce110_program_nbp_watermark( -+ struct mem_input *mem_input, -+ struct bw_watermarks marks); -+ -+void dce110_program_stutter_watermark( -+ struct mem_input *mem_input, -+ struct bw_watermarks marks); -+ -+void dce110_program_urgency_watermark( -+ struct mem_input *mem_input, -+ struct bw_watermarks marks, -+ uint32_t h_total, -+ uint32_t pixel_clk_in_khz, -+ uint32_t pstate_blackout_duration_ns); -+ -+void dce110_program_safe_display_marks(struct mem_input *mi); -+ -+void dce110_allocate_dmif_buffer( -+ struct mem_input *mem_input, -+ struct dc_crtc_timing *timing, -+ uint32_t paths_num); -+ -+void dce110_deallocate_dmif_buffer( -+ struct mem_input *mem_input, uint32_t paths_num); -+ -+void dce110_program_pix_dur( -+ struct mem_input *mem_input, uint32_t pix_clk_khz); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c -new file mode 100644 -index 0000000..0fdffac ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c -@@ -0,0 +1,296 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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" -+ -+#define FROM_OPP(opp)\ -+ container_of(opp, struct dce110_opp, base) -+ -+enum { -+ MAX_LUT_ENTRY = 256, -+ MAX_NUMBER_OF_ENTRIES = 256 -+}; -+ -+static const struct dce110_opp_reg_offsets 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), -+} -+}; -+ -+static void build_evenly_distributed_points( -+ struct gamma_pixel *points, -+ uint32_t numberof_points, -+ struct fixed31_32 max_value, -+ struct fixed31_32 divider1, -+ struct fixed31_32 divider2, -+ struct fixed31_32 divider3) -+{ -+ struct gamma_pixel *p = points; -+ struct gamma_pixel *p_last = p + numberof_points - 1; -+ -+ uint32_t i = 0; -+ -+ do { -+ struct fixed31_32 value = dal_fixed31_32_div_int( -+ dal_fixed31_32_mul_int(max_value, i), -+ numberof_points - 1); -+ -+ p->r = value; -+ p->g = value; -+ p->b = value; -+ -+ ++p; -+ ++i; -+ } while (i != numberof_points); -+ -+ p->r = dal_fixed31_32_div(p_last->r, divider1); -+ p->g = dal_fixed31_32_div(p_last->g, divider1); -+ p->b = dal_fixed31_32_div(p_last->b, divider1); -+ -+ ++p; -+ -+ p->r = dal_fixed31_32_div(p_last->r, divider2); -+ p->g = dal_fixed31_32_div(p_last->g, divider2); -+ p->b = dal_fixed31_32_div(p_last->b, divider2); -+ -+ ++p; -+ -+ p->r = dal_fixed31_32_div(p_last->r, divider3); -+ p->g = dal_fixed31_32_div(p_last->g, divider3); -+ p->b = dal_fixed31_32_div(p_last->b, divider3); -+} -+ -+/*****************************************/ -+/* Constructor, Destructor */ -+/*****************************************/ -+ -+bool dce110_opp_construct(struct dce110_opp *opp110, -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ if ((inst < 1) || (inst > ARRAY_SIZE(reg_offsets))) -+ return false; -+ -+ opp110->base.ctx = ctx; -+ -+ opp110->base.inst = inst; -+ -+ opp110->offsets = reg_offsets[inst - 1]; -+ -+ opp110->regamma.hw_points_num = 128; -+ opp110->regamma.coordinates_x = NULL; -+ opp110->regamma.rgb_resulted = NULL; -+ opp110->regamma.rgb_regamma = NULL; -+ opp110->regamma.coeff128 = NULL; -+ opp110->regamma.coeff128_oem = NULL; -+ opp110->regamma.coeff128_dx = NULL; -+ opp110->regamma.axis_x_256 = NULL; -+ opp110->regamma.axis_x_1025 = NULL; -+ opp110->regamma.rgb_oem = NULL; -+ opp110->regamma.rgb_user = NULL; -+ opp110->regamma.extra_points = 3; -+ opp110->regamma.use_half_points = false; -+ opp110->regamma.x_max1 = dal_fixed31_32_one; -+ opp110->regamma.x_max2 = dal_fixed31_32_from_int(2); -+ opp110->regamma.x_min = dal_fixed31_32_zero; -+ opp110->regamma.divider1 = dal_fixed31_32_from_fraction(3, 2); -+ opp110->regamma.divider2 = dal_fixed31_32_from_int(2); -+ opp110->regamma.divider3 = dal_fixed31_32_from_fraction(5, 2); -+ -+ opp110->regamma.rgb_user = dc_service_alloc( -+ ctx, -+ sizeof(struct pwl_float_data) * -+ (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); -+ if (!opp110->regamma.rgb_user) -+ goto failure_1; -+ -+ opp110->regamma.rgb_oem = dc_service_alloc( -+ ctx, -+ sizeof(struct pwl_float_data) * -+ (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); -+ if (!opp110->regamma.rgb_oem) -+ goto failure_2; -+ -+ opp110->regamma.rgb_resulted = dc_service_alloc( -+ ctx, -+ sizeof(struct pwl_result_data) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.rgb_resulted) -+ goto failure_3; -+ -+ opp110->regamma.rgb_regamma = dc_service_alloc( -+ ctx, -+ sizeof(struct pwl_float_data_ex) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.rgb_regamma) -+ goto failure_4; -+ -+ opp110->regamma.coordinates_x = dc_service_alloc( -+ ctx, -+ sizeof(struct hw_x_point) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.coordinates_x) -+ goto failure_5; -+ -+ opp110->regamma.axis_x_256 = dc_service_alloc( -+ ctx, -+ sizeof(struct gamma_pixel) * -+ (MAX_LUT_ENTRY + opp110->regamma.extra_points)); -+ if (!opp110->regamma.axis_x_256) -+ goto failure_6; -+ -+ opp110->regamma.axis_x_1025 = dc_service_alloc( -+ ctx, -+ sizeof(struct gamma_pixel) * -+ (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); -+ if (!opp110->regamma.axis_x_1025) -+ goto failure_7; -+ -+ opp110->regamma.coeff128 = dc_service_alloc( -+ ctx, -+ sizeof(struct pixel_gamma_point) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.coeff128) -+ goto failure_8; -+ -+ opp110->regamma.coeff128_oem = dc_service_alloc( -+ ctx, -+ sizeof(struct pixel_gamma_point) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.coeff128_oem) -+ goto failure_9; -+ -+ opp110->regamma.coeff128_dx = dc_service_alloc( -+ ctx, -+ sizeof(struct pixel_gamma_point) * -+ (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); -+ if (!opp110->regamma.coeff128_dx) -+ goto failure_10; -+ -+ /* init palette */ -+ { -+ uint32_t i = 0; -+ -+ do { -+ opp110->regamma.saved_palette[i].red = (uint8_t)i; -+ opp110->regamma.saved_palette[i].green = (uint8_t)i; -+ opp110->regamma.saved_palette[i].blue = (uint8_t)i; -+ -+ ++i; -+ } while (i != MAX_LUT_ENTRY); -+ } -+ -+ build_evenly_distributed_points( -+ opp110->regamma.axis_x_256, -+ MAX_LUT_ENTRY, -+ opp110->regamma.x_max1, -+ opp110->regamma.divider1, -+ opp110->regamma.divider2, -+ opp110->regamma.divider3); -+ -+ build_evenly_distributed_points( -+ opp110->regamma.axis_x_1025, -+ DX_GAMMA_RAMP_MAX, -+ opp110->regamma.x_max1, -+ opp110->regamma.divider1, -+ opp110->regamma.divider2, -+ opp110->regamma.divider3); -+ -+ return true; -+ -+failure_10: -+ dc_service_free(ctx, opp110->regamma.coeff128_oem); -+failure_9: -+ dc_service_free(ctx, opp110->regamma.coeff128); -+failure_8: -+ dc_service_free(ctx, opp110->regamma.axis_x_1025); -+failure_7: -+ dc_service_free(ctx, opp110->regamma.axis_x_256); -+failure_6: -+ dc_service_free(ctx, opp110->regamma.coordinates_x); -+failure_5: -+ dc_service_free(ctx, opp110->regamma.rgb_regamma); -+failure_4: -+ dc_service_free(ctx, opp110->regamma.rgb_resulted); -+failure_3: -+ dc_service_free(ctx, opp110->regamma.rgb_oem); -+failure_2: -+ dc_service_free(ctx, opp110->regamma.rgb_user); -+failure_1: -+ -+ return true; -+} -+ -+void dce110_opp_destroy(struct output_pixel_processor **opp) -+{ -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.coeff128_dx); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.coeff128_oem); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.coeff128); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.axis_x_1025); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.axis_x_256); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.coordinates_x); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.rgb_regamma); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.rgb_resulted); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.rgb_oem); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)->regamma.rgb_user); -+ dc_service_free((*opp)->ctx, FROM_OPP(*opp)); -+ *opp = NULL; -+} -+ -+struct output_pixel_processor *dce110_opp_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct dce110_opp *opp = -+ dc_service_alloc(ctx, sizeof(struct dce110_opp)); -+ -+ if (!opp) -+ return NULL; -+ -+ if (dce110_opp_construct(opp, -+ ctx, inst)) -+ return &opp->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, opp); -+ return NULL; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h -new file mode 100644 -index 0000000..71fe624 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.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 __DC_OPP_DCE110_H__ -+#define __DC_OPP_DCE110_H__ -+ -+#include "dc_types.h" -+#include "inc/opp.h" -+ -+enum dce110_opp_reg_type { -+ DCE110_OPP_REG_DCP = 0, -+ DCE110_OPP_REG_DCFE, -+ DCE110_OPP_REG_FMT, -+ -+ DCE110_OPP_REG_MAX -+}; -+ -+struct dce110_regamma { -+ struct gamma_curve arr_curve_points[16]; -+ struct curve_points arr_points[3]; -+ uint32_t hw_points_num; -+ struct hw_x_point *coordinates_x; -+ struct pwl_result_data *rgb_resulted; -+ -+ /* re-gamma curve */ -+ struct pwl_float_data_ex *rgb_regamma; -+ /* coeff used to map user evenly distributed points -+ * to our hardware points (predefined) for gamma 256 */ -+ struct pixel_gamma_point *coeff128; -+ struct pixel_gamma_point *coeff128_oem; -+ /* coeff used to map user evenly distributed points -+ * to our hardware points (predefined) for gamma 1025 */ -+ struct pixel_gamma_point *coeff128_dx; -+ /* evenly distributed points, gamma 256 software points 0-255 */ -+ struct gamma_pixel *axis_x_256; -+ /* evenly distributed points, gamma 1025 software points 0-1025 */ -+ struct gamma_pixel *axis_x_1025; -+ /* OEM supplied gamma for regamma LUT */ -+ struct pwl_float_data *rgb_oem; -+ /* user supplied gamma */ -+ struct pwl_float_data *rgb_user; -+ struct dev_c_lut saved_palette[RGB_256X3X16]; -+ uint32_t extra_points; -+ bool use_half_points; -+ struct fixed31_32 x_max1; -+ struct fixed31_32 x_max2; -+ struct fixed31_32 x_min; -+ struct fixed31_32 divider1; -+ struct fixed31_32 divider2; -+ struct fixed31_32 divider3; -+}; -+ -+/* OPP RELATED */ -+#define TO_DCE110_OPP(opp)\ -+ container_of(opp, struct dce110_opp, base) -+ -+struct dce110_opp_reg_offsets { -+ uint32_t fmt_offset; -+ uint32_t dcp_offset; -+ uint32_t dcfe_offset; -+}; -+ -+struct dce110_opp { -+ struct output_pixel_processor base; -+ struct dce110_opp_reg_offsets offsets; -+ struct dce110_regamma regamma; -+}; -+ -+bool dce110_opp_construct(struct dce110_opp *opp110, -+ struct dc_context *ctx, -+ uint32_t inst); -+ -+void dce110_opp_destroy(struct output_pixel_processor **opp); -+ -+struct output_pixel_processor *dce110_opp_create( -+ struct dc_context *ctx, -+ uint32_t inst); -+ -+/* REGAMMA RELATED */ -+void dce110_opp_power_on_regamma_lut( -+ struct output_pixel_processor *opp, -+ bool power_on); -+ -+bool dce110_opp_set_regamma( -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *ramp, -+ const struct gamma_parameters *params, -+ bool force_bypass); -+ -+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user( -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params); -+ -+void dce110_opp_set_csc_adjustment( -+ struct output_pixel_processor *opp, -+ const struct grph_csc_adjustment *adjust); -+ -+void dce110_opp_set_csc_default( -+ struct output_pixel_processor *opp, -+ const struct default_adjustment *default_adjust); -+ -+/* FORMATTER RELATED */ -+void dce110_opp_program_bit_depth_reduction( -+ struct output_pixel_processor *opp, -+ const struct bit_depth_reduction_params *params); -+ -+void dce110_opp_program_clamping_and_pixel_encoding( -+ struct output_pixel_processor *opp, -+ const struct clamping_and_pixel_encoding_params *params); -+ -+ -+void dce110_opp_set_dyn_expansion( -+ struct output_pixel_processor *opp, -+ enum color_space color_sp, -+ enum dc_color_depth color_dpth, -+ enum signal_type signal); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c -new file mode 100644 -index 0000000..91430c0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c -@@ -0,0 +1,904 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "dce110_opp.h" -+#include "basics/conversion.h" -+ -+/* include DCE11 register header files */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#define DCP_REG(reg)\ -+ (reg + opp110->offsets.dcp_offset) -+ -+enum { -+ OUTPUT_CSC_MATRIX_SIZE = 12 -+}; -+ -+struct out_csc_color_matrix { -+ enum color_space color_space; -+ uint16_t regval[OUTPUT_CSC_MATRIX_SIZE]; -+}; -+ -+static const struct out_csc_color_matrix global_color_matrix[] = { -+{ COLOR_SPACE_SRGB_FULL_RANGE, -+ { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -+{ COLOR_SPACE_SRGB_LIMITED_RANGE, -+ { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -+{ COLOR_SPACE_YCBCR601, -+ { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, -+ 0xF6B9, 0xE00, 0x1000} }, -+{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, -+ 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -+/* YOnly same as YCbCr709 but Y in Full range -To do. */ -+{ COLOR_SPACE_YCBCR601_YONLY, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, -+ 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -+{ COLOR_SPACE_YCBCR709_YONLY, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, -+ 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -+}; -+ -+enum csc_color_mode { -+ /* 00 - BITS2:0 Bypass */ -+ CSC_COLOR_MODE_GRAPHICS_BYPASS, -+ /* 01 - hard coded coefficient TV RGB */ -+ CSC_COLOR_MODE_GRAPHICS_PREDEFINED, -+ /* 04 - programmable OUTPUT CSC coefficient */ -+ CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -+}; -+ -+static void program_color_matrix( -+ struct dce110_opp *opp110, -+ const struct out_csc_color_matrix *tbl_entry, -+ enum grph_color_adjust_option options) -+{ -+ struct dc_context *ctx = opp110->base.ctx; -+ { -+ uint32_t value = 0; -+ uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ value, -+ tbl_entry->regval[0], -+ OUTPUT_CSC_C11_C12, -+ OUTPUT_CSC_C11); -+ -+ set_reg_field_value( -+ value, -+ tbl_entry->regval[1], -+ OUTPUT_CSC_C11_C12, -+ OUTPUT_CSC_C12); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+} -+ -+/* -+ * initialize_color_float_adj_reference_values -+ * This initialize display color adjust input from API to HW range for later -+ * calculation use. This is shared by all the display color adjustment. -+ * @param : -+ * @return None -+ */ -+static void initialize_color_float_adj_reference_values( -+ const struct grph_csc_adjustment *adjust, -+ struct fixed31_32 *grph_cont, -+ struct fixed31_32 *grph_sat, -+ struct fixed31_32 *grph_bright, -+ struct fixed31_32 *sin_grph_hue, -+ struct fixed31_32 *cos_grph_hue) -+{ -+ /* Hue adjustment could be negative. -45 ~ +45 */ -+ struct fixed31_32 hue = -+ dal_fixed31_32_mul( -+ dal_fixed31_32_from_fraction(adjust->grph_hue, 180), -+ dal_fixed31_32_pi); -+ -+ *sin_grph_hue = dal_fixed31_32_sin(hue); -+ *cos_grph_hue = dal_fixed31_32_cos(hue); -+ -+ if (adjust->adjust_divider) { -+ *grph_cont = -+ dal_fixed31_32_from_fraction( -+ adjust->grph_cont, -+ adjust->adjust_divider); -+ *grph_sat = -+ dal_fixed31_32_from_fraction( -+ adjust->grph_sat, -+ adjust->adjust_divider); -+ *grph_bright = -+ dal_fixed31_32_from_fraction( -+ adjust->grph_bright, -+ adjust->adjust_divider); -+ } else { -+ *grph_cont = dal_fixed31_32_from_int(adjust->grph_cont); -+ *grph_sat = dal_fixed31_32_from_int(adjust->grph_sat); -+ *grph_bright = dal_fixed31_32_from_int(adjust->grph_bright); -+ } -+} -+ -+static inline struct fixed31_32 fixed31_32_clamp( -+ struct fixed31_32 value, -+ int32_t min_numerator, -+ int32_t max_numerator, -+ int32_t denominator) -+{ -+ return dal_fixed31_32_clamp( -+ value, -+ dal_fixed31_32_from_fraction( -+ min_numerator, -+ denominator), -+ dal_fixed31_32_from_fraction( -+ max_numerator, -+ denominator)); -+} -+ -+static void setup_reg_format( -+ struct fixed31_32 *coefficients, -+ uint16_t *reg_values) -+{ -+ enum { -+ LENGTH = 12, -+ DENOMINATOR = 10000 -+ }; -+ -+ static const int32_t min_numerator[] = { -+ -3 * DENOMINATOR, -+ -DENOMINATOR -+ }; -+ -+ static const int32_t max_numerator[] = { -+ DENOMINATOR, -+ DENOMINATOR -+ }; -+ -+ static const uint8_t integer_bits[] = { 2, 0 }; -+ -+ uint32_t i = 0; -+ -+ do { -+ const uint32_t index = (i % 4) == 3; -+ -+ reg_values[i] = fixed_point_to_int_frac( -+ fixed31_32_clamp(coefficients[(i + 8) % LENGTH], -+ min_numerator[index], -+ max_numerator[index], -+ DENOMINATOR), -+ integer_bits[index], 13); -+ -+ ++i; -+ } while (i != LENGTH); -+} -+ -+/** -+ ***************************************************************************** -+ * Function: setup_adjustments -+ * @note prepare to setup the values -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+static void setup_adjustments(const struct grph_csc_adjustment *adjust, -+ struct dc_csc_adjustments *adjustments) -+{ -+ if (adjust->adjust_divider != 0) { -+ adjustments->brightness = -+ dal_fixed31_32_from_fraction(adjust->grph_bright, -+ adjust->adjust_divider); -+ adjustments->contrast = -+ dal_fixed31_32_from_fraction(adjust->grph_cont, -+ adjust->adjust_divider); -+ adjustments->saturation = -+ dal_fixed31_32_from_fraction(adjust->grph_sat, -+ adjust->adjust_divider); -+ } else { -+ adjustments->brightness = -+ dal_fixed31_32_from_fraction(adjust->grph_bright, 1); -+ adjustments->contrast = -+ dal_fixed31_32_from_fraction(adjust->grph_cont, 1); -+ adjustments->saturation = -+ dal_fixed31_32_from_fraction(adjust->grph_sat, 1); -+ } -+ -+ /* convert degrees into radians */ -+ adjustments->hue = -+ dal_fixed31_32_mul( -+ dal_fixed31_32_from_fraction(adjust->grph_hue, 180), -+ dal_fixed31_32_pi); -+} -+ -+static void prepare_tv_rgb_ideal( -+ struct fixed31_32 *matrix) -+{ -+ static const int32_t matrix_[] = { -+ 85546875, 0, 0, 6250000, -+ 0, 85546875, 0, 6250000, -+ 0, 0, 85546875, 6250000 -+ }; -+ -+ uint32_t i = 0; -+ -+ do { -+ matrix[i] = dal_fixed31_32_from_fraction( -+ matrix_[i], -+ 100000000); -+ ++i; -+ } while (i != ARRAY_SIZE(matrix_)); -+} -+ -+/** -+ ***************************************************************************** -+ * Function: dal_transform_wide_gamut_set_rgb_adjustment_legacy -+ * -+ * @param [in] const struct grph_csc_adjustment *adjust -+ * -+ * @return -+ * void -+ * -+ * @note calculate and program color adjustments for sRGB color space -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+static void set_rgb_adjustment_legacy( -+ struct dce110_opp *opp110, -+ const struct grph_csc_adjustment *adjust) -+{ -+ const struct fixed31_32 k1 = -+ dal_fixed31_32_from_fraction(701000, 1000000); -+ const struct fixed31_32 k2 = -+ dal_fixed31_32_from_fraction(236568, 1000000); -+ const struct fixed31_32 k3 = -+ dal_fixed31_32_from_fraction(-587000, 1000000); -+ const struct fixed31_32 k4 = -+ dal_fixed31_32_from_fraction(464432, 1000000); -+ const struct fixed31_32 k5 = -+ dal_fixed31_32_from_fraction(-114000, 1000000); -+ const struct fixed31_32 k6 = -+ dal_fixed31_32_from_fraction(-701000, 1000000); -+ const struct fixed31_32 k7 = -+ dal_fixed31_32_from_fraction(-299000, 1000000); -+ const struct fixed31_32 k8 = -+ dal_fixed31_32_from_fraction(-292569, 1000000); -+ const struct fixed31_32 k9 = -+ dal_fixed31_32_from_fraction(413000, 1000000); -+ const struct fixed31_32 k10 = -+ dal_fixed31_32_from_fraction(-92482, 1000000); -+ const struct fixed31_32 k11 = -+ dal_fixed31_32_from_fraction(-114000, 1000000); -+ const struct fixed31_32 k12 = -+ dal_fixed31_32_from_fraction(385051, 1000000); -+ const struct fixed31_32 k13 = -+ dal_fixed31_32_from_fraction(-299000, 1000000); -+ const struct fixed31_32 k14 = -+ dal_fixed31_32_from_fraction(886000, 1000000); -+ const struct fixed31_32 k15 = -+ dal_fixed31_32_from_fraction(-587000, 1000000); -+ const struct fixed31_32 k16 = -+ dal_fixed31_32_from_fraction(-741914, 1000000); -+ const struct fixed31_32 k17 = -+ dal_fixed31_32_from_fraction(886000, 1000000); -+ const struct fixed31_32 k18 = -+ dal_fixed31_32_from_fraction(-144086, 1000000); -+ -+ const struct fixed31_32 luma_r = -+ dal_fixed31_32_from_fraction(299, 1000); -+ const struct fixed31_32 luma_g = -+ dal_fixed31_32_from_fraction(587, 1000); -+ const struct fixed31_32 luma_b = -+ dal_fixed31_32_from_fraction(114, 1000); -+ -+ struct out_csc_color_matrix tbl_entry; -+ struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE]; -+ -+ struct fixed31_32 grph_cont; -+ struct fixed31_32 grph_sat; -+ struct fixed31_32 grph_bright; -+ struct fixed31_32 sin_grph_hue; -+ struct fixed31_32 cos_grph_hue; -+ -+ initialize_color_float_adj_reference_values( -+ adjust, &grph_cont, &grph_sat, -+ &grph_bright, &sin_grph_hue, &cos_grph_hue); -+ -+ /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + -+ * Sin(GrphHue) * K2)) */ -+ /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2) */ -+ matrix[0] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k1), -+ dal_fixed31_32_mul(sin_grph_hue, k2)); -+ /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ -+ matrix[0] = dal_fixed31_32_mul(grph_sat, matrix[0]); -+ /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)) */ -+ matrix[0] = dal_fixed31_32_add(luma_r, matrix[0]); -+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * -+ * K2)) */ -+ matrix[0] = dal_fixed31_32_mul(grph_cont, matrix[0]); -+ -+ /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + -+ * Sin(GrphHue) * K4)) */ -+ /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */ -+ matrix[1] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k3), -+ dal_fixed31_32_mul(sin_grph_hue, k4)); -+ /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */ -+ matrix[1] = dal_fixed31_32_mul(grph_sat, matrix[1]); -+ /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)) */ -+ matrix[1] = dal_fixed31_32_add(luma_g, matrix[1]); -+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * -+ * K4)) */ -+ matrix[1] = dal_fixed31_32_mul(grph_cont, matrix[1]); -+ -+ /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + -+ * Sin(GrphHue) * K6)) */ -+ /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */ -+ matrix[2] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k5), -+ dal_fixed31_32_mul(sin_grph_hue, k6)); -+ /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */ -+ matrix[2] = dal_fixed31_32_mul(grph_sat, matrix[2]); -+ /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */ -+ matrix[2] = dal_fixed31_32_add(luma_b, matrix[2]); -+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * -+ * K6)) */ -+ matrix[2] = dal_fixed31_32_mul(grph_cont, matrix[2]); -+ -+ /* COEF_1_4 = GrphBright */ -+ matrix[3] = grph_bright; -+ -+ /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + -+ * Sin(GrphHue) * K8)) */ -+ /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */ -+ matrix[4] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k7), -+ dal_fixed31_32_mul(sin_grph_hue, k8)); -+ /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */ -+ matrix[4] = dal_fixed31_32_mul(grph_sat, matrix[4]); -+ /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)) */ -+ matrix[4] = dal_fixed31_32_add(luma_r, matrix[4]); -+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * -+ * K8)) */ -+ matrix[4] = dal_fixed31_32_mul(grph_cont, matrix[4]); -+ -+ /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + -+ * Sin(GrphHue) * K10)) */ -+ /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */ -+ matrix[5] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k9), -+ dal_fixed31_32_mul(sin_grph_hue, k10)); -+ /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */ -+ matrix[5] = dal_fixed31_32_mul(grph_sat, matrix[5]); -+ /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */ -+ matrix[5] = dal_fixed31_32_add(luma_g, matrix[5]); -+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * -+ * K10)) */ -+ matrix[5] = dal_fixed31_32_mul(grph_cont, matrix[5]); -+ -+ /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + -+ * Sin(GrphHue) * K12)) */ -+ /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */ -+ matrix[6] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k11), -+ dal_fixed31_32_mul(sin_grph_hue, k12)); -+ /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */ -+ matrix[6] = dal_fixed31_32_mul(grph_sat, matrix[6]); -+ /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */ -+ matrix[6] = dal_fixed31_32_add(luma_b, matrix[6]); -+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * -+ * K12)) */ -+ matrix[6] = dal_fixed31_32_mul(grph_cont, matrix[6]); -+ -+ /* COEF_2_4 = GrphBright */ -+ matrix[7] = grph_bright; -+ -+ /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + -+ * Sin(GrphHue) * K14)) */ -+ /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ -+ matrix[8] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k13), -+ dal_fixed31_32_mul(sin_grph_hue, k14)); -+ /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ -+ matrix[8] = dal_fixed31_32_mul(grph_sat, matrix[8]); -+ /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ -+ matrix[8] = dal_fixed31_32_add(luma_r, matrix[8]); -+ /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * -+ * K14)) */ -+ matrix[8] = dal_fixed31_32_mul(grph_cont, matrix[8]); -+ -+ /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + -+ * Sin(GrphHue) * K16)) */ -+ /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ -+ matrix[9] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k15), -+ dal_fixed31_32_mul(sin_grph_hue, k16)); -+ /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ -+ matrix[9] = dal_fixed31_32_mul(grph_sat, matrix[9]); -+ /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ -+ matrix[9] = dal_fixed31_32_add(luma_g, matrix[9]); -+ /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * -+ * K16)) */ -+ matrix[9] = dal_fixed31_32_mul(grph_cont, matrix[9]); -+ -+ /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + -+ * Sin(GrphHue) * K18)) */ -+ /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ -+ matrix[10] = -+ dal_fixed31_32_add( -+ dal_fixed31_32_mul(cos_grph_hue, k17), -+ dal_fixed31_32_mul(sin_grph_hue, k18)); -+ /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ -+ matrix[10] = dal_fixed31_32_mul(grph_sat, matrix[10]); -+ /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ -+ matrix[10] = dal_fixed31_32_add(luma_b, matrix[10]); -+ /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * -+ * K18)) */ -+ matrix[10] = dal_fixed31_32_mul(grph_cont, matrix[10]); -+ -+ /* COEF_3_4 = GrphBright */ -+ matrix[11] = grph_bright; -+ -+ tbl_entry.color_space = adjust->c_space; -+ -+ convert_float_matrix(tbl_entry.regval, matrix, OUTPUT_CSC_MATRIX_SIZE); -+ -+ program_color_matrix( -+ opp110, &tbl_entry, adjust->color_adjust_option); -+} -+ -+/** -+ ***************************************************************************** -+ * Function: dal_transform_wide_gamut_set_rgb_limited_range_adjustment -+ * -+ * @param [in] const struct grph_csc_adjustment *adjust -+ * -+ * @return -+ * void -+ * -+ * @note calculate and program color adjustments for sRGB limited color space -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+static void set_rgb_limited_range_adjustment( -+ struct dce110_opp *opp110, -+ const struct grph_csc_adjustment *adjust) -+{ -+ struct out_csc_color_matrix reg_matrix; -+ struct fixed31_32 change_matrix[OUTPUT_CSC_MATRIX_SIZE]; -+ struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE]; -+ struct dc_csc_adjustments adjustments; -+ struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE]; -+ -+ prepare_tv_rgb_ideal(ideals); -+ -+ setup_adjustments(adjust, &adjustments); -+ -+ calculate_adjustments(ideals, &adjustments, matrix); -+ -+ dc_service_memmove(change_matrix, matrix, sizeof(matrix)); -+ -+ /* from 1 -> 3 */ -+ matrix[8] = change_matrix[0]; -+ matrix[9] = change_matrix[1]; -+ matrix[10] = change_matrix[2]; -+ matrix[11] = change_matrix[3]; -+ -+ /* from 2 -> 1 */ -+ matrix[0] = change_matrix[4]; -+ matrix[1] = change_matrix[5]; -+ matrix[2] = change_matrix[6]; -+ matrix[3] = change_matrix[7]; -+ -+ /* from 3 -> 2 */ -+ matrix[4] = change_matrix[8]; -+ matrix[5] = change_matrix[9]; -+ matrix[6] = change_matrix[10]; -+ matrix[7] = change_matrix[11]; -+ -+ dc_service_memset(®_matrix, 0, sizeof(struct out_csc_color_matrix)); -+ -+ setup_reg_format(matrix, reg_matrix.regval); -+ -+ program_color_matrix(opp110, ®_matrix, GRPH_COLOR_MATRIX_SW); -+} -+ -+static void prepare_yuv_ideal( -+ bool b601, -+ struct fixed31_32 *matrix) -+{ -+ static const int32_t matrix_1[] = { -+ 25578516, 50216016, 9752344, 6250000, -+ -14764391, -28985609, 43750000, 50000000, -+ 43750000, -36635164, -7114836, 50000000 -+ }; -+ -+ static const int32_t matrix_2[] = { -+ 18187266, 61183125, 6176484, 6250000, -+ -10025059, -33724941, 43750000, 50000000, -+ 43750000, -39738379, -4011621, 50000000 -+ }; -+ -+ const int32_t *matrix_x = b601 ? matrix_1 : matrix_2; -+ -+ uint32_t i = 0; -+ -+ do { -+ matrix[i] = dal_fixed31_32_from_fraction( -+ matrix_x[i], -+ 100000000); -+ ++i; -+ } while (i != ARRAY_SIZE(matrix_1)); -+} -+ -+/** -+ ***************************************************************************** -+ * Function: dal_transform_wide_gamut_set_yuv_adjustment -+ * -+ * @param [in] const struct grph_csc_adjustment *adjust -+ * -+ * @return -+ * void -+ * -+ * @note calculate and program color adjustments for YUV color spaces -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+static void set_yuv_adjustment( -+ struct dce110_opp *opp110, -+ const struct grph_csc_adjustment *adjust) -+{ -+ bool b601 = (adjust->c_space == COLOR_SPACE_YPBPR601) || -+ (adjust->c_space == COLOR_SPACE_YCBCR601) || -+ (adjust->c_space == COLOR_SPACE_YCBCR601_YONLY); -+ struct out_csc_color_matrix reg_matrix; -+ struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE]; -+ struct dc_csc_adjustments adjustments; -+ struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE]; -+ -+ prepare_yuv_ideal(b601, ideals); -+ -+ setup_adjustments(adjust, &adjustments); -+ -+ if ((adjust->c_space == COLOR_SPACE_YCBCR601_YONLY) || -+ (adjust->c_space == COLOR_SPACE_YCBCR709_YONLY)) -+ calculate_adjustments_y_only( -+ ideals, &adjustments, matrix); -+ else -+ calculate_adjustments( -+ ideals, &adjustments, matrix); -+ -+ dc_service_memset(®_matrix, 0, sizeof(struct out_csc_color_matrix)); -+ -+ setup_reg_format(matrix, reg_matrix.regval); -+ -+ program_color_matrix(opp110, ®_matrix, GRPH_COLOR_MATRIX_SW); -+} -+ -+static bool configure_graphics_mode( -+ struct dce110_opp *opp110, -+ enum csc_color_mode config, -+ enum graphics_csc_adjust_type csc_adjust_type, -+ enum color_space color_space) -+{ -+ struct dc_context *ctx = opp110->base.ctx; -+ uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ -+ if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { -+ if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { -+ set_reg_field_value( -+ value, -+ 4, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ } else { -+ -+ switch (color_space) { -+ case COLOR_SPACE_SRGB_FULL_RANGE: -+ /* by pass */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_SRGB_LIMITED_RANGE: -+ /* TV RGB */ -+ set_reg_field_value( -+ value, -+ 1, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_YCBCR601: -+ case COLOR_SPACE_YPBPR601: -+ case COLOR_SPACE_YCBCR601_YONLY: -+ /* YCbCr601 */ -+ set_reg_field_value( -+ value, -+ 2, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_YCBCR709: -+ case COLOR_SPACE_YPBPR709: -+ case COLOR_SPACE_YCBCR709_YONLY: -+ /* YCbCr709 */ -+ set_reg_field_value( -+ value, -+ 3, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ default: -+ return false; -+ } -+ } -+ } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { -+ switch (color_space) { -+ case COLOR_SPACE_SRGB_FULL_RANGE: -+ /* by pass */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_SRGB_LIMITED_RANGE: -+ /* TV RGB */ -+ set_reg_field_value( -+ value, -+ 1, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_YCBCR601: -+ case COLOR_SPACE_YPBPR601: -+ case COLOR_SPACE_YCBCR601_YONLY: -+ /* YCbCr601 */ -+ set_reg_field_value( -+ value, -+ 2, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ case COLOR_SPACE_YCBCR709: -+ case COLOR_SPACE_YPBPR709: -+ case COLOR_SPACE_YCBCR709_YONLY: -+ /* YCbCr709 */ -+ set_reg_field_value( -+ value, -+ 3, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ break; -+ default: -+ return false; -+ } -+ -+ } else -+ /* by pass */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUTPUT_CSC_CONTROL, -+ OUTPUT_CSC_GRPH_MODE); -+ -+ addr = DCP_REG(mmOUTPUT_CSC_CONTROL); -+ dal_write_reg(ctx, addr, value); -+ -+ return true; -+} -+ -+void dce110_opp_set_csc_adjustment( -+ struct output_pixel_processor *opp, -+ const struct grph_csc_adjustment *adjust) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ enum csc_color_mode config = -+ CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; -+ -+ /* Apply color adjustments: brightness, saturation, hue, contrast and -+ * CSC. No need for different color space routine, color space defines -+ * the ideal values only, but keep original design to allow quick switch -+ * to the old legacy routines */ -+ switch (adjust->c_space) { -+ case COLOR_SPACE_SRGB_FULL_RANGE: -+ set_rgb_adjustment_legacy(opp110, adjust); -+ break; -+ case COLOR_SPACE_SRGB_LIMITED_RANGE: -+ set_rgb_limited_range_adjustment( -+ opp110, adjust); -+ break; -+ case COLOR_SPACE_YCBCR601: -+ case COLOR_SPACE_YCBCR709: -+ case COLOR_SPACE_YCBCR601_YONLY: -+ case COLOR_SPACE_YCBCR709_YONLY: -+ case COLOR_SPACE_YPBPR601: -+ case COLOR_SPACE_YPBPR709: -+ set_yuv_adjustment(opp110, adjust); -+ break; -+ default: -+ set_rgb_adjustment_legacy(opp110, adjust); -+ break; -+ } -+ -+ /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ -+ configure_graphics_mode(opp110, config, adjust->csc_adjust_type, -+ adjust->c_space); -+} -+ -+void dce110_opp_set_csc_default( -+ struct output_pixel_processor *opp, -+ const struct default_adjustment *default_adjust) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ enum csc_color_mode config = -+ CSC_COLOR_MODE_GRAPHICS_PREDEFINED; -+ -+ if (default_adjust->force_hw_default == false) { -+ const struct out_csc_color_matrix *elm; -+ /* currently parameter not in use */ -+ enum grph_color_adjust_option option = -+ GRPH_COLOR_MATRIX_HW_DEFAULT; -+ uint32_t i; -+ /* -+ * HW default false we program locally defined matrix -+ * HW default true we use predefined hw matrix and we -+ * do not need to program matrix -+ * OEM wants the HW default via runtime parameter. -+ */ -+ option = GRPH_COLOR_MATRIX_SW; -+ -+ for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { -+ elm = &global_color_matrix[i]; -+ if (elm->color_space != default_adjust->color_space) -+ continue; -+ /* program the matrix with default values from this -+ * file */ -+ program_color_matrix(opp110, elm, option); -+ config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; -+ break; -+ } -+ } -+ -+ /* configure the what we programmed : -+ * 1. Default values from this file -+ * 2. Use hardware default from ROM_A and we do not need to program -+ * matrix */ -+ -+ configure_graphics_mode(opp110, config, -+ default_adjust->csc_adjust_type, -+ default_adjust->color_space); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c -new file mode 100644 -index 0000000..fdf87bd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c -@@ -0,0 +1,610 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 = dal_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); -+ -+ dal_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); -+ -+ dal_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 = dal_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); -+ -+ dal_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 = dal_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); -+ } -+ -+ dal_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); -+ dal_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); -+ dal_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); -+ dal_write_reg(opp110->base.ctx, addr, dither_b_value); -+ -+ /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero -+ * offset for the R/Cr channel, lower 4LSB -+ * is forced to zeros. Typically set to 0 -+ * RGB and 0x80000 YCbCr. -+ */ -+ /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero -+ * offset for the G/Y channel, lower 4LSB is -+ * forced to zeros. Typically set to 0 RGB -+ * and 0x80000 YCbCr. -+ */ -+ /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero -+ * offset for the B/Cb channel, lower 4LSB is -+ * forced to zeros. Typically set to 0 RGB and -+ * 0x80000 YCbCr. -+ */ -+ -+ /*Set spatial dithering bit depth*/ -+ set_reg_field_value(depth_cntl_value, -+ params->flags.SPATIAL_DITHER_DEPTH, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_SPATIAL_DITHER_DEPTH); -+ -+ /* Set spatial dithering mode -+ * (default is Seed patterrn AAAA...) -+ */ -+ set_reg_field_value(depth_cntl_value, -+ params->flags.SPATIAL_DITHER_MODE, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_SPATIAL_DITHER_MODE); -+ -+ /*Reset only at startup*/ -+ set_reg_field_value(depth_cntl_value, -+ params->flags.FRAME_RANDOM, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_RGB_RANDOM_ENABLE); -+ -+ /*Set RGB data dithered with x^28+x^3+1*/ -+ set_reg_field_value(depth_cntl_value, -+ params->flags.RGB_RANDOM, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_RGB_RANDOM_ENABLE); -+ -+ /*Disable High pass filter*/ -+ set_reg_field_value(depth_cntl_value, -+ params->flags.HIGHPASS_RANDOM, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_HIGHPASS_RANDOM_ENABLE); -+ -+ /*Enable spatial dithering*/ -+ set_reg_field_value(depth_cntl_value, -+ 1, -+ FMT_BIT_DEPTH_CONTROL, -+ FMT_SPATIAL_DITHER_EN); -+ -+ addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); -+ dal_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 = dal_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); -+ -+ dal_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); -+ dal_write_reg(opp110->base.ctx, addr, 0); -+ /*Set s matrix*/ -+ addr = FMT_REG( -+ mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); -+ dal_write_reg(opp110->base.ctx, addr, 0); -+ /*Set t matrix*/ -+ addr = FMT_REG( -+ mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); -+ dal_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); -+ dal_write_reg(opp110->base.ctx, addr, value); -+ -+} -+ -+/** -+ * Set Clamping -+ * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) -+ * 1 for 8 bpc -+ * 2 for 10 bpc -+ * 3 for 12 bpc -+ * 7 for programable -+ * 2) Enable clamp if Limited range requested -+ */ -+static void set_clamping( -+ struct dce110_opp *opp110, -+ const struct clamping_and_pixel_encoding_params *params) -+{ -+ uint32_t clamp_cntl_value = 0; -+ uint32_t red_clamp_value = 0; -+ uint32_t green_clamp_value = 0; -+ uint32_t blue_clamp_value = 0; -+ uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); -+ -+ clamp_cntl_value = dal_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); -+ dal_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); -+ dal_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); -+ dal_write_reg(opp110->base.ctx, addr, blue_clamp_value); -+ -+ break; -+ -+ default: -+ break; -+ } -+ -+ addr = FMT_REG(mmFMT_CLAMP_CNTL); -+ /*Set clamp control*/ -+ dal_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 = dal_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); -+ } -+ dal_write_reg(opp110->base.ctx, addr, fmt_cntl_value); -+ -+} -+ -+void dce110_opp_program_bit_depth_reduction( -+ struct output_pixel_processor *opp, -+ const struct bit_depth_reduction_params *params) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ -+ set_truncation(opp110, params); -+ set_spatial_dither(opp110, params); -+ set_temporal_dither(opp110, params); -+} -+ -+void dce110_opp_program_clamping_and_pixel_encoding( -+ struct output_pixel_processor *opp, -+ const struct clamping_and_pixel_encoding_params *params) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ -+ set_clamping(opp110, params); -+ set_pixel_encoding(opp110, params); -+} -+ -+void dce110_opp_set_dyn_expansion( -+ struct output_pixel_processor *opp, -+ enum color_space color_sp, -+ enum dc_color_depth color_dpth, -+ enum signal_type signal) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ uint32_t value; -+ bool enable_dyn_exp = false; -+ uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); -+ -+ value = dal_read_reg(opp->ctx, addr); -+ -+ set_reg_field_value(value, 0, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); -+ set_reg_field_value(value, 0, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); -+ -+ /* From HW programming guide: -+ FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output -+ FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ -+ if (color_sp == COLOR_SPACE_SRGB_FULL_RANGE) -+ enable_dyn_exp = true; -+ -+ /*00 - 10-bit -> 12-bit dynamic expansion*/ -+ /*01 - 8-bit -> 12-bit dynamic expansion*/ -+ if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { -+ switch (color_dpth) { -+ case COLOR_DEPTH_888: -+ set_reg_field_value(value, enable_dyn_exp ? 1:0, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); -+ set_reg_field_value(value, 1, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); -+ break; -+ case COLOR_DEPTH_101010: -+ set_reg_field_value(value, enable_dyn_exp ? 1:0, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); -+ set_reg_field_value(value, 0, -+ FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); -+ break; -+ case COLOR_DEPTH_121212: -+ break; -+ default: -+ break; -+ } -+ } -+ -+ dal_write_reg(opp->ctx, addr, value); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c -new file mode 100644 -index 0000000..4cba172 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c -@@ -0,0 +1,2473 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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" -+ -+#define DCP_REG(reg)\ -+ (reg + opp110->offsets.dcp_offset) -+ -+#define DCFE_REG(reg)\ -+ (reg + opp110->offsets.dcfe_offset) -+ -+enum { -+ MAX_PWL_ENTRY = 128, -+ MAX_REGIONS_NUMBER = 16 -+ -+}; -+ -+struct curve_config { -+ uint32_t offset; -+ int8_t segments[MAX_REGIONS_NUMBER]; -+ int8_t begin; -+}; -+ -+/* BASE */ -+static bool find_software_points( -+ struct dce110_opp *opp110, -+ struct fixed31_32 hw_point, -+ enum channel_name channel, -+ uint32_t *index_to_start, -+ uint32_t *index_left, -+ uint32_t *index_right, -+ enum hw_point_position *pos) -+{ -+ const uint32_t max_number = -+ RGB_256X3X16 + opp110->regamma.extra_points; -+ -+ struct fixed31_32 left, right; -+ -+ uint32_t i = *index_to_start; -+ -+ while (i < max_number) { -+ if (channel == CHANNEL_NAME_RED) { -+ left = opp110-> -+ regamma.axis_x_256[i].r; -+ -+ if (i < max_number - 1) -+ right = opp110-> -+ regamma.axis_x_256[i + 1].r; -+ else -+ right = opp110-> -+ regamma.axis_x_256[max_number - 1].r; -+ } else if (channel == CHANNEL_NAME_GREEN) { -+ left = opp110->regamma.axis_x_256[i].g; -+ -+ if (i < max_number - 1) -+ right = opp110-> -+ regamma.axis_x_256[i + 1].g; -+ else -+ right = opp110-> -+ regamma.axis_x_256[max_number - 1].g; -+ } else { -+ left = opp110->regamma.axis_x_256[i].b; -+ -+ if (i < max_number - 1) -+ right = opp110-> -+ regamma.axis_x_256[i + 1].b; -+ else -+ right = opp110-> -+ regamma.axis_x_256[max_number - 1].b; -+ } -+ -+ if (dal_fixed31_32_le(left, hw_point) && -+ dal_fixed31_32_le(hw_point, right)) { -+ *index_to_start = i; -+ *index_left = i; -+ -+ if (i < max_number - 1) -+ *index_right = i + 1; -+ else -+ *index_right = max_number - 1; -+ -+ *pos = HW_POINT_POSITION_MIDDLE; -+ -+ return true; -+ } else if ((i == *index_to_start) && -+ dal_fixed31_32_le(hw_point, left)) { -+ *index_to_start = i; -+ *index_left = i; -+ *index_right = i; -+ -+ *pos = HW_POINT_POSITION_LEFT; -+ -+ return true; -+ } else if ((i == max_number - 1) && -+ dal_fixed31_32_le(right, hw_point)) { -+ *index_to_start = i; -+ *index_left = i; -+ *index_right = i; -+ -+ *pos = HW_POINT_POSITION_RIGHT; -+ -+ return true; -+ } -+ -+ ++i; -+ } -+ -+ return false; -+} -+ -+static bool find_software_points_dx( -+ struct dce110_opp *opp110, -+ struct fixed31_32 hw_point, -+ enum channel_name channel, -+ uint32_t *index_to_start, -+ uint32_t *index_left, -+ uint32_t *index_right, -+ enum hw_point_position *pos) -+{ -+ const uint32_t max_number = DX_GAMMA_RAMP_MAX + -+ opp110->regamma.extra_points; -+ -+ struct fixed31_32 left, right; -+ -+ uint32_t i = *index_to_start; -+ -+ while (i < max_number) { -+ if (channel == CHANNEL_NAME_RED) { -+ left = opp110->regamma.axis_x_1025[i].r; -+ -+ if (i < DX_GAMMA_RAMP_MAX - 1) -+ right = opp110-> -+ regamma.axis_x_1025[i + 1].r; -+ else -+ right = opp110-> -+ regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].r; -+ } else if (channel == CHANNEL_NAME_GREEN) { -+ left = opp110->regamma.axis_x_1025[i].g; -+ -+ if (i < DX_GAMMA_RAMP_MAX - 1) -+ right = opp110-> -+ regamma.axis_x_1025[i + 1].g; -+ else -+ right = opp110-> -+ regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].g; -+ } else { -+ left = opp110->regamma.axis_x_1025[i].b; -+ -+ if (i < DX_GAMMA_RAMP_MAX - 1) -+ right = opp110-> -+ regamma.axis_x_1025[i + 1].b; -+ else -+ right = opp110-> -+ regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].b; -+ } -+ -+ if (dal_fixed31_32_le(left, hw_point) && -+ dal_fixed31_32_le(hw_point, right)) { -+ *index_to_start = i; -+ *index_left = i; -+ -+ if (i < DX_GAMMA_RAMP_MAX - 1) -+ *index_right = i + 1; -+ else -+ *index_right = DX_GAMMA_RAMP_MAX - 1; -+ -+ *pos = HW_POINT_POSITION_MIDDLE; -+ -+ return true; -+ } else if ((i == *index_to_start) && -+ dal_fixed31_32_le(hw_point, left)) { -+ *index_to_start = i; -+ *index_left = i; -+ *index_right = i; -+ -+ *pos = HW_POINT_POSITION_LEFT; -+ -+ return true; -+ } else if ((i == max_number - 1) && -+ dal_fixed31_32_le(right, hw_point)) { -+ *index_to_start = i; -+ *index_left = i; -+ *index_right = i; -+ -+ *pos = HW_POINT_POSITION_RIGHT; -+ -+ return true; -+ } -+ -+ ++i; -+ } -+ -+ return false; -+} -+ -+static bool build_custom_gamma_mapping_coefficients_worker( -+ struct dce110_opp *opp110, -+ struct pixel_gamma_point *coeff, -+ enum channel_name channel, -+ uint32_t number_of_points, -+ enum pixel_format pixel_format) -+{ -+ uint32_t i = 0; -+ -+ while (i <= number_of_points) { -+ struct fixed31_32 coord_x; -+ -+ uint32_t index_to_start = 0; -+ uint32_t index_left = 0; -+ uint32_t index_right = 0; -+ -+ enum hw_point_position hw_pos; -+ -+ struct gamma_point *point; -+ -+ struct fixed31_32 left_pos; -+ struct fixed31_32 right_pos; -+ -+ if (pixel_format == PIXEL_FORMAT_FP16) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].adjusted_x; -+ else if (channel == CHANNEL_NAME_RED) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_red; -+ else if (channel == CHANNEL_NAME_GREEN) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_green; -+ else -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_blue; -+ -+ if (!find_software_points( -+ opp110, coord_x, channel, -+ &index_to_start, &index_left, &index_right, &hw_pos)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (index_left >= RGB_256X3X16 + -+ opp110->regamma.extra_points) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (index_right >= RGB_256X3X16 + -+ opp110->regamma.extra_points) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (channel == CHANNEL_NAME_RED) { -+ point = &coeff[i].r; -+ -+ left_pos = opp110-> -+ regamma.axis_x_256[index_left].r; -+ right_pos = opp110-> -+ regamma.axis_x_256[index_right].r; -+ } else if (channel == CHANNEL_NAME_GREEN) { -+ point = &coeff[i].g; -+ -+ left_pos = opp110-> -+ regamma.axis_x_256[index_left].g; -+ right_pos = opp110-> -+ regamma.axis_x_256[index_right].g; -+ } else { -+ point = &coeff[i].b; -+ -+ left_pos = opp110-> -+ regamma.axis_x_256[index_left].b; -+ right_pos = opp110-> -+ regamma.axis_x_256[index_right].b; -+ } -+ -+ if (hw_pos == HW_POINT_POSITION_MIDDLE) -+ point->coeff = dal_fixed31_32_div( -+ dal_fixed31_32_sub( -+ coord_x, -+ left_pos), -+ dal_fixed31_32_sub( -+ right_pos, -+ left_pos)); -+ else if (hw_pos == HW_POINT_POSITION_LEFT) -+ point->coeff = opp110->regamma.x_min; -+ else if (hw_pos == HW_POINT_POSITION_RIGHT) -+ point->coeff = opp110->regamma.x_max2; -+ else { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ point->left_index = index_left; -+ point->right_index = index_right; -+ point->pos = hw_pos; -+ -+ ++i; -+ } -+ -+ return true; -+} -+ -+static inline bool build_custom_gamma_mapping_coefficients( -+ struct dce110_opp *opp110, -+ enum channel_name channel, -+ uint32_t number_of_points, -+ enum pixel_format pixel_format) -+{ -+ return build_custom_gamma_mapping_coefficients_worker( -+ opp110, opp110->regamma.coeff128, channel, -+ number_of_points, pixel_format); -+} -+ -+static inline bool build_oem_custom_gamma_mapping_coefficients( -+ struct dce110_opp *opp110, -+ enum channel_name channel, -+ uint32_t number_of_points, -+ enum pixel_format pixel_format) -+{ -+ return build_custom_gamma_mapping_coefficients_worker( -+ opp110, opp110->regamma.coeff128_oem, channel, -+ number_of_points, pixel_format); -+} -+ -+static bool build_custom_dx_gamma_mapping_coefficients( -+ struct dce110_opp *opp110, -+ enum channel_name channel, -+ uint32_t number_of_points, -+ enum pixel_format pixel_format) -+{ -+ uint32_t i = 0; -+ -+ while (i <= number_of_points) { -+ struct fixed31_32 coord_x; -+ -+ uint32_t index_to_start = 0; -+ uint32_t index_left = 0; -+ uint32_t index_right = 0; -+ -+ enum hw_point_position hw_pos; -+ -+ struct gamma_point *point; -+ -+ struct fixed31_32 left_pos; -+ struct fixed31_32 right_pos; -+ -+ if (pixel_format == PIXEL_FORMAT_FP16) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].adjusted_x; -+ else if (channel == CHANNEL_NAME_RED) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_red; -+ else if (channel == CHANNEL_NAME_GREEN) -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_green; -+ else -+ coord_x = opp110-> -+ regamma.coordinates_x[i].regamma_y_blue; -+ -+ if (!find_software_points_dx( -+ opp110, coord_x, channel, -+ &index_to_start, &index_left, &index_right, &hw_pos)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (index_left >= DX_GAMMA_RAMP_MAX + -+ opp110->regamma.extra_points) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (index_right >= DX_GAMMA_RAMP_MAX + -+ opp110->regamma.extra_points) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (channel == CHANNEL_NAME_RED) { -+ point = &opp110->regamma.coeff128_dx[i].r; -+ -+ left_pos = opp110-> -+ regamma.axis_x_1025[index_left].r; -+ right_pos = opp110-> -+ regamma.axis_x_1025[index_right].r; -+ } else if (channel == CHANNEL_NAME_GREEN) { -+ point = &opp110->regamma.coeff128_dx[i].g; -+ -+ left_pos = opp110-> -+ regamma.axis_x_1025[index_left].g; -+ right_pos = opp110-> -+ regamma.axis_x_1025[index_right].g; -+ } else { -+ point = &opp110->regamma.coeff128_dx[i].b; -+ -+ left_pos = opp110-> -+ regamma.axis_x_1025[index_left].b; -+ right_pos = opp110-> -+ regamma.axis_x_1025[index_right].b; -+ } -+ -+ if (hw_pos == HW_POINT_POSITION_MIDDLE) -+ point->coeff = dal_fixed31_32_div( -+ dal_fixed31_32_sub( -+ coord_x, -+ left_pos), -+ dal_fixed31_32_sub( -+ right_pos, -+ left_pos)); -+ else if (hw_pos == HW_POINT_POSITION_LEFT) -+ point->coeff = opp110->regamma.x_min; -+ else if (hw_pos == HW_POINT_POSITION_RIGHT) -+ point->coeff = opp110->regamma.x_max2; -+ else { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ point->left_index = index_left; -+ point->right_index = index_right; -+ point->pos = hw_pos; -+ -+ ++i; -+ } -+ -+ return true; -+} -+ -+static struct fixed31_32 calculate_mapped_value( -+ struct dce110_opp *opp110, -+ struct pwl_float_data *rgb, -+ const struct pixel_gamma_point *coeff, -+ enum channel_name channel, -+ uint32_t max_index) -+{ -+ const struct gamma_point *point; -+ -+ struct fixed31_32 result; -+ -+ if (channel == CHANNEL_NAME_RED) -+ point = &coeff->r; -+ else if (channel == CHANNEL_NAME_GREEN) -+ point = &coeff->g; -+ else -+ point = &coeff->b; -+ -+ if ((point->left_index < 0) || (point->left_index > max_index)) { -+ BREAK_TO_DEBUGGER(); -+ return dal_fixed31_32_zero; -+ } -+ -+ if ((point->right_index < 0) || (point->right_index > max_index)) { -+ BREAK_TO_DEBUGGER(); -+ return dal_fixed31_32_zero; -+ } -+ -+ if (point->pos == HW_POINT_POSITION_MIDDLE) -+ if (channel == CHANNEL_NAME_RED) -+ result = dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ point->coeff, -+ dal_fixed31_32_sub( -+ rgb[point->right_index].r, -+ rgb[point->left_index].r)), -+ rgb[point->left_index].r); -+ else if (channel == CHANNEL_NAME_GREEN) -+ result = dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ point->coeff, -+ dal_fixed31_32_sub( -+ rgb[point->right_index].g, -+ rgb[point->left_index].g)), -+ rgb[point->left_index].g); -+ else -+ result = dal_fixed31_32_add( -+ dal_fixed31_32_mul( -+ point->coeff, -+ dal_fixed31_32_sub( -+ rgb[point->right_index].b, -+ rgb[point->left_index].b)), -+ rgb[point->left_index].b); -+ else if (point->pos == HW_POINT_POSITION_LEFT) { -+ BREAK_TO_DEBUGGER(); -+ result = opp110->regamma.x_min; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ result = opp110->regamma.x_max1; -+ } -+ -+ return result; -+} -+ -+static inline struct fixed31_32 calculate_regamma_user_mapped_value( -+ struct dce110_opp *opp110, -+ const struct pixel_gamma_point *coeff, -+ enum channel_name channel, -+ uint32_t max_index) -+{ -+ return calculate_mapped_value( -+ opp110, opp110->regamma.rgb_oem, -+ coeff, channel, max_index); -+} -+ -+static inline struct fixed31_32 calculate_user_mapped_value( -+ struct dce110_opp *opp110, -+ const struct pixel_gamma_point *coeff, -+ enum channel_name channel, -+ uint32_t max_index) -+{ -+ return calculate_mapped_value( -+ opp110, opp110->regamma.rgb_user, -+ coeff, channel, max_index); -+} -+ -+static inline struct fixed31_32 calculate_oem_mapped_value( -+ struct dce110_opp *opp110, -+ uint32_t index, -+ enum channel_name channel, -+ uint32_t max_index) -+{ -+ return calculate_regamma_user_mapped_value( -+ opp110, opp110->regamma.coeff128_oem + -+ index, channel, max_index); -+} -+ -+static void scale_oem_gamma( -+ struct dce110_opp *opp110, -+ const struct regamma_ramp *regamma_ramp) -+{ -+ const uint16_t max_driver = 0xFFFF; -+ const uint16_t max_os = 0xFF00; -+ -+ uint16_t scale = max_os; -+ -+ uint32_t i; -+ -+ struct pwl_float_data *rgb = opp110->regamma.rgb_oem; -+ struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; -+ -+ /* find OEM maximum */ -+ -+ i = 0; -+ -+ do { -+ if ((regamma_ramp->gamma[i] > max_os) || -+ (regamma_ramp->gamma[i + RGB_256X3X16] > max_os) || -+ (regamma_ramp->gamma[i + 2 * RGB_256X3X16] > max_os)) { -+ scale = max_driver; -+ break; -+ } -+ -+ ++i; -+ } while (i != RGB_256X3X16); -+ -+ /* scale */ -+ -+ i = 0; -+ -+ do { -+ rgb->r = dal_fixed31_32_div_int( -+ dal_fixed31_32_from_int( -+ regamma_ramp->gamma[i]), -+ scale); -+ rgb->g = dal_fixed31_32_div_int( -+ dal_fixed31_32_from_int( -+ regamma_ramp->gamma[i + RGB_256X3X16]), -+ scale); -+ rgb->b = dal_fixed31_32_div_int( -+ dal_fixed31_32_from_int( -+ regamma_ramp->gamma[i + 2 * RGB_256X3X16]), -+ scale); -+ -+ ++rgb; -+ ++i; -+ } while (i != RGB_256X3X16); -+ -+ /* add 3 extra points, 2 physical plus 1 virtual */ -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider1); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider1); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider1); -+ -+ ++rgb; -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider2); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider2); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider2); -+ -+ ++rgb; -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider3); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider3); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider3); -+} -+ -+static inline void copy_rgb_regamma_to_coordinates_x( -+ struct dce110_opp *opp110) -+{ -+ struct hw_x_point *coords = opp110->regamma.coordinates_x; -+ const struct pwl_float_data_ex *rgb_regamma = -+ opp110->regamma.rgb_regamma; -+ -+ uint32_t i = 0; -+ -+ while (i <= opp110->regamma.hw_points_num) { -+ coords->regamma_y_red = rgb_regamma->r; -+ coords->regamma_y_green = rgb_regamma->g; -+ coords->regamma_y_blue = rgb_regamma->b; -+ -+ ++coords; -+ ++rgb_regamma; -+ ++i; -+ } -+} -+ -+static bool calculate_interpolated_hardware_curve( -+ struct dce110_opp *opp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ struct pwl_result_data *rgb_resulted = -+ opp110->regamma.rgb_resulted; -+ -+ const struct pixel_gamma_point *coeff; -+ uint32_t max_entries = opp110->regamma.extra_points - 1; -+ -+ uint32_t i = 0; -+ -+ if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) { -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_RED, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_GREEN, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_BLUE, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ coeff = opp110->regamma.coeff128; -+ max_entries += RGB_256X3X16; -+ } else if (gamma_ramp->type == GAMMA_RAMP_DXGI_1) { -+ if (!build_custom_dx_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_RED, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_dx_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_GREEN, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_dx_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_BLUE, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ coeff = opp110->regamma.coeff128_dx; -+ max_entries += DX_GAMMA_RAMP_MAX; -+ } else { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (i <= opp110->regamma.hw_points_num) { -+ rgb_resulted->red = calculate_user_mapped_value( -+ opp110, coeff, CHANNEL_NAME_RED, max_entries); -+ rgb_resulted->green = calculate_user_mapped_value( -+ opp110, coeff, CHANNEL_NAME_GREEN, max_entries); -+ rgb_resulted->blue = calculate_user_mapped_value( -+ opp110, coeff, CHANNEL_NAME_BLUE, max_entries); -+ -+ ++coeff; -+ ++rgb_resulted; -+ ++i; -+ } -+ -+ return true; -+} -+ -+static void map_standard_regamma_hw_to_x_user( -+ struct dce110_opp *opp110, -+ enum gamma_ramp_type type, -+ const struct gamma_parameters *params) -+{ -+ struct pwl_result_data *rgb_resulted = -+ opp110->regamma.rgb_resulted; -+ const struct pwl_float_data_ex *rgb_regamma = -+ opp110->regamma.rgb_regamma; -+ -+ uint32_t i = 0; -+ -+ while (i <= opp110->regamma.hw_points_num) { -+ rgb_resulted->red = rgb_regamma->r; -+ rgb_resulted->green = rgb_regamma->g; -+ rgb_resulted->blue = rgb_regamma->b; -+ -+ ++rgb_resulted; -+ ++rgb_regamma; -+ ++i; -+ } -+} -+ -+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user( -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ -+ if (params->regamma.features.bits.GAMMA_RAMP_ARRAY || -+ params->regamma.features.bits.APPLY_DEGAMMA) { -+ -+ const uint32_t max_entries = -+ RGB_256X3X16 + opp110->regamma.extra_points - 1; -+ -+ const struct pixel_gamma_point *coeff = -+ opp110->regamma.coeff128; -+ struct pwl_result_data *rgb_resulted = -+ opp110->regamma.rgb_resulted; -+ -+ uint32_t i = 0; -+ -+ scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); -+ -+ copy_rgb_regamma_to_coordinates_x(opp110); -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_RED, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_GREEN, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_BLUE, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (i <= opp110->regamma.hw_points_num) { -+ rgb_resulted->red = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_RED, max_entries); -+ rgb_resulted->green = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_GREEN, max_entries); -+ rgb_resulted->blue = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_BLUE, max_entries); -+ -+ ++coeff; -+ ++rgb_resulted; -+ ++i; -+ } -+ } else -+ map_standard_regamma_hw_to_x_user(opp110, -+ gamma_ramp->type, -+ params); -+ -+ return true; -+} -+ -+static bool map_regamma_hw_to_x_user( -+ struct dce110_opp *opp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ /* setup to spare calculated ideal regamma values */ -+ if (params->regamma.features.bits.GAMMA_RAMP_ARRAY || -+ params->regamma.features.bits.APPLY_DEGAMMA) { -+ -+ const uint32_t max_entries = -+ RGB_256X3X16 + opp110->regamma.extra_points - 1; -+ -+ const struct pixel_gamma_point *coeff = -+ opp110->regamma.coeff128; -+ struct hw_x_point *coords = -+ opp110->regamma.coordinates_x; -+ -+ uint32_t i = 0; -+ -+ scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); -+ -+ copy_rgb_regamma_to_coordinates_x(opp110); -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_RED, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_GREEN, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_BLUE, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ while (i <= opp110->regamma.hw_points_num) { -+ coords->regamma_y_red = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_RED, max_entries); -+ coords->regamma_y_green = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_GREEN, max_entries); -+ coords->regamma_y_blue = -+ calculate_regamma_user_mapped_value(opp110, -+ coeff, -+ CHANNEL_NAME_BLUE, max_entries); -+ -+ ++coeff; -+ ++coords; -+ ++i; -+ } -+ } else { -+ copy_rgb_regamma_to_coordinates_x(opp110); -+ } -+ -+ return calculate_interpolated_hardware_curve(opp110, gamma_ramp, -+ params); -+} -+ -+static void build_regamma_coefficients( -+ const struct regamma_lut *regamma, -+ bool is_degamma_srgb, -+ struct gamma_coefficients *coefficients) -+{ -+ /* sRGB should apply 2.4 */ -+ static const int32_t numerator01[3] = { 31308, 31308, 31308 }; -+ static const int32_t numerator02[3] = { 12920, 12920, 12920 }; -+ static const int32_t numerator03[3] = { 55, 55, 55 }; -+ static const int32_t numerator04[3] = { 55, 55, 55 }; -+ static const int32_t numerator05[3] = { 2400, 2400, 2400 }; -+ -+ /* Non-sRGB should apply 2.2 */ -+ static const int32_t numerator11[3] = { 180000, 180000, 180000 }; -+ static const int32_t numerator12[3] = { 4500, 4500, 4500 }; -+ static const int32_t numerator13[3] = { 99, 99, 99 }; -+ static const int32_t numerator14[3] = { 99, 99, 99 }; -+ static const int32_t numerator15[3] = { 2200, 2200, 2200 }; -+ -+ const int32_t *numerator1; -+ const int32_t *numerator2; -+ const int32_t *numerator3; -+ const int32_t *numerator4; -+ const int32_t *numerator5; -+ -+ uint32_t i = 0; -+ -+ if (!regamma->features.bits.GAMMA_RAMP_ARRAY) { -+ numerator1 = regamma->gamma_coeff.a0; -+ numerator2 = regamma->gamma_coeff.a1; -+ numerator3 = regamma->gamma_coeff.a2; -+ numerator4 = regamma->gamma_coeff.a3; -+ numerator5 = regamma->gamma_coeff.gamma; -+ } else if (is_degamma_srgb) { -+ numerator1 = numerator01; -+ numerator2 = numerator02; -+ numerator3 = numerator03; -+ numerator4 = numerator04; -+ numerator5 = numerator05; -+ } else { -+ numerator1 = numerator11; -+ numerator2 = numerator12; -+ numerator3 = numerator13; -+ numerator4 = numerator14; -+ numerator5 = numerator15; -+ } -+ -+ do { -+ coefficients->a0[i] = dal_fixed31_32_from_fraction( -+ numerator1[i], 10000000); -+ coefficients->a1[i] = dal_fixed31_32_from_fraction( -+ numerator2[i], 1000); -+ coefficients->a2[i] = dal_fixed31_32_from_fraction( -+ numerator3[i], 1000); -+ coefficients->a3[i] = dal_fixed31_32_from_fraction( -+ numerator4[i], 1000); -+ coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( -+ numerator5[i], 1000); -+ -+ ++i; -+ } while (i != ARRAY_SIZE(regamma->gamma_coeff.a0)); -+} -+ -+static struct fixed31_32 translate_from_linear_space( -+ struct fixed31_32 arg, -+ struct fixed31_32 a0, -+ struct fixed31_32 a1, -+ struct fixed31_32 a2, -+ struct fixed31_32 a3, -+ struct fixed31_32 gamma) -+{ -+ const struct fixed31_32 one = dal_fixed31_32_from_int(1); -+ -+ if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) -+ return dal_fixed31_32_sub( -+ a2, -+ dal_fixed31_32_mul( -+ dal_fixed31_32_add( -+ one, -+ a3), -+ dal_fixed31_32_pow( -+ dal_fixed31_32_neg(arg), -+ dal_fixed31_32_recip(gamma)))); -+ else if (dal_fixed31_32_le(a0, arg)) -+ return dal_fixed31_32_sub( -+ dal_fixed31_32_mul( -+ dal_fixed31_32_add( -+ one, -+ a3), -+ dal_fixed31_32_pow( -+ arg, -+ dal_fixed31_32_recip(gamma))), -+ a2); -+ else -+ return dal_fixed31_32_mul( -+ arg, -+ a1); -+} -+ -+static inline struct fixed31_32 translate_from_linear_space_ex( -+ struct fixed31_32 arg, -+ struct gamma_coefficients *coeff, -+ uint32_t color_index) -+{ -+ return translate_from_linear_space( -+ arg, -+ coeff->a0[color_index], -+ coeff->a1[color_index], -+ coeff->a2[color_index], -+ coeff->a3[color_index], -+ coeff->user_gamma[color_index]); -+} -+ -+static bool build_regamma_curve( -+ struct dce110_opp *opp110, -+ const struct gamma_parameters *params) -+{ -+ struct pwl_float_data_ex *rgb = opp110->regamma.rgb_regamma; -+ -+ uint32_t i; -+ -+ if (!params->regamma.features.bits.GAMMA_RAMP_ARRAY && -+ params->regamma.features.bits.APPLY_DEGAMMA) { -+ struct gamma_coefficients coeff; -+ -+ struct hw_x_point *coord_x = -+ opp110->regamma.coordinates_x; -+ -+ build_regamma_coefficients( -+ ¶ms->regamma, -+ params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB, -+ &coeff); -+ -+ /* Use opp110->regamma.coordinates_x to retrieve -+ * coordinates chosen base on given user curve (future task). -+ * The x values are exponentially distributed and currently -+ * it is hard-coded, the user curve shape is ignored. -+ * The future task is to recalculate opp110- -+ * regamma.coordinates_x based on input/user curve, -+ * translation from 256/1025 to 128 pwl points. -+ */ -+ -+ i = 0; -+ -+ while (i != opp110->regamma.hw_points_num + 1) { -+ rgb->r = translate_from_linear_space_ex( -+ coord_x->adjusted_x, &coeff, 0); -+ rgb->g = translate_from_linear_space_ex( -+ coord_x->adjusted_x, &coeff, 1); -+ rgb->b = translate_from_linear_space_ex( -+ coord_x->adjusted_x, &coeff, 2); -+ -+ ++coord_x; -+ ++rgb; -+ ++i; -+ } -+ } else { -+ const uint32_t max_entries = -+ RGB_256X3X16 + opp110->regamma.extra_points - 1; -+ -+ /* interpolate between 256 input points and output 185 points */ -+ -+ scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); -+ -+ if (!build_oem_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_RED, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_oem_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_GREEN, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!build_oem_custom_gamma_mapping_coefficients( -+ opp110, CHANNEL_NAME_BLUE, -+ opp110->regamma.hw_points_num, -+ params->surface_pixel_format)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ i = 0; -+ -+ while (i != opp110->regamma.hw_points_num + 1) { -+ rgb->r = calculate_oem_mapped_value( -+ opp110, i, CHANNEL_NAME_RED, max_entries); -+ rgb->g = calculate_oem_mapped_value( -+ opp110, i, CHANNEL_NAME_GREEN, max_entries); -+ rgb->b = calculate_oem_mapped_value( -+ opp110, i, CHANNEL_NAME_BLUE, max_entries); -+ ++rgb; -+ ++i; -+ } -+ } -+ -+ return true; -+} -+ -+static void build_new_custom_resulted_curve( -+ struct dce110_opp *opp110, -+ const struct gamma_parameters *params) -+{ -+ struct pwl_result_data *rgb = opp110->regamma.rgb_resulted; -+ struct pwl_result_data *rgb_plus_1 = rgb + 1; -+ -+ uint32_t i; -+ -+ i = 0; -+ -+ while (i != opp110->regamma.hw_points_num + 1) { -+ rgb->red = dal_fixed31_32_clamp( -+ rgb->red, opp110->regamma.x_min, -+ opp110->regamma.x_max1); -+ rgb->green = dal_fixed31_32_clamp( -+ rgb->green, opp110->regamma.x_min, -+ opp110->regamma.x_max1); -+ rgb->blue = dal_fixed31_32_clamp( -+ rgb->blue, opp110->regamma.x_min, -+ opp110->regamma.x_max1); -+ -+ ++rgb; -+ ++i; -+ } -+ -+ rgb = opp110->regamma.rgb_resulted; -+ -+ i = 1; -+ -+ while (i != opp110->regamma.hw_points_num + 1) { -+ if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) -+ rgb_plus_1->red = rgb->red; -+ if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) -+ rgb_plus_1->green = rgb->green; -+ if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) -+ rgb_plus_1->blue = rgb->blue; -+ -+ rgb->delta_red = dal_fixed31_32_sub( -+ rgb_plus_1->red, -+ rgb->red); -+ rgb->delta_green = dal_fixed31_32_sub( -+ rgb_plus_1->green, -+ rgb->green); -+ rgb->delta_blue = dal_fixed31_32_sub( -+ rgb_plus_1->blue, -+ rgb->blue); -+ -+ ++rgb_plus_1; -+ ++rgb; -+ ++i; -+ } -+} -+ -+static bool rebuild_curve_configuration_magic( -+ struct dce110_opp *opp110) -+{ -+ const struct fixed31_32 magic_number = -+ dal_fixed31_32_from_fraction(249, 1000); -+ -+ struct fixed31_32 y_r; -+ struct fixed31_32 y_g; -+ struct fixed31_32 y_b; -+ -+ struct fixed31_32 y1_min; -+ struct fixed31_32 y2_max; -+ struct fixed31_32 y3_max; -+ -+ y_r = opp110->regamma.rgb_resulted[0].red; -+ y_g = opp110->regamma.rgb_resulted[0].green; -+ y_b = opp110->regamma.rgb_resulted[0].blue; -+ -+ y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); -+ -+ opp110->regamma.arr_points[0].x = -+ opp110->regamma.coordinates_x[0].adjusted_x; -+ opp110->regamma.arr_points[0].y = y1_min; -+ opp110->regamma.arr_points[0].slope = dal_fixed31_32_div( -+ opp110->regamma.arr_points[0].y, -+ opp110->regamma.arr_points[0].x); -+ -+ opp110->regamma.arr_points[1].x = dal_fixed31_32_add( -+ opp110->regamma.coordinates_x -+ [opp110->regamma.hw_points_num - 1].adjusted_x, -+ magic_number); -+ -+ opp110->regamma.arr_points[2].x = -+ opp110->regamma.arr_points[1].x; -+ -+ y_r = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num - 1].red; -+ y_g = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num - 1].green; -+ y_b = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num - 1].blue; -+ -+ y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); -+ -+ opp110->regamma.arr_points[1].y = y2_max; -+ -+ y_r = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num].red; -+ y_g = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num].green; -+ y_b = opp110->regamma.rgb_resulted -+ [opp110->regamma.hw_points_num].blue; -+ -+ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); -+ -+ opp110->regamma.arr_points[2].y = y3_max; -+ -+ opp110->regamma.arr_points[2].slope = dal_fixed31_32_one; -+ -+ return true; -+} -+ -+static bool build_custom_float( -+ struct fixed31_32 value, -+ const struct custom_float_format *format, -+ bool *negative, -+ uint32_t *mantissa, -+ uint32_t *exponenta) -+{ -+ uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; -+ -+ const struct fixed31_32 mantissa_constant_plus_max_fraction = -+ dal_fixed31_32_from_fraction( -+ (1LL << (format->mantissa_bits + 1)) - 1, -+ 1LL << format->mantissa_bits); -+ -+ struct fixed31_32 mantiss; -+ -+ if (dal_fixed31_32_eq( -+ value, -+ dal_fixed31_32_zero)) { -+ *negative = false; -+ *mantissa = 0; -+ *exponenta = 0; -+ return true; -+ } -+ -+ if (dal_fixed31_32_lt( -+ value, -+ dal_fixed31_32_zero)) { -+ *negative = format->sign; -+ value = dal_fixed31_32_neg(value); -+ } else { -+ *negative = false; -+ } -+ -+ if (dal_fixed31_32_lt( -+ value, -+ dal_fixed31_32_one)) { -+ uint32_t i = 1; -+ -+ do { -+ value = dal_fixed31_32_shl(value, 1); -+ ++i; -+ } while (dal_fixed31_32_lt( -+ value, -+ dal_fixed31_32_one)); -+ -+ --i; -+ -+ if (exp_offset <= i) { -+ *mantissa = 0; -+ *exponenta = 0; -+ return true; -+ } -+ -+ *exponenta = exp_offset - i; -+ } else if (dal_fixed31_32_le( -+ mantissa_constant_plus_max_fraction, -+ value)) { -+ uint32_t i = 1; -+ -+ do { -+ value = dal_fixed31_32_shr(value, 1); -+ ++i; -+ } while (dal_fixed31_32_lt( -+ mantissa_constant_plus_max_fraction, -+ value)); -+ -+ *exponenta = exp_offset + i - 1; -+ } else { -+ *exponenta = exp_offset; -+ } -+ -+ mantiss = dal_fixed31_32_sub( -+ value, -+ dal_fixed31_32_one); -+ -+ if (dal_fixed31_32_lt( -+ mantiss, -+ dal_fixed31_32_zero) || -+ dal_fixed31_32_lt( -+ dal_fixed31_32_one, -+ mantiss)) -+ mantiss = dal_fixed31_32_zero; -+ else -+ mantiss = dal_fixed31_32_shl( -+ mantiss, -+ format->mantissa_bits); -+ -+ *mantissa = dal_fixed31_32_floor(mantiss); -+ -+ return true; -+} -+ -+static bool setup_custom_float( -+ const struct custom_float_format *format, -+ bool negative, -+ uint32_t mantissa, -+ uint32_t exponenta, -+ uint32_t *result) -+{ -+ uint32_t i = 0; -+ uint32_t j = 0; -+ -+ uint32_t value = 0; -+ -+ /* verification code: -+ * once calculation is ok we can remove it */ -+ -+ const uint32_t mantissa_mask = -+ (1 << (format->mantissa_bits + 1)) - 1; -+ -+ const uint32_t exponenta_mask = -+ (1 << (format->exponenta_bits + 1)) - 1; -+ -+ if (mantissa & ~mantissa_mask) { -+ BREAK_TO_DEBUGGER(); -+ mantissa = mantissa_mask; -+ } -+ -+ if (exponenta & ~exponenta_mask) { -+ BREAK_TO_DEBUGGER(); -+ exponenta = exponenta_mask; -+ } -+ -+ /* end of verification code */ -+ -+ while (i < format->mantissa_bits) { -+ uint32_t mask = 1 << i; -+ -+ if (mantissa & mask) -+ value |= mask; -+ -+ ++i; -+ } -+ -+ while (j < format->exponenta_bits) { -+ uint32_t mask = 1 << j; -+ -+ if (exponenta & mask) -+ value |= mask << i; -+ -+ ++j; -+ } -+ -+ if (negative && format->sign) -+ value |= 1 << (i + j); -+ -+ *result = value; -+ -+ return true; -+} -+ -+static bool convert_to_custom_float_format( -+ struct fixed31_32 value, -+ const struct custom_float_format *format, -+ uint32_t *result) -+{ -+ uint32_t mantissa; -+ uint32_t exponenta; -+ bool negative; -+ -+ return build_custom_float( -+ value, format, &negative, &mantissa, &exponenta) && -+ setup_custom_float( -+ format, negative, mantissa, exponenta, result); -+} -+ -+static bool convert_to_custom_float_format_ex( -+ struct fixed31_32 value, -+ const struct custom_float_format *format, -+ struct custom_float_value *result) -+{ -+ return build_custom_float( -+ value, format, -+ &result->negative, &result->mantissa, &result->exponenta) && -+ setup_custom_float( -+ format, result->negative, result->mantissa, result->exponenta, -+ &result->value); -+} -+ -+static bool convert_to_custom_float( -+ struct dce110_opp *opp110) -+{ -+ struct custom_float_format fmt; -+ -+ struct pwl_result_data *rgb = opp110->regamma.rgb_resulted; -+ -+ uint32_t i = 0; -+ -+ fmt.exponenta_bits = 6; -+ fmt.mantissa_bits = 12; -+ fmt.sign = true; -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[0].x, -+ &fmt, -+ &opp110->regamma.arr_points[0].custom_float_x)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[0].offset, -+ &fmt, -+ &opp110->regamma.arr_points[0].custom_float_offset)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[0].slope, -+ &fmt, -+ &opp110->regamma.arr_points[0].custom_float_slope)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ fmt.mantissa_bits = 10; -+ fmt.sign = false; -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[1].x, -+ &fmt, -+ &opp110->regamma.arr_points[1].custom_float_x)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[1].y, -+ &fmt, -+ &opp110->regamma.arr_points[1].custom_float_y)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ opp110->regamma.arr_points[2].slope, -+ &fmt, -+ &opp110->regamma.arr_points[2].custom_float_slope)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ fmt.mantissa_bits = 12; -+ fmt.sign = true; -+ -+ while (i != opp110->regamma.hw_points_num) { -+ if (!convert_to_custom_float_format( -+ rgb->red, -+ &fmt, -+ &rgb->red_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ rgb->green, -+ &fmt, -+ &rgb->green_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ rgb->blue, -+ &fmt, -+ &rgb->blue_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ rgb->delta_red, -+ &fmt, -+ &rgb->delta_red_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ rgb->delta_green, -+ &fmt, -+ &rgb->delta_green_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!convert_to_custom_float_format( -+ rgb->delta_blue, -+ &fmt, -+ &rgb->delta_blue_reg)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ ++rgb; -+ ++i; -+ } -+ -+ return true; -+} -+ -+static bool round_custom_float_6_12( -+ struct hw_x_point *x) -+{ -+ struct custom_float_format fmt; -+ -+ struct custom_float_value value; -+ -+ fmt.exponenta_bits = 6; -+ fmt.mantissa_bits = 12; -+ fmt.sign = true; -+ -+ if (!convert_to_custom_float_format_ex( -+ x->x, &fmt, &value)) -+ return false; -+ -+ x->adjusted_x = x->x; -+ -+ if (value.mantissa) { -+ BREAK_TO_DEBUGGER(); -+ -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool build_hw_curve_configuration( -+ const struct curve_config *curve_config, -+ struct gamma_curve *gamma_curve, -+ struct curve_points *curve_points, -+ struct hw_x_point *points, -+ uint32_t *number_of_points) -+{ -+ const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); -+ -+ int8_t i; -+ -+ uint8_t segments_calculation[8] = { 0 }; -+ -+ struct fixed31_32 region1 = dal_fixed31_32_zero; -+ struct fixed31_32 region2; -+ struct fixed31_32 increment; -+ -+ uint32_t index = 0; -+ uint32_t segments = 0; -+ uint32_t max_number; -+ -+ bool result = false; -+ -+ if (!number_of_points) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ max_number = *number_of_points; -+ -+ i = 0; -+ -+ while (i != max_regions_number) { -+ gamma_curve[i].offset = 0; -+ gamma_curve[i].segments_num = 0; -+ -+ ++i; -+ } -+ -+ i = 0; -+ -+ while (i != max_regions_number) { -+ /* number should go in uninterruptible sequence */ -+ if (curve_config->segments[i] == -1) -+ break; -+ -+ ASSERT(curve_config->segments[i] >= 0); -+ -+ segments += (1 << curve_config->segments[i]); -+ -+ ++i; -+ } -+ -+ if (segments > max_number) { -+ BREAK_TO_DEBUGGER(); -+ } else { -+ int32_t divisor; -+ uint32_t offset = 0; -+ int8_t begin = curve_config->begin; -+ int32_t region_number = 0; -+ -+ i = begin; -+ -+ while ((index < max_number) && -+ (region_number < max_regions_number) && -+ (i <= 1)) { -+ int32_t j = 0; -+ -+ segments = curve_config->segments[region_number]; -+ divisor = 1 << segments; -+ -+ if (segments == -1) { -+ if (i > 0) { -+ region1 = dal_fixed31_32_shl( -+ dal_fixed31_32_one, -+ i - 1); -+ region2 = dal_fixed31_32_shl( -+ dal_fixed31_32_one, -+ i); -+ } else { -+ region1 = dal_fixed31_32_shr( -+ dal_fixed31_32_one, -+ -(i - 1)); -+ region2 = dal_fixed31_32_shr( -+ dal_fixed31_32_one, -+ -i); -+ } -+ -+ break; -+ } -+ -+ if (i > -1) { -+ region1 = dal_fixed31_32_shl( -+ dal_fixed31_32_one, -+ i); -+ region2 = dal_fixed31_32_shl( -+ dal_fixed31_32_one, -+ i + 1); -+ } else { -+ region1 = dal_fixed31_32_shr( -+ dal_fixed31_32_one, -+ -i); -+ region2 = dal_fixed31_32_shr( -+ dal_fixed31_32_one, -+ -(i + 1)); -+ } -+ -+ gamma_curve[region_number].offset = offset; -+ gamma_curve[region_number].segments_num = segments; -+ -+ offset += divisor; -+ -+ ++segments_calculation[segments]; -+ -+ increment = dal_fixed31_32_div_int( -+ dal_fixed31_32_sub( -+ region2, -+ region1), -+ divisor); -+ -+ points[index].x = region1; -+ -+ round_custom_float_6_12(points + index); -+ -+ ++index; -+ ++region_number; -+ -+ while ((index < max_number) && (j < divisor - 1)) { -+ region1 = dal_fixed31_32_add( -+ region1, -+ increment); -+ -+ points[index].x = region1; -+ points[index].adjusted_x = region1; -+ -+ ++index; -+ ++j; -+ } -+ -+ ++i; -+ } -+ -+ points[index].x = region1; -+ -+ round_custom_float_6_12(points + index); -+ -+ *number_of_points = index; -+ -+ result = true; -+ } -+ -+ curve_points[0].x = points[0].adjusted_x; -+ curve_points[0].offset = dal_fixed31_32_zero; -+ -+ curve_points[1].x = points[index - 1].adjusted_x; -+ curve_points[1].offset = dal_fixed31_32_zero; -+ -+ curve_points[2].x = points[index].adjusted_x; -+ curve_points[2].offset = dal_fixed31_32_zero; -+ -+ return result; -+} -+ -+static bool setup_distribution_points( -+ struct dce110_opp *opp110) -+{ -+ uint32_t hw_points_num = MAX_PWL_ENTRY * 2; -+ -+ struct curve_config cfg; -+ -+ cfg.offset = 0; -+ -+ cfg.segments[0] = 3; -+ cfg.segments[1] = 4; -+ cfg.segments[2] = 4; -+ cfg.segments[3] = 4; -+ cfg.segments[4] = 4; -+ cfg.segments[5] = 4; -+ cfg.segments[6] = 4; -+ cfg.segments[7] = 4; -+ cfg.segments[8] = 5; -+ cfg.segments[9] = 5; -+ cfg.segments[10] = 0; -+ cfg.segments[11] = -1; -+ cfg.segments[12] = -1; -+ cfg.segments[13] = -1; -+ cfg.segments[14] = -1; -+ cfg.segments[15] = -1; -+ -+ cfg.begin = -10; -+ -+ if (!build_hw_curve_configuration( -+ &cfg, opp110->regamma.arr_curve_points, -+ opp110->regamma.arr_points, -+ opp110->regamma.coordinates_x, &hw_points_num)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ opp110->regamma.hw_points_num = hw_points_num; -+ -+ return true; -+} -+ -+ -+/* -+ ***************************************************************************** -+ * Function: regamma_config_regions_and_segments -+ * -+ * build regamma curve by using predefined hw points -+ * uses interface parameters ,like EDID coeff. -+ * -+ * @param : parameters interface parameters -+ * @return void -+ * -+ * @note -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+static void regamma_config_regions_and_segments( -+ struct dce110_opp *opp110) -+{ -+ struct gamma_curve *curve; -+ uint32_t value = 0; -+ -+ { -+ set_reg_field_value( -+ value, -+ opp110->regamma.arr_points[0].custom_float_x, -+ REGAMMA_CNTLA_START_CNTL, -+ REGAMMA_CNTLA_EXP_REGION_START); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ REGAMMA_CNTLA_START_CNTL, -+ REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_CNTLA_START_CNTL), -+ value); -+ } -+ { -+ value = 0; -+ set_reg_field_value( -+ value, -+ opp110->regamma.arr_points[0].custom_float_slope, -+ REGAMMA_CNTLA_SLOPE_CNTL, -+ REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); -+ } -+ { -+ value = 0; -+ set_reg_field_value( -+ value, -+ opp110->regamma.arr_points[1].custom_float_x, -+ REGAMMA_CNTLA_END_CNTL1, -+ REGAMMA_CNTLA_EXP_REGION_END); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); -+ } -+ { -+ value = 0; -+ set_reg_field_value( -+ value, -+ opp110->regamma.arr_points[2].custom_float_slope, -+ REGAMMA_CNTLA_END_CNTL2, -+ REGAMMA_CNTLA_EXP_REGION_END_BASE); -+ -+ set_reg_field_value( -+ value, -+ opp110->regamma.arr_points[1].custom_float_y, -+ REGAMMA_CNTLA_END_CNTL2, -+ REGAMMA_CNTLA_EXP_REGION_END_SLOPE); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); -+ } -+ -+ curve = opp110->regamma.arr_curve_points; -+ -+ { -+ value = 0; -+ set_reg_field_value( -+ value, -+ curve[0].offset, -+ REGAMMA_CNTLA_REGION_0_1, -+ REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); -+ -+ set_reg_field_value( -+ value, -+ curve[0].segments_num, -+ REGAMMA_CNTLA_REGION_0_1, -+ REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); -+ -+ set_reg_field_value( -+ value, -+ curve[1].offset, -+ REGAMMA_CNTLA_REGION_0_1, -+ REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); -+ -+ set_reg_field_value( -+ value, -+ curve[1].segments_num, -+ REGAMMA_CNTLA_REGION_0_1, -+ REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_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); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), -+ value); -+ } -+} -+ -+static void program_pwl( -+ struct dce110_opp *opp110, -+ const struct gamma_parameters *params) -+{ -+ uint32_t value; -+ -+ { -+ uint8_t max_tries = 10; -+ uint8_t counter = 0; -+ -+ /* Power on LUT memory */ -+ value = dal_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); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -+ -+ while (counter < max_tries) { -+ value = -+ dal_read_reg( -+ opp110->base.ctx, -+ DCFE_REG(mmDCFE_MEM_PWR_STATUS)); -+ -+ if (get_reg_field_value( -+ value, -+ DCFE_MEM_PWR_STATUS, -+ DCP_REGAMMA_MEM_PWR_STATE) == 0) -+ break; -+ -+ ++counter; -+ } -+ -+ if (counter == max_tries) { -+ dal_logger_write(opp110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "%s: regamma lut was not powered on " -+ "in a timely manner," -+ " programming still proceeds\n", -+ __func__); -+ } -+ } -+ -+ value = 0; -+ -+ set_reg_field_value( -+ value, -+ 7, -+ REGAMMA_LUT_WRITE_EN_MASK, -+ REGAMMA_LUT_WRITE_EN_MASK); -+ -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); -+ dal_write_reg(opp110->base.ctx, -+ DCP_REG(mmREGAMMA_LUT_INDEX), 0); -+ -+ /* Program REGAMMA_LUT_DATA */ -+ { -+ const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); -+ -+ uint32_t i = 0; -+ -+ struct pwl_result_data *rgb = -+ opp110->regamma.rgb_resulted; -+ -+ while (i != opp110->regamma.hw_points_num) { -+ dal_write_reg(opp110->base.ctx, addr, rgb->red_reg); -+ dal_write_reg(opp110->base.ctx, addr, rgb->green_reg); -+ dal_write_reg(opp110->base.ctx, addr, rgb->blue_reg); -+ -+ dal_write_reg(opp110->base.ctx, addr, -+ rgb->delta_red_reg); -+ dal_write_reg(opp110->base.ctx, addr, -+ rgb->delta_green_reg); -+ dal_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 = dal_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); -+ -+ dal_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -+} -+ -+void dce110_opp_power_on_regamma_lut( -+ struct output_pixel_processor *opp, -+ bool power_on) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ -+ uint32_t value = -+ dal_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); -+ -+ dal_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -+} -+ -+static bool scale_gamma( -+ struct dce110_opp *opp110, -+ const struct gamma_ramp *gamma_ramp, -+ const struct gamma_parameters *params) -+{ -+ const struct gamma_ramp_rgb256x3x16 *gamma; -+ bool use_palette = params->surface_pixel_format == PIXEL_FORMAT_INDEX8; -+ -+ const uint16_t max_driver = 0xFFFF; -+ const uint16_t max_os = 0xFF00; -+ -+ uint16_t scaler = max_os; -+ -+ uint32_t i; -+ -+ struct dev_c_lut *palette = opp110->regamma.saved_palette; -+ -+ struct pwl_float_data *rgb = opp110->regamma.rgb_user; -+ struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; -+ -+ if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) -+ gamma = &gamma_ramp->gamma_ramp_rgb256x3x16; -+ else -+ return false; /* invalid option */ -+ -+ i = 0; -+ -+ do { -+ if ((gamma->red[i] > max_os) || -+ (gamma->green[i] > max_os) || -+ (gamma->blue[i] > max_os)) { -+ scaler = max_driver; -+ break; -+ } -+ ++i; -+ } while (i != RGB_256X3X16); -+ -+ i = 0; -+ -+ if (use_palette) -+ do { -+ rgb->r = dal_fixed31_32_from_fraction( -+ gamma->red[palette->red], scaler); -+ rgb->g = dal_fixed31_32_from_fraction( -+ gamma->green[palette->green], scaler); -+ rgb->b = dal_fixed31_32_from_fraction( -+ gamma->blue[palette->blue], scaler); -+ -+ ++palette; -+ ++rgb; -+ ++i; -+ } while (i != RGB_256X3X16); -+ else -+ do { -+ rgb->r = dal_fixed31_32_from_fraction( -+ gamma->red[i], scaler); -+ rgb->g = dal_fixed31_32_from_fraction( -+ gamma->green[i], scaler); -+ rgb->b = dal_fixed31_32_from_fraction( -+ gamma->blue[i], scaler); -+ -+ ++rgb; -+ ++i; -+ } while (i != RGB_256X3X16); -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider1); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider1); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider1); -+ -+ ++rgb; -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider2); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider2); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider2); -+ -+ ++rgb; -+ -+ rgb->r = dal_fixed31_32_mul(rgb_last->r, -+ opp110->regamma.divider3); -+ rgb->g = dal_fixed31_32_mul(rgb_last->g, -+ opp110->regamma.divider3); -+ rgb->b = dal_fixed31_32_mul(rgb_last->b, -+ opp110->regamma.divider3); -+ -+ return true; -+} -+ -+ -+static void configure_regamma_mode( -+ struct dce110_opp *opp110, -+ const struct gamma_parameters *params, -+ bool force_bypass) -+{ -+ const uint32_t addr = DCP_REG(mmREGAMMA_CONTROL); -+ -+ enum wide_gamut_regamma_mode mode = -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A; -+ -+ uint32_t value = dal_read_reg(opp110->base.ctx, addr); -+ -+ if (force_bypass) { -+ -+ set_reg_field_value( -+ value, -+ 0, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ -+ dal_write_reg(opp110->base.ctx, addr, value); -+ -+ return; -+ } -+ -+ if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_BYPASS) -+ mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS; -+ else if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_HW) { -+ if (params->surface_pixel_format == PIXEL_FORMAT_FP16) -+ mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS; -+ else -+ mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24; -+ } -+ -+ switch (mode) { -+ case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS: -+ set_reg_field_value( -+ value, -+ 0, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ break; -+ case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24: -+ set_reg_field_value( -+ value, -+ 1, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ break; -+ case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22: -+ set_reg_field_value( -+ value, -+ 2, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ break; -+ case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A: -+ set_reg_field_value( -+ value, -+ 3, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ break; -+ case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B: -+ set_reg_field_value( -+ value, -+ 4, -+ REGAMMA_CONTROL, -+ GRPH_REGAMMA_MODE); -+ break; -+ default: -+ break; -+ } -+ -+ dal_write_reg(opp110->base.ctx, addr, value); -+} -+ -+bool dce110_opp_set_regamma( -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *ramp, -+ const struct gamma_parameters *params, -+ bool force_bypass) -+{ -+ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); -+ -+ if (force_bypass) { -+ configure_regamma_mode(opp110, params, true); -+ } else { -+ /* 1. Scale gamma to 0 - 1 to m_pRgbUser */ -+ if (!scale_gamma(opp110, ramp, params)) { -+ ASSERT_CRITICAL(false); -+ /* invalid option */ -+ return false; -+ } -+ -+ /* 2. Configure regamma curve without analysis (future task) */ -+ /* and program the PWL regions and segments */ -+ if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_SW || -+ params->surface_pixel_format == PIXEL_FORMAT_FP16) { -+ -+ /* 3. Setup x exponentially distributed points */ -+ if (!setup_distribution_points(opp110)) { -+ ASSERT_CRITICAL(false); -+ /* invalid option */ -+ return false; -+ } -+ -+ /* 4. Build ideal regamma curve */ -+ if (!build_regamma_curve(opp110, params)) { -+ ASSERT_CRITICAL(false); -+ /* invalid parameters or bug */ -+ return false; -+ } -+ -+ /* 5. Map user gamma (evenly distributed x points) to -+ * new curve when x is y from ideal regamma , step 5 */ -+ if (!map_regamma_hw_to_x_user( -+ opp110, ramp, params)) { -+ ASSERT_CRITICAL(false); -+ /* invalid parameters or bug */ -+ return false; -+ } -+ -+ /* 6.Build and verify resulted curve */ -+ build_new_custom_resulted_curve(opp110, params); -+ -+ /* 7. Build and translate x to hw format */ -+ if (!rebuild_curve_configuration_magic(opp110)) { -+ ASSERT_CRITICAL(false); -+ /* invalid parameters or bug */ -+ return false; -+ } -+ -+ /* 8. convert all params to the custom float format */ -+ if (!convert_to_custom_float(opp110)) { -+ ASSERT_CRITICAL(false); -+ /* invalid parameters or bug */ -+ return false; -+ } -+ -+ /* 9. program regamma curve configuration */ -+ regamma_config_regions_and_segments(opp110); -+ -+ /* 10. Program PWL */ -+ program_pwl(opp110, params); -+ } -+ -+ /* -+ * 11. program regamma config -+ */ -+ configure_regamma_mode(opp110, params, false); -+ } -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c -new file mode 100644 -index 0000000..d2594a9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c -@@ -0,0 +1,1276 @@ -+/* -+* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_services.h" -+ -+#include "resource.h" -+#include "include/irq_service_interface.h" -+#include "dce110/dce110_timing_generator.h" -+#include "dce110/dce110_link_encoder.h" -+#include "dce110/dce110_mem_input.h" -+#include "dce110/dce110_ipp.h" -+#include "dce110/dce110_transform.h" -+#include "dce110/dce110_stream_encoder.h" -+#include "dce110/dce110_opp.h" -+#include "link_encoder_types.h" -+#include "stream_encoder_types.h" -+ -+enum dce110_clk_src_array_id { -+ DCE110_CLK_SRC_PLL0 = 0, -+ DCE110_CLK_SRC_PLL1, -+ DCE110_CLK_SRC_EXT, -+ -+ DCE110_CLK_SRC_TOTAL -+}; -+ -+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 enum ds_color_space build_default_color_space( -+ struct core_stream *stream) -+{ -+ enum ds_color_space color_space = -+ DS_COLOR_SPACE_SRGB_FULLRANGE; -+ struct dc_crtc_timing *timing = &stream->public.timing; -+ -+ switch (stream->signal) { -+ /* TODO: implement other signal color space setting */ -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ { -+ uint32_t pix_clk_khz; -+ -+ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 && -+ timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) { -+ if (timing->timing_standard == -+ TIMING_STANDARD_CEA770 && -+ timing->timing_standard == -+ TIMING_STANDARD_CEA861) -+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; -+ -+ pix_clk_khz = timing->pix_clk_khz / 10; -+ if (timing->h_addressable == 640 && -+ timing->v_addressable == 480 && -+ (pix_clk_khz == 2520 || pix_clk_khz == 2517)) -+ color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; -+ } else { -+ if (timing->timing_standard == -+ TIMING_STANDARD_CEA770 || -+ timing->timing_standard == -+ TIMING_STANDARD_CEA861) { -+ -+ color_space = -+ (timing->pix_clk_khz > PIXEL_CLOCK) ? -+ DS_COLOR_SPACE_YCBCR709 : -+ DS_COLOR_SPACE_YCBCR601; -+ } -+ } -+ break; -+ } -+ default: -+ switch (timing->pixel_encoding) { -+ case PIXEL_ENCODING_YCBCR422: -+ case PIXEL_ENCODING_YCBCR444: -+ if (timing->pix_clk_khz > PIXEL_CLOCK) -+ color_space = DS_COLOR_SPACE_YCBCR709; -+ else -+ color_space = DS_COLOR_SPACE_YCBCR601; -+ break; -+ default: -+ break; -+ } -+ break; -+ } -+ return color_space; -+} -+ -+static void set_avi_info_frame(struct hw_info_packet *info_packet, -+ struct core_stream *stream) -+{ -+ enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN; -+ struct info_frame info_frame = { {0} }; -+ uint32_t pixel_encoding = 0; -+ enum scanning_type scan_type = SCANNING_TYPE_NODATA; -+ enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; -+ bool itc = false; -+ uint8_t cn0_cn1 = 0; -+ uint8_t *check_sum = NULL; -+ uint8_t byte_index = 0; -+ -+ if (info_packet == NULL) -+ return; -+ -+ color_space = build_default_color_space(stream); -+ -+ /* Initialize header */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.header. -+ info_frame_type = INFO_FRAME_AVI; -+ /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall -+ * not be used in HDMI 2.0 (Section 10.1) */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = -+ INFO_FRAME_VERSION_2; -+ info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = -+ INFO_FRAME_SIZE_AVI; -+ -+ /* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built -+ * according to HDMI 2.0 spec (Section 10.1) -+ * Add "case PixelEncoding_YCbCr420: pixelEncoding = 3; break;" -+ * when YCbCr 4:2:0 is supported by DAL hardware. */ -+ -+ switch (stream->public.timing.pixel_encoding) { -+ case PIXEL_ENCODING_YCBCR422: -+ pixel_encoding = 1; -+ break; -+ -+ case PIXEL_ENCODING_YCBCR444: -+ pixel_encoding = 2; -+ break; -+ -+ case PIXEL_ENCODING_RGB: -+ default: -+ pixel_encoding = 0; -+ } -+ -+ /* Y0_Y1_Y2 : The pixel encoding */ -+ /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = -+ pixel_encoding; -+ -+ -+ /* A0 = 1 Active Format Information valid */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = -+ ACTIVE_FORMAT_VALID; -+ -+ /* B0, B1 = 3; Bar info data is valid */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = -+ BAR_INFO_BOTH_VALID; -+ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = -+ PICTURE_SCALING_UNIFORM; -+ -+ /* S0, S1 : Underscan / Overscan */ -+ /* TODO: un-hardcode scan type */ -+ scan_type = SCANNING_TYPE_UNDERSCAN; -+ info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; -+ -+ /* C0, C1 : Colorimetry */ -+ if (color_space == DS_COLOR_SPACE_YCBCR709) -+ info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = -+ COLORIMETRY_ITU709; -+ else if (color_space == DS_COLOR_SPACE_YCBCR601) -+ info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = -+ COLORIMETRY_ITU601; -+ else -+ info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = -+ COLORIMETRY_NO_DATA; -+ -+ -+ /* TODO: un-hardcode aspect ratio */ -+ aspect = stream->public.timing.aspect_ratio; -+ -+ switch (aspect) { -+ case ASPECT_RATIO_4_3: -+ case ASPECT_RATIO_16_9: -+ info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; -+ break; -+ -+ case ASPECT_RATIO_NO_DATA: -+ case ASPECT_RATIO_64_27: -+ case ASPECT_RATIO_256_135: -+ default: -+ info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; -+ } -+ -+ /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = -+ ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; -+ -+ /* TODO: un-hardcode cn0_cn1 and itc */ -+ cn0_cn1 = 0; -+ itc = false; -+ -+ if (itc) { -+ info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; -+ info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = -+ cn0_cn1; -+ } -+ -+ /* TODO: un-hardcode q0_q1 */ -+ if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE) -+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = -+ RGB_QUANTIZATION_FULL_RANGE; -+ else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE) -+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = -+ RGB_QUANTIZATION_LIMITED_RANGE; -+ else -+ info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = -+ RGB_QUANTIZATION_DEFAULT_RANGE; -+ -+ /* TODO : We should handle YCC quantization, -+ * but we do not have matrix calculation */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = -+ YYC_QUANTIZATION_LIMITED_RANGE; -+ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = -+ stream->public.timing.vic; -+ -+ /* pixel repetition -+ * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel -+ * repetition start from 1 */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; -+ -+ /* Bar Info -+ * barTop: Line Number of End of Top Bar. -+ * barBottom: Line Number of Start of Bottom Bar. -+ * barLeft: Pixel Number of End of Left Bar. -+ * barRight: Pixel Number of Start of Right Bar. */ -+ info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = -+ stream->public.timing.v_border_top; -+ info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = -+ (stream->public.timing.v_border_top -+ - stream->public.timing.v_border_bottom + 1); -+ info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = -+ stream->public.timing.h_border_left; -+ info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = -+ (stream->public.timing.h_total -+ - stream->public.timing.h_border_right + 1); -+ -+ /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ -+ check_sum = -+ &info_frame. -+ avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; -+ *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI -+ + INFO_FRAME_VERSION_2; -+ -+ for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) -+ *check_sum += info_frame.avi_info_packet.info_packet_hdmi. -+ packet_raw_data.sb[byte_index]; -+ -+ /* one byte complement */ -+ *check_sum = (uint8_t) (0x100 - *check_sum); -+ -+ /* Store in hw_path_mode */ -+ info_packet->hb0 = -+ info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; -+ info_packet->hb1 = -+ info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; -+ info_packet->hb2 = -+ info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; -+ -+ for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) -+ info_packet->sb[byte_index] = info_frame.avi_info_packet. -+ info_packet_hdmi.packet_raw_data.sb[byte_index]; -+ -+ info_packet->valid = true; -+} -+ -+static void translate_info_frame(const struct hw_info_frame *hw_info_frame, -+ struct encoder_info_frame *encoder_info_frame) -+{ -+ dc_service_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; -+ -+ dc_service_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) { -+ dc_service_memmove( -+ &encoder_info_frame->avi, -+ &hw_info_frame->avi_info_packet, -+ sizeof(struct hw_info_packet)); -+ } -+ -+ if (hw_info_frame->vendor_info_packet.valid) { -+ dc_service_memmove( -+ &encoder_info_frame->vendor, -+ &hw_info_frame->vendor_info_packet, -+ sizeof(struct hw_info_packet)); -+ } -+ -+ if (hw_info_frame->spd_packet.valid) { -+ dc_service_memmove( -+ &encoder_info_frame->spd, -+ &hw_info_frame->spd_packet, -+ sizeof(struct hw_info_packet)); -+ } -+ -+ if (hw_info_frame->vsc_packet.valid) { -+ dc_service_memmove( -+ &encoder_info_frame->vsc, -+ &hw_info_frame->vsc_packet, -+ sizeof(struct hw_info_packet)); -+ } -+} -+ -+static void build_info_frame(struct core_stream *stream) -+{ -+ enum signal_type signal = SIGNAL_TYPE_NONE; -+ struct hw_info_frame info_frame = { { 0 } }; -+ -+ /* default all packets to invalid */ -+ info_frame.avi_info_packet.valid = false; -+ info_frame.gamut_packet.valid = false; -+ info_frame.vendor_info_packet.valid = false; -+ info_frame.spd_packet.valid = false; -+ info_frame.vsc_packet.valid = false; -+ -+ signal = stream->sink->public.sink_signal; -+ -+ /* HDMi and DP have different info packets*/ -+ if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { -+ set_avi_info_frame(&info_frame.avi_info_packet, -+ stream); -+ set_vendor_info_packet(stream, &info_frame.vendor_info_packet); -+ } -+ -+ translate_info_frame(&info_frame, -+ &stream->encoder_info_frame); -+} -+ -+ -+bool dce110_construct_resource_pool( -+ struct adapter_service *adapter_serv, -+ struct dc *dc, -+ struct resource_pool *pool) -+{ -+ unsigned int i; -+ struct clock_source_init_data clk_src_init_data = { 0 }; -+ struct audio_init_data audio_init_data = { 0 }; -+ struct dc_context *ctx = dc->ctx; -+ pool->adapter_srv = adapter_serv; -+ -+ pool->stream_engines.engine.ENGINE_ID_DIGA = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGB = 1; -+ pool->stream_engines.engine.ENGINE_ID_DIGC = 1; -+ -+ clk_src_init_data.as = adapter_serv; -+ clk_src_init_data.ctx = ctx; -+ clk_src_init_data.clk_src_id.enum_id = ENUM_ID_1; -+ clk_src_init_data.clk_src_id.type = OBJECT_TYPE_CLOCK_SOURCE; -+ pool->clk_src_count = DCE110_CLK_SRC_TOTAL; -+ -+ clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL0; -+ pool->clock_sources[DCE110_CLK_SRC_PLL0] = dal_clock_source_create( -+ &clk_src_init_data); -+ clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL1; -+ pool->clock_sources[DCE110_CLK_SRC_PLL1] = dal_clock_source_create( -+ &clk_src_init_data); -+ clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_EXTERNAL; -+ pool->clock_sources[DCE110_CLK_SRC_EXT] = dal_clock_source_create( -+ &clk_src_init_data); -+ -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] == NULL) { -+ dal_error("DC: failed to create clock sources!\n"); -+ BREAK_TO_DEBUGGER(); -+ goto clk_src_create_fail; -+ } -+ } -+ -+ pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv); -+ if (pool->display_clock == NULL) { -+ dal_error("DC: failed to create display clock!\n"); -+ BREAK_TO_DEBUGGER(); -+ goto disp_clk_create_fail; -+ } -+ -+ { -+ struct irq_service_init_data init_data; -+ init_data.ctx = dc->ctx; -+ pool->irqs = dal_irq_service_create( -+ dal_adapter_service_get_dce_version( -+ dc->res_pool.adapter_srv), -+ &init_data); -+ if (!pool->irqs) -+ goto irqs_create_fail; -+ -+ } -+ -+ pool->controller_count = -+ dal_adapter_service_get_func_controllers_num(adapter_serv); -+ pool->stream_enc_count = 3; -+ pool->scaler_filter = dal_scaler_filter_create(ctx); -+ if (pool->scaler_filter == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error("DC: failed to create filter!\n"); -+ goto filter_create_fail; -+ } -+ -+ for (i = 0; i < pool->controller_count; i++) { -+ pool->timing_generators[i] = dce110_timing_generator_create( -+ adapter_serv, -+ ctx, -+ i + 1); -+ if (pool->timing_generators[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error("DC: failed to create tg!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->mis[i] = dce110_mem_input_create( -+ ctx, -+ i + 1); -+ if (pool->mis[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error( -+ "DC: failed to create memory input!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->ipps[i] = dce110_ipp_create( -+ ctx, -+ i + 1); -+ if (pool->ipps[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error( -+ "DC: failed to create input pixel processor!\n"); -+ goto controller_create_fail; -+ } -+ -+ pool->transforms[i] = dce110_transform_create( -+ ctx, -+ i + 1); -+ if (pool->transforms[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error( -+ "DC: failed to create transform!\n"); -+ goto controller_create_fail; -+ } -+ dce110_transform_set_scaler_filter( -+ pool->transforms[i], -+ pool->scaler_filter); -+ -+ pool->opps[i] = dce110_opp_create( -+ ctx, -+ i + 1); -+ if (pool->opps[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error( -+ "DC: failed to create output pixel processor!\n"); -+ goto controller_create_fail; -+ } -+ } -+ -+ audio_init_data.as = adapter_serv; -+ audio_init_data.ctx = ctx; -+ pool->audio_count = 0; -+ for (i = 0; i < pool->controller_count; i++) { -+ struct graphics_object_id obj_id; -+ -+ obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); -+ if (false == dal_graphics_object_id_is_valid(obj_id)) { -+ /* no more valid audio objects */ -+ break; -+ } -+ -+ audio_init_data.audio_stream_id = obj_id; -+ pool->audios[i] = dal_audio_create(&audio_init_data); -+ if (pool->audios[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error("DC: failed to create DPPs!\n"); -+ goto audio_create_fail; -+ } -+ pool->audio_count++; -+ } -+ -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ struct stream_enc_init_data enc_init_data = { 0 }; -+ /* TODO: rework fragile code*/ -+ enc_init_data.stream_engine_id = i; -+ enc_init_data.adapter_service = adapter_serv; -+ enc_init_data.ctx = dc->ctx; -+ if (pool->stream_engines.u_all & 1 << i) { -+ pool->stream_enc[i] = dce110_stream_encoder_create( -+ &enc_init_data); -+ -+ if (pool->stream_enc[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dal_error("DC: failed to create stream_encoder!\n"); -+ goto stream_enc_create_fail; -+ } -+ } -+ } -+ -+ return true; -+ -+stream_enc_create_fail: -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ if (pool->stream_enc[i] != NULL) -+ dce110_stream_encoder_destroy(&pool->stream_enc[i]); -+ } -+ -+audio_create_fail: -+ for (i = 0; i < pool->controller_count; i++) { -+ if (pool->audios[i] != NULL) -+ dal_audio_destroy(&pool->audios[i]); -+ } -+ -+controller_create_fail: -+ for (i = 0; i < pool->controller_count; i++) { -+ if (pool->opps[i] != NULL) -+ dce110_opp_destroy(&pool->opps[i]); -+ -+ if (pool->transforms[i] != NULL) -+ dce110_transform_destroy(&pool->transforms[i]); -+ -+ if (pool->ipps[i] != NULL) -+ dce110_ipp_destroy(&pool->ipps[i]); -+ -+ if (pool->mis[i] != NULL) -+ dce110_mem_input_destroy(&pool->mis[i]); -+ -+ if (pool->timing_generators[i] != NULL) -+ dce110_timing_generator_destroy( -+ &pool->timing_generators[i]); -+ } -+ -+filter_create_fail: -+ dal_irq_service_destroy(&pool->irqs); -+ -+irqs_create_fail: -+ dal_display_clock_destroy(&pool->display_clock); -+ -+disp_clk_create_fail: -+clk_src_create_fail: -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] != NULL) -+ dal_clock_source_destroy(&pool->clock_sources[i]); -+ } -+ return false; -+} -+ -+void dce110_destruct_resource_pool(struct resource_pool *pool) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pool->controller_count; i++) { -+ if (pool->opps[i] != NULL) -+ dce110_opp_destroy(&pool->opps[i]); -+ -+ if (pool->transforms[i] != NULL) -+ dce110_transform_destroy(&pool->transforms[i]); -+ -+ if (pool->ipps[i] != NULL) -+ dce110_ipp_destroy(&pool->ipps[i]); -+ -+ if (pool->mis[i] != NULL) -+ dce110_mem_input_destroy(&pool->mis[i]); -+ -+ if (pool->timing_generators[i] != NULL) -+ dce110_timing_generator_destroy( -+ &pool->timing_generators[i]); -+ } -+ -+ for (i = 0; i < pool->stream_enc_count; i++) { -+ if (pool->stream_enc[i] != NULL) -+ dce110_stream_encoder_destroy(&pool->stream_enc[i]); -+ } -+ -+ for (i = 0; i < pool->clk_src_count; i++) { -+ if (pool->clock_sources[i] != NULL) { -+ dal_clock_source_destroy(&pool->clock_sources[i]); -+ } -+ } -+ -+ for (i = 0; i < pool->audio_count; i++) { -+ if (pool->audios[i] != NULL) { -+ dal_audio_destroy(&pool->audios[i]); -+ } -+ } -+ if (pool->display_clock != NULL) { -+ dal_display_clock_destroy(&pool->display_clock); -+ } -+ -+ if (pool->scaler_filter != NULL) { -+ dal_scaler_filter_destroy(&pool->scaler_filter); -+ } -+ if (pool->irqs != NULL) { -+ dal_irq_service_destroy(&pool->irqs); -+ } -+ -+ if (pool->adapter_srv != NULL) { -+ dal_adapter_service_destroy(&pool->adapter_srv); -+ } -+} -+ -+static void attach_stream_to_controller( -+ struct resource_context *res_ctx, -+ struct core_stream *stream) -+{ -+ res_ctx->controller_ctx[stream->controller_idx].stream = stream; -+} -+ -+static bool assign_first_free_controller( -+ struct resource_context *res_ctx, -+ struct core_stream *stream) -+{ -+ uint8_t i; -+ for (i = 0; i < res_ctx->pool.controller_count; i++) { -+ if (!res_ctx->controller_ctx[i].stream) { -+ stream->tg = res_ctx->pool.timing_generators[i]; -+ stream->mi = res_ctx->pool.mis[i]; -+ stream->ipp = res_ctx->pool.ipps[i]; -+ stream->xfm = res_ctx->pool.transforms[i]; -+ stream->opp = res_ctx->pool.opps[i]; -+ stream->controller_idx = i; -+ stream->dis_clk = res_ctx->pool.display_clock; -+ return true; -+ } -+ } -+ return false; -+} -+ -+static 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; -+ } -+} -+ -+static struct stream_encoder *find_first_free_match_stream_enc_for_link( -+ struct resource_context *res_ctx, -+ struct core_link *link) -+{ -+ uint8_t i; -+ -+ 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]) { -+ if (res_ctx->pool.stream_enc[i]->id == -+ link->link_enc->preferred_engine) -+ return res_ctx->pool.stream_enc[i]; -+ } -+ } -+ -+ /* TODO: Handle MST*/ -+ -+ return NULL; -+} -+ -+/* 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 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 struct clock_source *find_first_free_pll( -+ struct resource_context *res_ctx) -+{ -+ if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL0] == 0) { -+ return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL0]; -+ } -+ if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL1] == 0) { -+ return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL1]; -+ } -+ -+ return 0; -+} -+ -+static bool check_timing_change(struct core_stream *cur_stream, -+ struct core_stream *new_stream) -+{ -+ if (cur_stream == NULL) -+ return true; -+ -+ /* If sink pointer changed, it means this is a hotplug, we should do -+ * full hw setting. -+ */ -+ if (cur_stream->sink != new_stream->sink) -+ return true; -+ -+ return !is_same_timing( -+ &cur_stream->public.timing, -+ &new_stream->public.timing); -+} -+ -+static enum dc_status map_resources( -+ const struct dc *dc, -+ struct validate_context *context) -+{ -+ uint8_t i, j; -+ -+ /* mark resources used for targets that are already active */ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ if (context->target_flags[i].unchanged) -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ attach_stream_to_controller( -+ &context->res_ctx, -+ stream); -+ -+ set_stream_engine_in_use( -+ &context->res_ctx, -+ stream->stream_enc); -+ -+ reference_clock_source( -+ &context->res_ctx, -+ stream->clock_source); -+ -+ if (stream->audio) { -+ set_audio_in_use(&context->res_ctx, -+ stream->audio); -+ } -+ } -+ } -+ -+ /* acquire new resources */ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ if (context->target_flags[i].unchanged) -+ continue; -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ struct core_stream *curr_stream; -+ -+ if (!assign_first_free_controller( -+ &context->res_ctx, stream)) -+ return DC_NO_CONTROLLER_RESOURCE; -+ -+ attach_stream_to_controller(&context->res_ctx, stream); -+ -+ stream->stream_enc = -+ find_first_free_match_stream_enc_for_link( -+ &context->res_ctx, -+ stream->sink->link); -+ -+ if (!stream->stream_enc) -+ return DC_NO_STREAM_ENG_RESOURCE; -+ -+ set_stream_engine_in_use( -+ &context->res_ctx, -+ stream->stream_enc); -+ stream->signal = -+ stream->sink->public.sink_signal; -+ -+ if (dc_is_dp_signal(stream->signal)) -+ stream->clock_source = context->res_ctx. -+ pool.clock_sources[DCE110_CLK_SRC_EXT]; -+ else -+ stream->clock_source = -+ find_used_clk_src_for_sharing( -+ context, stream); -+ if (stream->clock_source == NULL) -+ stream->clock_source = -+ find_first_free_pll(&context->res_ctx); -+ -+ if (stream->clock_source == NULL) -+ return DC_NO_CLOCK_SOURCE_RESOURCE; -+ -+ reference_clock_source( -+ &context->res_ctx, -+ stream->clock_source); -+ -+ /* TODO: Add check if ASIC support and EDID audio */ -+ if (!stream->sink->converter_disable_audio && -+ dc_is_audio_capable_signal( -+ stream->signal)) { -+ stream->audio = find_first_free_audio( -+ &context->res_ctx); -+ -+ if (!stream->audio) -+ return DC_NO_STREAM_AUDIO_RESOURCE; -+ -+ set_audio_in_use(&context->res_ctx, -+ stream->audio); -+ } -+ curr_stream = -+ dc->current_context.res_ctx.controller_ctx -+ [stream->controller_idx].stream; -+ context->res_ctx.controller_ctx[stream->controller_idx] -+ .flags.timing_changed = -+ check_timing_change(curr_stream, stream); -+ -+ } -+ } -+ -+ return DC_OK; -+} -+ -+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) -+{ -+ switch (crtc_id) { -+ case CONTROLLER_ID_D0: -+ return DTO_SOURCE_ID0; -+ case CONTROLLER_ID_D1: -+ return DTO_SOURCE_ID1; -+ case CONTROLLER_ID_D2: -+ return DTO_SOURCE_ID2; -+ case CONTROLLER_ID_D3: -+ return DTO_SOURCE_ID3; -+ case CONTROLLER_ID_D4: -+ return DTO_SOURCE_ID4; -+ case CONTROLLER_ID_D5: -+ return DTO_SOURCE_ID5; -+ default: -+ return DTO_SOURCE_UNKNOWN; -+ } -+} -+ -+static void build_audio_output( -+ const struct core_stream *stream, -+ struct audio_output *audio_output) -+{ -+ audio_output->engine_id = stream->stream_enc->id; -+ -+ audio_output->signal = stream->signal; -+ -+ /* audio_crtc_info */ -+ -+ audio_output->crtc_info.h_total = -+ stream->public.timing.h_total; -+ -+ /* Audio packets are sent during actual CRTC blank physical signal, we -+ * need to specify actual active signal portion */ -+ audio_output->crtc_info.h_active = -+ stream->public.timing.h_addressable -+ + stream->public.timing.h_border_left -+ + stream->public.timing.h_border_right; -+ -+ audio_output->crtc_info.v_active = -+ stream->public.timing.v_addressable -+ + stream->public.timing.v_border_top -+ + stream->public.timing.v_border_bottom; -+ -+ audio_output->crtc_info.pixel_repetition = 1; -+ -+ audio_output->crtc_info.interlaced = -+ stream->public.timing.flags.INTERLACE; -+ -+ audio_output->crtc_info.refresh_rate = -+ (stream->public.timing.pix_clk_khz*1000)/ -+ (stream->public.timing.h_total*stream->public.timing.v_total); -+ -+ audio_output->crtc_info.color_depth = -+ stream->public.timing.display_color_depth; -+ -+ audio_output->crtc_info.requested_pixel_clock = -+ stream->pix_clk_params.requested_pix_clk; -+ -+ /* TODO - Investigate why calculated pixel clk has to be -+ * requested pixel clk */ -+ audio_output->crtc_info.calculated_pixel_clock = -+ stream->pix_clk_params.requested_pix_clk; -+ -+ /* TODO: This is needed for DP */ -+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT) { -+ audio_output->pll_info.dp_dto_source_clock_in_khz = -+ dal_display_clock_get_dp_ref_clk_frequency( -+ stream->dis_clk); -+ } -+ -+ audio_output->pll_info.feed_back_divider = -+ stream->pll_settings.feedback_divider; -+ -+ audio_output->pll_info.dto_source = -+ translate_to_dto_source( -+ stream->controller_idx + 1); -+ -+ /* TODO hard code to enable for now. Need get from stream */ -+ audio_output->pll_info.ss_enabled = true; -+ -+ audio_output->pll_info.ss_percentage = -+ stream->pll_settings.ss_percentage; -+} -+ -+static void get_pixel_clock_parameters( -+ const struct core_stream *stream, -+ struct pixel_clk_params *pixel_clk_params) -+{ -+ pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; -+ pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; -+ pixel_clk_params->signal_type = stream->sink->public.sink_signal; -+ pixel_clk_params->controller_id = stream->controller_idx + 1; -+ /* TODO: un-hardcode*/ -+ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * -+ LINK_RATE_REF_FREQ_IN_KHZ; -+ pixel_clk_params->flags.ENABLE_SS = 0; -+ pixel_clk_params->color_depth = -+ stream->public.timing.display_color_depth; -+ pixel_clk_params->flags.DISPLAY_BLANKED = 1; -+} -+ -+static enum dc_status build_stream_hw_param(struct core_stream *stream) -+{ -+ /*TODO: unhardcode*/ -+ stream->max_tmds_clk_from_edid_in_mhz = 0; -+ stream->max_hdmi_deep_color = COLOR_DEPTH_121212; -+ stream->max_hdmi_pixel_clock = 600000; -+ -+ get_pixel_clock_parameters(stream, &stream->pix_clk_params); -+ dal_clock_source_get_pix_clk_dividers( -+ stream->clock_source, -+ &stream->pix_clk_params, -+ &stream->pll_settings); -+ -+ build_audio_output(stream, &stream->audio_output); -+ -+ return DC_OK; -+} -+ -+static enum dc_status validate_mapped_resource( -+ const struct dc *dc, -+ struct validate_context *context) -+{ -+ enum dc_status status = DC_OK; -+ uint8_t i, j; -+ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ if (context->target_flags[i].unchanged) -+ continue; -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ struct core_link *link = stream->sink->link; -+ status = build_stream_hw_param(stream); -+ -+ if (status != DC_OK) -+ return status; -+ -+ if (!dce110_timing_generator_validate_timing( -+ stream->tg, -+ &stream->public.timing, -+ SIGNAL_TYPE_HDMI_TYPE_A)) -+ return DC_FAIL_CONTROLLER_VALIDATE; -+ -+ -+ if (dce110_link_encoder_validate_output_with_stream( -+ link->link_enc, -+ stream) -+ != ENCODER_RESULT_OK) -+ return DC_FAIL_ENC_VALIDATE; -+ -+ /* TODO: validate audio ASIC caps, encoder */ -+ -+ status = dc_link_validate_mode_timing(stream->sink, -+ link, -+ &stream->public.timing); -+ -+ if (status != DC_OK) -+ return status; -+ -+ build_info_frame(stream); -+ } -+ } -+ -+ return DC_OK; -+} -+ -+enum dc_status dce110_validate_bandwidth( -+ const struct dc *dc, -+ struct validate_context *context) -+{ -+ uint8_t i, j; -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ uint8_t number_of_displays = 0; -+ -+ memset(&context->bw_mode_data, 0, sizeof(context->bw_mode_data)); -+ -+ for (i = 0; i < context->target_count; i++) { -+ struct core_target *target = context->targets[i]; -+ for (j = 0; j < target->stream_count; j++) { -+ struct core_stream *stream = target->streams[j]; -+ struct bw_calcs_input_single_display *disp = &context-> -+ bw_mode_data.displays_data[number_of_displays]; -+ -+ if (target->status.surface_count == 0) { -+ disp->graphics_scale_ratio = int_to_fixed(1); -+ disp->graphics_h_taps = 4; -+ disp->graphics_v_taps = 4; -+ -+ } else { -+ disp->graphics_scale_ratio = -+ fixed31_32_to_bw_fixed( -+ stream->ratios.vert.value); -+ disp->graphics_h_taps = stream->taps.h_taps; -+ disp->graphics_v_taps = stream->taps.v_taps; -+ } -+ -+ disp->graphics_src_width = -+ stream->public.timing.h_addressable; -+ disp->graphics_src_height = -+ stream->public.timing.v_addressable; -+ disp->h_total = stream->public.timing.h_total; -+ disp->pixel_rate = frc_to_fixed( -+ stream->public.timing.pix_clk_khz, 1000); -+ -+ /*TODO: get from surface*/ -+ disp->graphics_bytes_per_pixel = 4; -+ disp->graphics_tiling_mode = tiled; -+ -+ /* DCE11 defaults*/ -+ disp->graphics_lb_bpc = 10; -+ disp->graphics_interlace_mode = false; -+ disp->fbc_enable = false; -+ disp->lpt_enable = false; -+ disp->graphics_stereo_mode = mono; -+ disp->underlay_mode = ul_none; -+ -+ number_of_displays++; -+ } -+ } -+ -+ context->bw_mode_data.number_of_displays = number_of_displays; -+ context->bw_mode_data.display_synchronization_enabled = false; -+ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, -+ "%s: Start bandwidth calculations", -+ __func__); -+ if (true == bw_calcs( -+ dc->ctx, -+ &dc->bw_dceip, -+ &dc->bw_vbios, -+ &context->bw_mode_data, -+ &context->bw_results)) -+ result = DC_OK; -+ else { -+ result = DC_FAIL_BANDWIDTH_VALIDATE; -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_MODE_VALIDATION, -+ "%s: Bandwidth validation failed!", -+ __func__); -+ } -+ -+ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_BWM, -+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, -+ "%s: Finish bandwidth calculations\n nbpMark: %d", -+ __func__, -+ context->bw_results.nbp_state_change_watermark[0].b_mark); -+ -+ return result; -+} -+ -+static void set_target_unchanged( -+ struct validate_context *context, -+ uint8_t target_idx) -+{ -+ uint8_t i; -+ struct core_target *target = context->targets[target_idx]; -+ context->target_flags[target_idx].unchanged = true; -+ for (i = 0; i < target->stream_count; i++) { -+ uint8_t index = target->streams[i]->controller_idx; -+ context->res_ctx.controller_ctx[index].flags.unchanged = true; -+ } -+} -+ -+enum dc_status dce110_validate_with_context( -+ const struct dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count, -+ struct validate_context *context) -+{ -+ enum dc_status result = DC_ERROR_UNEXPECTED; -+ uint8_t i, j; -+ struct dc_context *dc_ctx = dc->ctx; -+ -+ for (i = 0; i < set_count; i++) { -+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target); -+ -+ for (j = 0; j < dc->current_context.target_count; j++) -+ if (dc->current_context.targets[j] == context->targets[i]) -+ set_target_unchanged(context, i); -+ -+ if (!context->target_flags[i].unchanged) -+ if (!logical_attach_surfaces_to_target( -+ (struct dc_surface **)set[i].surfaces, -+ set[i].surface_count, -+ &context->targets[i]->public)) { -+ DC_ERROR("Failed to attach surface to target!\n"); -+ return DC_FAIL_ATTACH_SURFACES; -+ } -+ } -+ -+ context->target_count = set_count; -+ -+ context->res_ctx.pool = dc->res_pool; -+ -+ result = map_resources(dc, context); -+ -+ if (result == DC_OK) -+ result = validate_mapped_resource(dc, context); -+ -+ if (result == DC_OK) -+ build_scaling_params_for_context(dc, context); -+ -+ if (result == DC_OK) -+ result = dce110_validate_bandwidth(dc, context); -+ -+ return result; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h -new file mode 100644 -index 0000000..e113d11 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_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_DCE110_H__ -+#define __DC_RESOURCE_DCE110_H__ -+ -+#include "core_types.h" -+ -+struct adapter_service; -+struct dc; -+struct resource_pool; -+struct dc_validation_set; -+ -+ -+bool dce110_construct_resource_pool( -+ struct adapter_service *adapter_serv, -+ struct dc *dc, -+ struct resource_pool *pool); -+ -+void dce110_destruct_resource_pool(struct resource_pool *pool); -+ -+enum dc_status dce110_validate_with_context( -+ const struct dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count, -+ struct validate_context *context); -+ -+enum dc_status dce110_validate_bandwidth( -+ const struct dc *dc, -+ struct validate_context *context); -+ -+#endif /* __DC_RESOURCE_DCE110_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c -new file mode 100644 -index 0000000..a9edf96 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c -@@ -0,0 +1,1168 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "stream_encoder_types.h" -+#include "dce110_stream_encoder.h" -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "dce/dce_11_0_enum.h" -+ -+static const uint32_t fe_engine_offsets[] = { -+ mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+ mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -+}; -+ -+#define VBI_LINE_0 0 -+#define DP_BLANK_MAX_RETRY 20 -+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 -+ -+#ifndef HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK -+ #define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK 0x2 -+ #define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN__SHIFT 0x1 -+#endif -+ -+static void construct( -+ struct stream_encoder *enc, -+ struct stream_enc_init_data *init) -+{ -+ enc->ctx = init->ctx; -+ enc->id = init->stream_engine_id; -+ enc->adapter_service = init->adapter_service; -+} -+ -+struct stream_encoder *dce110_stream_encoder_create( -+ struct stream_enc_init_data *init) -+{ -+ struct stream_encoder *enc = -+ dc_service_alloc(init->ctx, sizeof(struct stream_encoder)); -+ -+ if (!enc) -+ goto enc_create_fail; -+ -+ construct(enc, init); -+ -+ return enc; -+ -+enc_create_fail: -+ return NULL; -+} -+ -+void dce110_stream_encoder_destroy(struct stream_encoder **enc) -+{ -+ dc_service_free((*enc)->ctx, *enc); -+ *enc = NULL; -+} -+ -+static void stop_hdmi_info_packets(struct dc_context *ctx, uint32_t offset) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ /* stop generic packets 0 & 1 on HDMI */ -+ addr = mmHDMI_GENERIC_PACKET_CONTROL0 + offset; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_CONT); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_LINE); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_SEND); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_CONT); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_LINE); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_SEND); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ /* stop generic packets 2 & 3 on HDMI */ -+ addr = mmHDMI_GENERIC_PACKET_CONTROL1 + offset; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC2_CONT); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC2_LINE); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC2_SEND); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC3_CONT); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC3_LINE); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_GENERIC_PACKET_CONTROL1, -+ HDMI_GENERIC3_SEND); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ /* stop AVI packet on HDMI */ -+ addr = mmHDMI_INFOFRAME_CONTROL0 + offset; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_SEND); -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_CONT); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void stop_dp_info_packets(struct dc_context *ctx, int32_t offset) -+{ -+ /* stop generic packets on DP */ -+ -+ const uint32_t addr = mmDP_SEC_CNTL + offset; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP1_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP2_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP3_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_AVI_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_MPG_ENABLE); -+ set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE); -+ -+ /* this register shared with audio info frame. -+ * therefore we need to keep master enabled -+ * if at least one of the fields is not 0 */ -+ -+ if (value) -+ set_reg_field_value( -+ value, -+ 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+void dce110_stream_encoder_stop_info_packets( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ enum signal_type signal) -+{ -+ if (dc_is_hdmi_signal(signal)) -+ stop_hdmi_info_packets( -+ enc->ctx, -+ fe_engine_offsets[engine]); -+ else if (dc_is_dp_signal(signal)) -+ stop_dp_info_packets( -+ enc->ctx, -+ fe_engine_offsets[engine]); -+} -+ -+ -+static void update_avi_info_packet( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ enum signal_type signal, -+ const struct encoder_info_packet *info_packet) -+{ -+ const int32_t offset = fe_engine_offsets[engine]; -+ -+ uint32_t regval; -+ uint32_t addr; -+ -+ if (info_packet->valid) { -+ const uint32_t *content = -+ (const uint32_t *) &info_packet->sb[0]; -+ -+ { -+ regval = content[0]; -+ -+ dal_write_reg( -+ enc->ctx, -+ mmAFMT_AVI_INFO0 + offset, -+ regval); -+ } -+ { -+ regval = content[1]; -+ -+ dal_write_reg( -+ enc->ctx, -+ mmAFMT_AVI_INFO1 + offset, -+ regval); -+ } -+ { -+ regval = content[2]; -+ -+ dal_write_reg( -+ enc->ctx, -+ mmAFMT_AVI_INFO2 + offset, -+ regval); -+ } -+ { -+ regval = content[3]; -+ -+ /* move version to AVI_INFO3 */ -+ set_reg_field_value( -+ regval, -+ info_packet->hb1, -+ AFMT_AVI_INFO3, -+ AFMT_AVI_INFO_VERSION); -+ -+ dal_write_reg( -+ enc->ctx, -+ mmAFMT_AVI_INFO3 + offset, -+ regval); -+ } -+ -+ if (dc_is_hdmi_signal(signal)) { -+ -+ uint32_t control0val; -+ uint32_t control1val; -+ -+ addr = mmHDMI_INFOFRAME_CONTROL0 + offset; -+ -+ control0val = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ control0val, -+ 1, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_SEND); -+ -+ set_reg_field_value( -+ control0val, -+ 1, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_CONT); -+ -+ dal_write_reg(enc->ctx, addr, control0val); -+ -+ addr = mmHDMI_INFOFRAME_CONTROL1 + offset; -+ -+ control1val = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ control1val, -+ VBI_LINE_0 + 2, -+ HDMI_INFOFRAME_CONTROL1, -+ HDMI_AVI_INFO_LINE); -+ -+ dal_write_reg(enc->ctx, addr, control1val); -+ } -+ } else if (dc_is_hdmi_signal(signal)) { -+ addr = mmHDMI_INFOFRAME_CONTROL0 + offset; -+ -+ regval = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ regval, -+ 0, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_SEND); -+ -+ set_reg_field_value( -+ regval, -+ 0, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AVI_INFO_CONT); -+ -+ dal_write_reg(enc->ctx, addr, regval); -+ } -+} -+ -+static void update_generic_info_packet( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ uint32_t packet_index, -+ const struct encoder_info_packet *info_packet) -+{ -+ uint32_t addr; -+ uint32_t regval; -+ /* choose which generic packet to use */ -+ { -+ addr = mmAFMT_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; -+ -+ regval = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ regval, -+ packet_index, -+ AFMT_VBI_PACKET_CONTROL, -+ AFMT_GENERIC_INDEX); -+ -+ dal_write_reg(enc->ctx, addr, regval); -+ } -+ -+ /* write generic packet header -+ * (4th byte is for GENERIC0 only) */ -+ { -+ addr = mmAFMT_GENERIC_HDR + fe_engine_offsets[engine]; -+ -+ regval = 0; -+ -+ set_reg_field_value( -+ regval, -+ info_packet->hb0, -+ AFMT_GENERIC_HDR, -+ AFMT_GENERIC_HB0); -+ -+ set_reg_field_value( -+ regval, -+ info_packet->hb1, -+ AFMT_GENERIC_HDR, -+ AFMT_GENERIC_HB1); -+ -+ set_reg_field_value( -+ regval, -+ info_packet->hb2, -+ AFMT_GENERIC_HDR, -+ AFMT_GENERIC_HB2); -+ -+ set_reg_field_value( -+ regval, -+ info_packet->hb3, -+ AFMT_GENERIC_HDR, -+ AFMT_GENERIC_HB3); -+ -+ dal_write_reg(enc->ctx, addr, regval); -+ } -+ -+ /* write generic packet contents -+ * (we never use last 4 bytes) -+ * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers */ -+ { -+ const uint32_t *content = -+ (const uint32_t *) &info_packet->sb[0]; -+ -+ uint32_t counter = 0; -+ -+ addr = mmAFMT_GENERIC_0 + fe_engine_offsets[engine]; -+ -+ do { -+ dal_write_reg(enc->ctx, addr++, *content++); -+ -+ ++counter; -+ } while (counter < 7); -+ } -+ -+ dal_write_reg( -+ enc->ctx, -+ mmAFMT_GENERIC_7 + fe_engine_offsets[engine], -+ 0); -+ -+ /* force double-buffered packet update */ -+ { -+ addr = mmAFMT_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; -+ -+ regval = dal_read_reg(enc->ctx, addr); -+ -+ set_reg_field_value( -+ regval, -+ (packet_index == 0), -+ AFMT_VBI_PACKET_CONTROL, -+ AFMT_GENERIC0_UPDATE); -+ -+ set_reg_field_value( -+ regval, -+ (packet_index == 2), -+ AFMT_VBI_PACKET_CONTROL, -+ AFMT_GENERIC2_UPDATE); -+ -+ dal_write_reg(enc->ctx, addr, regval); -+ } -+} -+ -+static void update_hdmi_info_packet( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ uint32_t packet_index, -+ const struct encoder_info_packet *info_packet) -+{ -+ uint32_t cont, send, line; -+ uint32_t addr = fe_engine_offsets[engine]; -+ uint32_t regval; -+ -+ if (info_packet->valid) { -+ update_generic_info_packet( -+ enc, -+ engine, -+ packet_index, -+ info_packet); -+ -+ /* enable transmission of packet(s) - -+ * packet transmission begins on the next frame */ -+ cont = 1; -+ /* send packet(s) every frame */ -+ send = 1; -+ /* select line number to send packets on */ -+ line = 2; -+ } else { -+ cont = 0; -+ send = 0; -+ line = 0; -+ } -+ -+ /* choose which generic packet control to use */ -+ -+ switch (packet_index) { -+ case 0: -+ case 1: -+ addr += mmHDMI_GENERIC_PACKET_CONTROL0; -+ break; -+ case 2: -+ case 3: -+ addr += mmHDMI_GENERIC_PACKET_CONTROL1; -+ break; -+ default: -+ /* invalid HW packet index */ -+ dal_logger_write( -+ enc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_ENCODER, -+ "Invalid HW packet index: %s()\n", -+ __func__); -+ break; -+ } -+ -+ regval = dal_read_reg(enc->ctx, addr); -+ -+ switch (packet_index) { -+ case 0: -+ case 2: -+ set_reg_field_value( -+ regval, -+ cont, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_CONT); -+ set_reg_field_value( -+ regval, -+ send, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_SEND); -+ set_reg_field_value( -+ regval, -+ line, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC0_LINE); -+ break; -+ case 1: -+ case 3: -+ set_reg_field_value( -+ regval, -+ cont, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_CONT); -+ set_reg_field_value( -+ regval, -+ send, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_SEND); -+ set_reg_field_value( -+ regval, -+ line, -+ HDMI_GENERIC_PACKET_CONTROL0, -+ HDMI_GENERIC1_LINE); -+ break; -+ default: -+ /* invalid HW packet index */ -+ dal_logger_write( -+ enc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_ENCODER, -+ "Invalid HW packet index: %s()\n", -+ __func__); -+ break; -+ } -+ -+ dal_write_reg(enc->ctx, addr, regval); -+} -+ -+static void update_dp_info_packet( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ uint32_t packet_index, -+ const struct encoder_info_packet *info_packet) -+{ -+ const uint32_t addr = mmDP_SEC_CNTL + fe_engine_offsets[engine]; -+ -+ uint32_t value; -+ -+ if (info_packet->valid) -+ update_generic_info_packet( -+ enc, -+ engine, -+ packet_index, -+ info_packet); -+ -+ /* enable/disable transmission of packet(s). -+ * If enabled, packet transmission begins on the next frame */ -+ -+ value = dal_read_reg(enc->ctx, addr); -+ -+ switch (packet_index) { -+ case 0: -+ set_reg_field_value( -+ value, -+ info_packet->valid, -+ DP_SEC_CNTL, -+ DP_SEC_GSP0_ENABLE); -+ break; -+ case 1: -+ set_reg_field_value( -+ value, -+ info_packet->valid, -+ DP_SEC_CNTL, -+ DP_SEC_GSP1_ENABLE); -+ break; -+ case 2: -+ set_reg_field_value( -+ value, -+ info_packet->valid, -+ DP_SEC_CNTL, -+ DP_SEC_GSP2_ENABLE); -+ break; -+ case 3: -+ set_reg_field_value( -+ value, -+ info_packet->valid, -+ DP_SEC_CNTL, -+ DP_SEC_GSP3_ENABLE); -+ break; -+ default: -+ /* invalid HW packet index */ -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ /* This bit is the master enable bit. -+ * When enabling secondary stream engine, -+ * this master bit must also be set. -+ * This register shared with audio info frame. -+ * Therefore we need to enable master bit -+ * if at least on of the fields is not 0 */ -+ -+ if (value) -+ set_reg_field_value( -+ value, -+ 1, -+ DP_SEC_CNTL, -+ DP_SEC_STREAM_ENABLE); -+ -+ dal_write_reg(enc->ctx, addr, value); -+} -+ -+void dce110_stream_encoder_update_info_packets( -+ struct stream_encoder *enc, -+ enum signal_type signal, -+ const struct encoder_info_frame *info_frame) -+{ -+ if (dc_is_hdmi_signal(signal)) { -+ update_avi_info_packet( -+ enc, -+ enc->id, -+ signal, -+ &info_frame->avi); -+ update_hdmi_info_packet(enc, enc->id, 0, &info_frame->vendor); -+ update_hdmi_info_packet(enc, enc->id, 1, &info_frame->gamut); -+ update_hdmi_info_packet(enc, enc->id, 2, &info_frame->spd); -+ } else if (dc_is_dp_signal(signal)) -+ update_dp_info_packet(enc, enc->id, 0, &info_frame->vsc); -+} -+ -+static void dp_steer_fifo_reset( -+ struct dc_context *ctx, -+ enum engine_id engine, -+ bool reset) -+{ -+ const uint32_t addr = mmDP_STEER_FIFO + fe_engine_offsets[engine]; -+ -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, reset, DP_STEER_FIFO, DP_STEER_FIFO_RESET); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+/* -+ * @brief -+ * Output blank data, -+ * prevents output of the actual surface data on active transmitter -+ */ -+enum encoder_result dce110_stream_encoder_blank( -+ struct stream_encoder *enc, -+ enum signal_type signal) -+{ -+ enum engine_id engine = enc->id; -+ const uint32_t addr = mmDP_VID_STREAM_CNTL + fe_engine_offsets[engine]; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ uint32_t retries = 0; -+ uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; -+ -+ if (!dc_is_dp_signal(signal)) -+ return ENCODER_RESULT_OK; -+ -+ /* Note: For CZ, we are changing driver default to disable -+ * stream deferred to next VBLANK. If results are positive, we -+ * will make the same change to all DCE versions. There are a -+ * handful of panels that cannot handle disable stream at -+ * HBLANK and will result in a white line flash across the -+ * screen on stream disable. */ -+ -+ /* Specify the video stream disable point -+ * (2 = start of the next vertical blank) */ -+ set_reg_field_value( -+ value, -+ 2, -+ DP_VID_STREAM_CNTL, -+ DP_VID_STREAM_DIS_DEFER); -+ /* Larger delay to wait until VBLANK - use max retry of -+ * 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode + -+ * a little more because we may not trust delay accuracy. */ -+ max_retries = DP_BLANK_MAX_RETRY * 150; -+ -+ /* disable DP stream */ -+ set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ /* the encoder stops sending the video stream -+ * at the start of the vertical blanking. -+ * Poll for DP_VID_STREAM_STATUS == 0 */ -+ -+ do { -+ value = dal_read_reg(enc->ctx, addr); -+ -+ if (!get_reg_field_value( -+ value, -+ DP_VID_STREAM_CNTL, -+ DP_VID_STREAM_STATUS)) -+ break; -+ -+ dc_service_delay_in_microseconds(enc->ctx, 10); -+ -+ ++retries; -+ } while (retries < max_retries); -+ -+ ASSERT(retries <= max_retries); -+ -+ /* Tell the DP encoder to ignore timing from CRTC, must be done after -+ * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is -+ * complete, stream status will be stuck in video stream enabled state, -+ * i.e. DP_VID_STREAM_STATUS stuck at 1. */ -+ dp_steer_fifo_reset(enc->ctx, engine, true); -+ -+ return ENCODER_RESULT_OK; -+} -+ -+static void unblank_dp_output( -+ struct stream_encoder *enc, -+ enum engine_id engine) -+{ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* set DIG_START to 0x1 to resync FIFO */ -+ addr = mmDIG_FE_CNTL + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 1, DIG_FE_CNTL, DIG_START); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ /* switch DP encoder to CRTC data */ -+ dp_steer_fifo_reset(enc->ctx, engine, false); -+ -+ /* wait 100us for DIG/DP logic to prime -+ * (i.e. a few video lines) */ -+ dc_service_delay_in_microseconds(enc->ctx, 100); -+ -+ /* the hardware would start sending video at the start of the next DP -+ * frame (i.e. rising edge of the vblank). -+ * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this -+ * register has no effect on enable transition! HW always guarantees -+ * VID_STREAM enable at start of next frame, and this is not -+ * programmable */ -+ addr = mmDP_VID_STREAM_CNTL + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value( -+ value, -+ true, -+ DP_VID_STREAM_CNTL, -+ DP_VID_STREAM_ENABLE); -+ dal_write_reg(enc->ctx, addr, value); -+ -+} -+ -+static void setup_vid_stream( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ uint32_t m_vid, -+ uint32_t n_vid) -+{ -+ uint32_t addr; -+ uint32_t value; -+ -+ /* enable auto measurement */ -+ addr = mmDP_VID_TIMING + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 0, DP_VID_TIMING, DP_VID_M_N_GEN_EN); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ /* auto measurement need 1 full 0x8000 symbol cycle to kick in, -+ * therefore program initial value for Mvid and Nvid */ -+ addr = mmDP_VID_N + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, n_vid, DP_VID_N, DP_VID_N); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmDP_VID_M + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, m_vid, DP_VID_M, DP_VID_M); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmDP_VID_TIMING + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 1, DP_VID_TIMING, DP_VID_M_N_GEN_EN); -+ dal_write_reg(enc->ctx, addr, value); -+} -+/* -+ * @brief -+ * Stop sending blank data, -+ * output the actual surface data on active transmitter -+ */ -+enum encoder_result dce110_stream_encoder_unblank( -+ struct stream_encoder *enc, -+ const struct encoder_unblank_param *param) -+{ -+ bool is_dp_signal = param->signal == SIGNAL_TYPE_DISPLAY_PORT -+ || param->signal == SIGNAL_TYPE_DISPLAY_PORT_MST -+ || param->signal == SIGNAL_TYPE_EDP; -+ -+ if (!is_dp_signal) -+ return ENCODER_RESULT_OK; -+ -+ 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; -+ -+ setup_vid_stream(enc, -+ enc->id, m_vid, n_vid); -+ } -+ -+ unblank_dp_output(enc, enc->id); -+ -+ return ENCODER_RESULT_OK; -+} -+ -+static void set_dp_stream_attributes( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ const struct dc_crtc_timing *timing) -+{ -+ const uint32_t addr = mmDP_PIXEL_FORMAT + fe_engine_offsets[engine]; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ -+ /* set pixel encoding */ -+ switch (timing->pixel_encoding) { -+ case PIXEL_ENCODING_YCBCR422: -+ set_reg_field_value( -+ value, -+ DP_PIXEL_ENCODING_YCBCR422, -+ DP_PIXEL_FORMAT, -+ DP_PIXEL_ENCODING); -+ break; -+ case PIXEL_ENCODING_YCBCR444: -+ set_reg_field_value( -+ value, -+ DP_PIXEL_ENCODING_YCBCR444, -+ DP_PIXEL_FORMAT, -+ DP_PIXEL_ENCODING); -+ -+ if (timing->flags.Y_ONLY) -+ if (timing->display_color_depth != COLOR_DEPTH_666) -+ /* HW testing only, no use case yet. -+ * Color depth of Y-only could be -+ * 8, 10, 12, 16 bits */ -+ set_reg_field_value( -+ value, -+ DP_PIXEL_ENCODING_Y_ONLY, -+ DP_PIXEL_FORMAT, -+ DP_PIXEL_ENCODING); -+ /* Note: DP_MSA_MISC1 bit 7 is the indicator -+ * of Y-only mode. -+ * This bit is set in HW if register -+ * DP_PIXEL_ENCODING is programmed to 0x4 */ -+ break; -+ default: -+ set_reg_field_value( -+ value, -+ DP_PIXEL_ENCODING_RGB444, -+ DP_PIXEL_FORMAT, -+ DP_PIXEL_ENCODING); -+ break; -+ } -+ -+ /* set color depth */ -+ -+ switch (timing->display_color_depth) { -+ case COLOR_DEPTH_888: -+ set_reg_field_value( -+ value, -+ DP_COMPONENT_DEPTH_8BPC, -+ DP_PIXEL_FORMAT, -+ DP_COMPONENT_DEPTH); -+ break; -+ case COLOR_DEPTH_101010: -+ set_reg_field_value( -+ value, -+ DP_COMPONENT_DEPTH_10BPC, -+ DP_PIXEL_FORMAT, -+ DP_COMPONENT_DEPTH); -+ break; -+ case COLOR_DEPTH_121212: -+ set_reg_field_value( -+ value, -+ DP_COMPONENT_DEPTH_12BPC, -+ DP_PIXEL_FORMAT, -+ DP_COMPONENT_DEPTH); -+ break; -+ default: -+ set_reg_field_value( -+ value, -+ DP_COMPONENT_DEPTH_6BPC, -+ DP_PIXEL_FORMAT, -+ DP_COMPONENT_DEPTH); -+ break; -+ } -+ -+ /* set dynamic range and YCbCr range */ -+ set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_DYN_RANGE); -+ set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_YCBCR_RANGE); -+ -+ dal_write_reg(enc->ctx, addr, value); -+} -+ -+static void setup_hdmi( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t output_pixel_clock = timing->pix_clk_khz; -+ uint32_t value; -+ uint32_t addr; -+ -+ addr = mmHDMI_CONTROL + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_PACKET_GEN_VERSION); -+ set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_KEEPOUT_MODE); -+ set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE); -+ set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN); -+ set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE); -+ -+ switch (timing->display_color_depth) { -+ case COLOR_DEPTH_888: -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_DEPTH); -+ break; -+ case COLOR_DEPTH_101010: -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_DEPTH); -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_ENABLE); -+ output_pixel_clock = (timing->pix_clk_khz * 30) / 24; -+ break; -+ case COLOR_DEPTH_121212: -+ set_reg_field_value( -+ value, -+ 2, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_DEPTH); -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_ENABLE); -+ output_pixel_clock = (timing->pix_clk_khz * 36) / 24; -+ break; -+ case COLOR_DEPTH_161616: -+ set_reg_field_value( -+ value, -+ 3, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_DEPTH); -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DEEP_COLOR_ENABLE); -+ output_pixel_clock = (timing->pix_clk_khz * 48) / 24; -+ break; -+ default: -+ break; -+ } -+ -+ if (output_pixel_clock >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { -+ /* enable HDMI data scrambler */ -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DATA_SCRAMBLE_EN); -+ -+ /* HDMI_CLOCK_CHANNEL_RATE_MORE_340M -+ * Clock channel frequency is 1/4 of character rate.*/ -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_CLOCK_CHANNEL_RATE); -+ } else if (timing->flags.LTE_340MCSC_SCRAMBLE) { -+ -+ /* TODO: New feature for DCE11, still need to implement */ -+ -+ /* enable HDMI data scrambler */ -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_CONTROL, -+ HDMI_DATA_SCRAMBLE_EN); -+ -+ /* HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE -+ * Clock channel frequency is the same -+ * as character rate */ -+ set_reg_field_value( -+ value, -+ 0, -+ HDMI_CONTROL, -+ HDMI_CLOCK_CHANNEL_RATE); -+ } -+ -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmHDMI_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT); -+ set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND); -+ set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND); -+ -+ dal_write_reg(enc->ctx, addr, value); -+ -+ /* following belongs to audio */ -+ addr = mmHDMI_INFOFRAME_CONTROL0 + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ HDMI_INFOFRAME_CONTROL0, -+ HDMI_AUDIO_INFO_SEND); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmAFMT_INFOFRAME_CONTROL0 + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value( -+ value, -+ 1, -+ AFMT_INFOFRAME_CONTROL0, -+ AFMT_AUDIO_INFO_UPDATE); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmHDMI_INFOFRAME_CONTROL1 + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value( -+ value, -+ VBI_LINE_0 + 2, -+ HDMI_INFOFRAME_CONTROL1, -+ HDMI_AUDIO_INFO_LINE); -+ dal_write_reg(enc->ctx, addr, value); -+ -+ addr = mmHDMI_GC + fe_engine_offsets[engine]; -+ value = dal_read_reg(enc->ctx, addr); -+ set_reg_field_value(value, 0, HDMI_GC, HDMI_GC_AVMUTE); -+ dal_write_reg(enc->ctx, addr, value); -+ -+} -+ -+static void set_tmds_stream_attributes( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ enum signal_type signal, -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t addr = mmDIG_FE_CNTL + fe_engine_offsets[engine]; -+ uint32_t value = dal_read_reg(enc->ctx, addr); -+ -+ switch (timing->pixel_encoding) { -+ case PIXEL_ENCODING_YCBCR422: -+ set_reg_field_value(value, 1, DIG_FE_CNTL, TMDS_PIXEL_ENCODING); -+ break; -+ default: -+ set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_PIXEL_ENCODING); -+ break; -+ } -+ -+ switch (timing->pixel_encoding) { -+ case COLOR_DEPTH_101010: -+ if ((signal == SIGNAL_TYPE_DVI_SINGLE_LINK -+ || signal == SIGNAL_TYPE_DVI_DUAL_LINK) -+ && timing->pixel_encoding == PIXEL_ENCODING_RGB) -+ set_reg_field_value( -+ value, -+ 2, -+ DIG_FE_CNTL, -+ TMDS_COLOR_FORMAT); -+ else -+ set_reg_field_value( -+ value, -+ 0, -+ DIG_FE_CNTL, -+ TMDS_COLOR_FORMAT); -+ break; -+ default: -+ set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT); -+ break; -+ } -+ dal_write_reg(enc->ctx, addr, value); -+} -+ -+/* -+ * @brief -+ * Associate digital encoder with specified output transmitter -+ * and configure to output signal. -+ * Encoder will be activated later in enable_output() -+ */ -+enum encoder_result dce110_stream_encoder_setup( -+ struct stream_encoder *enc, -+ struct dc_crtc_timing *crtc_timing, -+ enum signal_type signal, -+ bool enable_audio) -+{ -+ if (!dc_is_dp_signal(signal)) { -+ struct bp_encoder_control cntl; -+ -+ cntl.action = ENCODER_CONTROL_SETUP; -+ cntl.engine_id = enc->id; -+ cntl.signal = signal; -+ cntl.enable_dp_audio = enable_audio; -+ cntl.pixel_clock = crtc_timing->pix_clk_khz; -+ cntl.lanes_number = (signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? -+ LANE_COUNT_EIGHT : LANE_COUNT_FOUR; -+ cntl.color_depth = crtc_timing->display_color_depth; -+ -+ if (dal_bios_parser_encoder_control( -+ dal_adapter_service_get_bios_parser( -+ enc->adapter_service), -+ &cntl) != BP_RESULT_OK) -+ return ENCODER_RESULT_ERROR; -+ } -+ -+ switch (signal) { -+ case SIGNAL_TYPE_DVI_SINGLE_LINK: -+ case SIGNAL_TYPE_DVI_DUAL_LINK: -+ /* set signal format */ -+ set_tmds_stream_attributes( -+ enc, enc->id, signal, -+ crtc_timing); -+ break; -+ case SIGNAL_TYPE_HDMI_TYPE_A: -+ /* set signal format */ -+ set_tmds_stream_attributes( -+ enc, enc->id, signal, -+ crtc_timing); -+ /* setup HDMI engine */ -+ setup_hdmi( -+ enc, enc->id, crtc_timing); -+ break; -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ /* set signal format */ -+ set_dp_stream_attributes(enc, enc->id, crtc_timing); -+ break; -+ default: -+ break; -+ } -+ -+ return ENCODER_RESULT_OK; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h -new file mode 100644 -index 0000000..d2c7b90 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h -@@ -0,0 +1,64 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_STREAM_ENCODER_DCE110_H__ -+#define __DC_STREAM_ENCODER_DCE110_H__ -+ -+struct stream_enc_init_data { -+ enum engine_id stream_engine_id; -+ struct adapter_service *adapter_service; -+ struct dc_context *ctx; -+}; -+ -+struct stream_encoder *dce110_stream_encoder_create( -+ struct stream_enc_init_data *init); -+ -+void dce110_stream_encoder_destroy(struct stream_encoder **enc); -+ -+void dce110_stream_encoder_stop_info_packets( -+ struct stream_encoder *enc, -+ enum engine_id engine, -+ enum signal_type signal); -+ -+void dce110_stream_encoder_update_info_packets( -+ struct stream_encoder *enc, -+ enum signal_type signal, -+ const struct encoder_info_frame *info_frame); -+ -+enum encoder_result dce110_stream_encoder_blank( -+ struct stream_encoder *enc, -+ enum signal_type signal); -+ -+enum encoder_result dce110_stream_encoder_unblank( -+ struct stream_encoder *enc, -+ const struct encoder_unblank_param *param); -+ -+enum encoder_result dce110_stream_encoder_setup( -+ struct stream_encoder *enc, -+ struct dc_crtc_timing *crtc_timing, -+ enum signal_type signal, -+ bool enable_audio); -+ -+#endif /* __DC_STREAM_ENCODER_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c -new file mode 100644 -index 0000000..198ff28 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c -@@ -0,0 +1,1878 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 "include/grph_object_id.h" -+#include "include/adapter_service_interface.h" -+#include "include/logger_interface.h" -+#include "include/timing_generator_types.h" -+#include "dce110_timing_generator.h" -+ -+ -+enum tg_regs_idx { -+ IDX_CRTC_UPDATE_LOCK, -+ IDX_CRTC_MASTER_UPDATE_LOCK, -+ IDX_CRTC_MASTER_UPDATE_MODE, -+ IDX_CRTC_H_TOTAL, -+ IDX_CRTC_V_TOTAL, -+ IDX_CRTC_H_BLANK_START_END, -+ IDX_CRTC_V_BLANK_START_END, -+ IDX_CRTC_H_SYNC_A, -+ IDX_CRTC_V_SYNC_A, -+ IDX_CRTC_H_SYNC_A_CNTL, -+ IDX_CRTC_V_SYNC_A_CNTL, -+ IDX_CRTC_INTERLACE_CONTROL, -+ IDX_CRTC_BLANK_CONTROL, -+ IDX_PIPE_PG_STATUS, -+ -+ IDX_CRTC_TEST_PATTERN_COLOR, -+ IDX_CRTC_TEST_PATTERN_CONTROL, -+ IDX_CRTC_TEST_PATTERN_PARAMETERS, -+ IDX_CRTC_FLOW_CONTROL, -+ IDX_CRTC_STATUS, -+ IDX_CRTC_STATUS_POSITION, -+ IDX_CRTC_STATUS_FRAME_COUNT, -+ IDX_CRTC_STEREO_CONTROL, -+ IDX_CRTC_STEREO_STATUS, -+ IDX_CRTC_STEREO_FORCE_NEXT_EYE, -+ IDX_CRTC_3D_STRUCTURE_CONTROL, -+ IDX_CRTC_DOUBLE_BUFFER_CONTROL, -+ IDX_CRTC_V_TOTAL_MIN, -+ IDX_CRTC_V_TOTAL_MAX, -+ IDX_CRTC_V_TOTAL_CONTROL, -+ IDX_CRTC_NOM_VERT_POSITION, -+ IDX_CRTC_STATIC_SCREEN_CONTROL, -+ IDX_CRTC_TRIGB_CNTL, -+ IDX_CRTC_FORCE_COUNT_CNTL, -+ IDX_CRTC_GSL_CONTROL, -+ IDX_CRTC_GSL_WINDOW, -+ -+ IDX_CRTC_CONTROL, -+ IDX_CRTC_START_LINE_CONTROL, -+ IDX_CRTC_COUNT_CONTROL, -+ -+ IDX_MODE_EXT_OVERSCAN_LEFT_RIGHT, -+ IDX_MODE_EXT_OVERSCAN_TOP_BOTTOM, -+ IDX_DCP_GSL_CONTROL, -+ IDX_GRPH_UPDATE, -+ -+ IDX_CRTC_VBI_END, -+ -+ IDX_BLND_UNDERFLOW_INTERRUPT, -+ IDX_CRTC_BLACK_COLOR, -+ IDX_CRTC_OVERSCAN_COLOR, -+ IDX_CRTC_BLANK_DATA_COLOR, -+ -+ TG_REGS_IDX_SIZE -+}; -+ -+enum black_color_format { -+ BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, /* used as index in array */ -+ BLACK_COLOR_FORMAT_RGB_LIMITED, -+ BLACK_COLOR_FORMAT_YUV_TV, -+ BLACK_COLOR_FORMAT_YUV_CV, -+ BLACK_COLOR_FORMAT_YUV_SUPER_AA, -+ -+ BLACK_COLOR_FORMAT_COUNT -+}; -+ -+#define regs_for_controller(id)\ -+[CONTROLLER_ID_D ## id - 1] =\ -+{[IDX_CRTC_UPDATE_LOCK] = mmCRTC ## id ## _CRTC_UPDATE_LOCK,\ -+[IDX_CRTC_MASTER_UPDATE_LOCK] = mmCRTC ## id ## _CRTC_MASTER_UPDATE_LOCK,\ -+[IDX_CRTC_MASTER_UPDATE_MODE] = mmCRTC ## id ## _CRTC_MASTER_UPDATE_MODE,\ -+[IDX_CRTC_H_TOTAL] = mmCRTC ## id ## _CRTC_H_TOTAL,\ -+[IDX_CRTC_V_TOTAL] = mmCRTC ## id ## _CRTC_V_TOTAL,\ -+[IDX_CRTC_H_BLANK_START_END] = mmCRTC ## id ## _CRTC_H_BLANK_START_END,\ -+[IDX_CRTC_V_BLANK_START_END] = mmCRTC ## id ## _CRTC_V_BLANK_START_END,\ -+[IDX_CRTC_H_SYNC_A] = mmCRTC ## id ## _CRTC_H_SYNC_A,\ -+[IDX_CRTC_V_SYNC_A] = mmCRTC ## id ## _CRTC_V_SYNC_A,\ -+[IDX_CRTC_H_SYNC_A_CNTL] = mmCRTC ## id ## _CRTC_H_SYNC_A_CNTL,\ -+[IDX_CRTC_V_SYNC_A_CNTL] = mmCRTC ## id ## _CRTC_V_SYNC_A_CNTL,\ -+[IDX_CRTC_INTERLACE_CONTROL] = mmCRTC ## id ## _CRTC_INTERLACE_CONTROL,\ -+[IDX_CRTC_BLANK_CONTROL] = mmCRTC ## id ## _CRTC_BLANK_CONTROL,\ -+[IDX_PIPE_PG_STATUS] = mmPIPE ## id ## _PG_STATUS,\ -+[IDX_CRTC_TEST_PATTERN_COLOR] = mmCRTC ## id ## _CRTC_TEST_PATTERN_COLOR,\ -+[IDX_CRTC_TEST_PATTERN_CONTROL] = mmCRTC ## id ## _CRTC_TEST_PATTERN_CONTROL,\ -+[IDX_CRTC_TEST_PATTERN_PARAMETERS] =\ -+mmCRTC ## id ## _CRTC_TEST_PATTERN_PARAMETERS,\ -+[IDX_CRTC_FLOW_CONTROL] = mmCRTC ## id ## _CRTC_FLOW_CONTROL,\ -+[IDX_CRTC_STATUS] = mmCRTC ## id ## _CRTC_STATUS,\ -+[IDX_CRTC_STATUS_POSITION] = mmCRTC ## id ## _CRTC_STATUS_POSITION,\ -+[IDX_CRTC_STATUS_FRAME_COUNT] = mmCRTC ## id ## _CRTC_STATUS_FRAME_COUNT,\ -+[IDX_CRTC_STEREO_CONTROL] = mmCRTC ## id ## _CRTC_STEREO_CONTROL,\ -+[IDX_CRTC_STEREO_STATUS] = mmCRTC ## id ## _CRTC_STEREO_STATUS,\ -+[IDX_CRTC_STEREO_FORCE_NEXT_EYE] = \ -+mmCRTC ## id ## _CRTC_STEREO_FORCE_NEXT_EYE,\ -+[IDX_CRTC_3D_STRUCTURE_CONTROL] = mmCRTC ## id ## _CRTC_3D_STRUCTURE_CONTROL,\ -+[IDX_CRTC_DOUBLE_BUFFER_CONTROL] =\ -+mmCRTC ## id ## _CRTC_DOUBLE_BUFFER_CONTROL,\ -+[IDX_CRTC_V_TOTAL_MIN] = mmCRTC ## id ## _CRTC_V_TOTAL_MIN,\ -+[IDX_CRTC_V_TOTAL_MAX] = mmCRTC ## id ## _CRTC_V_TOTAL_MAX,\ -+[IDX_CRTC_V_TOTAL_CONTROL] = mmCRTC ## id ## _CRTC_V_TOTAL_CONTROL,\ -+[IDX_CRTC_NOM_VERT_POSITION] = mmCRTC ## id ## _CRTC_NOM_VERT_POSITION,\ -+[IDX_CRTC_STATIC_SCREEN_CONTROL] =\ -+mmCRTC ## id ## _CRTC_STATIC_SCREEN_CONTROL,\ -+[IDX_CRTC_TRIGB_CNTL] = mmCRTC ## id ## _CRTC_TRIGB_CNTL,\ -+[IDX_CRTC_FORCE_COUNT_CNTL] = mmCRTC ## id ## _CRTC_FORCE_COUNT_NOW_CNTL,\ -+[IDX_CRTC_GSL_CONTROL] = mmCRTC ## id ## _CRTC_GSL_CONTROL,\ -+[IDX_CRTC_GSL_WINDOW] = mmCRTC ## id ## _CRTC_GSL_WINDOW,\ -+[IDX_CRTC_CONTROL] = mmCRTC ## id ## _CRTC_CONTROL,\ -+[IDX_CRTC_START_LINE_CONTROL] = mmCRTC ## id ## _CRTC_START_LINE_CONTROL,\ -+[IDX_CRTC_COUNT_CONTROL] = mmCRTC ## id ## _CRTC_COUNT_CONTROL,\ -+[IDX_MODE_EXT_OVERSCAN_LEFT_RIGHT] = mmSCL ## id ## _EXT_OVERSCAN_LEFT_RIGHT,\ -+[IDX_MODE_EXT_OVERSCAN_TOP_BOTTOM] = mmSCL ## id ## _EXT_OVERSCAN_TOP_BOTTOM,\ -+[IDX_DCP_GSL_CONTROL] = mmDCP ## id ## _DCP_GSL_CONTROL,\ -+[IDX_GRPH_UPDATE] = mmDCP ## id ## _GRPH_UPDATE,\ -+[IDX_CRTC_VBI_END] = mmCRTC ## id ## _CRTC_VBI_END,\ -+[IDX_BLND_UNDERFLOW_INTERRUPT] = mmBLND ## id ## _BLND_UNDERFLOW_INTERRUPT,\ -+[IDX_CRTC_BLACK_COLOR] = mmCRTC ## id ## _CRTC_BLACK_COLOR,\ -+[IDX_CRTC_OVERSCAN_COLOR] = mmCRTC ## id ## _CRTC_OVERSCAN_COLOR,\ -+[IDX_CRTC_BLANK_DATA_COLOR] = mmCRTC ## id ## _CRTC_BLANK_DATA_COLOR,\ -+} -+ -+#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 FROM_TIMING_GENERATOR(tg)\ -+ container_of(tg, struct dce110_timing_generator, base) -+ -+static uint32_t tg_regs[][TG_REGS_IDX_SIZE] = { -+ regs_for_controller(0), -+ regs_for_controller(1), -+ regs_for_controller(2), -+}; -+ -+/******************************************************************************* -+ * GSL Sync related values */ -+ -+/* In VSync mode, after 4 units of time, master pipe will generate -+ * flip_ready signal */ -+#define VFLIP_READY_DELAY 4 -+/* In HSync mode, after 2 units of time, master pipe will generate -+ * flip_ready signal */ -+#define HFLIP_READY_DELAY 2 -+/* 6 lines delay between forcing flip and checking all pipes ready */ -+#define HFLIP_CHECK_DELAY 6 -+/* 3 lines before end of frame */ -+#define FLIP_READY_BACK_LOOKUP 3 -+ -+/* Trigger Source Select - ASIC-dependant, actual values for the -+ * register programming */ -+enum trigger_source_select { -+ TRIGGER_SOURCE_SELECT_LOGIC_ZERO = 0, -+ TRIGGER_SOURCE_SELECT_CRTC_VSYNCA = 1, -+ TRIGGER_SOURCE_SELECT_CRTC_HSYNCA = 2, -+ TRIGGER_SOURCE_SELECT_CRTC_VSYNCB = 3, -+ TRIGGER_SOURCE_SELECT_CRTC_HSYNCB = 4, -+ TRIGGER_SOURCE_SELECT_GENERICF = 5, -+ TRIGGER_SOURCE_SELECT_GENERICE = 6, -+ TRIGGER_SOURCE_SELECT_VSYNCA = 7, -+ TRIGGER_SOURCE_SELECT_HSYNCA = 8, -+ TRIGGER_SOURCE_SELECT_VSYNCB = 9, -+ TRIGGER_SOURCE_SELECT_HSYNCB = 10, -+ TRIGGER_SOURCE_SELECT_HPD1 = 11, -+ TRIGGER_SOURCE_SELECT_HPD2 = 12, -+ TRIGGER_SOURCE_SELECT_GENERICD = 13, -+ TRIGGER_SOURCE_SELECT_GENERICC = 14, -+ TRIGGER_SOURCE_SELECT_VIDEO_CAPTURE = 15, -+ TRIGGER_SOURCE_SELECT_GSL_GROUP0 = 16, -+ TRIGGER_SOURCE_SELECT_GSL_GROUP1 = 17, -+ TRIGGER_SOURCE_SELECT_GSL_GROUP2 = 18, -+ TRIGGER_SOURCE_SELECT_BLONY = 19, -+ TRIGGER_SOURCE_SELECT_GENERICA = 20, -+ TRIGGER_SOURCE_SELECT_GENERICB = 21, -+ TRIGGER_SOURCE_SELECT_GSL_ALLOW_FLIP = 22, -+ TRIGGER_SOURCE_SELECT_MANUAL_TRIGGER = 23 -+}; -+ -+/* Trigger Source Select - ASIC-dependant, actual values for the -+ * register programming */ -+enum trigger_polarity_select { -+ TRIGGER_POLARITY_SELECT_LOGIC_ZERO = 0, -+ TRIGGER_POLARITY_SELECT_CRTC = 1, -+ TRIGGER_POLARITY_SELECT_GENERICA = 2, -+ TRIGGER_POLARITY_SELECT_GENERICB = 3, -+ TRIGGER_POLARITY_SELECT_HSYNCA = 4, -+ TRIGGER_POLARITY_SELECT_HSYNCB = 5, -+ TRIGGER_POLARITY_SELECT_VIDEO_CAPTURE = 6, -+ TRIGGER_POLARITY_SELECT_GENERICC = 7 -+}; -+ -+/******************************************************************************/ -+ -+bool dce110_timing_generator_construct( -+ struct timing_generator *tg, -+ enum controller_id id) -+{ -+ tg->controller_id = id; -+ return true; -+} -+ -+static const struct crtc_black_color black_color_format[] = { -+ /* BlackColorFormat_RGB_FullRange */ -+ {0, 0, 0}, -+ /* BlackColorFormat_RGB_Limited */ -+ {CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE}, -+ /* BlackColorFormat_YUV_TV */ -+ {CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV}, -+ /* BlackColorFormat_YUV_CV */ -+ {CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV}, -+ /* BlackColorFormat_YUV_SuperAA */ -+ {CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA} -+}; -+ -+void dce110_timing_generator_color_space_to_black_color( -+ enum color_space colorspace, -+ struct crtc_black_color *black_color) -+{ -+ switch (colorspace) { -+ case COLOR_SPACE_YPBPR601: -+ *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV]; -+ break; -+ -+ case COLOR_SPACE_YPBPR709: -+ case COLOR_SPACE_YCBCR601: -+ case COLOR_SPACE_YCBCR709: -+ *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; -+ break; -+ -+ case COLOR_SPACE_N_MVPU_SUPER_AA: -+ /* In crossfire SuperAA mode, the slave overscan data is forced -+ * to 0 in the pixel mixer on the master. As a result, we need -+ * to adjust the blank color so that after blending the -+ * master+slave, it will appear black -+ */ -+ *black_color = -+ black_color_format[BLACK_COLOR_FORMAT_YUV_SUPER_AA]; -+ break; -+ -+ case COLOR_SPACE_SRGB_LIMITED_RANGE: -+ *black_color = -+ black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED]; -+ break; -+ -+ default: -+ /* fefault is sRGB black (full range). */ -+ *black_color = -+ black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE]; -+ /* default is sRGB black 0. */ -+ break; -+ } -+} -+ -+/** -+* 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. -+*/ -+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; -+ } -+} -+ -+int32_t dce110_timing_generator_get_vsynch_and_front_porch_size( -+ const struct dc_crtc_timing *timing) -+{ -+ return timing->v_sync_width + timing->v_front_porch; -+} -+ -+ -+void dce110_timing_generator_set_early_control( -+ struct timing_generator *tg, -+ uint32_t early_cntl) -+{ -+ uint32_t regval; -+ uint32_t address = tg->regs[IDX_CRTC_CONTROL]; -+ -+ regval = dal_read_reg(tg->ctx, address); -+ set_reg_field_value(regval, early_cntl, -+ CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL); -+ dal_write_reg(tg->ctx, address, regval); -+} -+ -+/** -+ * Enable CRTC -+ * Enable CRTC - call ASIC Control Object to enable Timing generator. -+ */ -+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg) -+{ -+ enum bp_result result; -+ -+ /* 0 value is needed by DRR and is also suggested default value for CZ -+ */ -+ uint32_t value; -+ -+ value = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_MASTER_UPDATE_MODE]); -+ set_reg_field_value(value, 3, -+ CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE); -+ dal_write_reg(tg->ctx, -+ tg->regs[IDX_CRTC_MASTER_UPDATE_MODE], value); -+ -+ result = dal_bios_parser_enable_crtc(tg->bp, tg->controller_id, true); -+ -+ return result == BP_RESULT_OK; -+} -+ -+void dce110_timing_generator_program_blank_color( -+ struct timing_generator *tg, -+ enum color_space color_space) -+{ -+ struct crtc_black_color black_color; -+ uint32_t addr = tg->regs[IDX_CRTC_BLACK_COLOR]; -+ uint32_t value = dal_read_reg(tg->ctx, addr); -+ -+ dce110_timing_generator_color_space_to_black_color( -+ color_space, -+ &black_color); -+ -+ set_reg_field_value( -+ value, -+ black_color.black_color_b_cb, -+ CRTC_BLACK_COLOR, -+ CRTC_BLACK_COLOR_B_CB); -+ set_reg_field_value( -+ value, -+ black_color.black_color_g_y, -+ CRTC_BLACK_COLOR, -+ CRTC_BLACK_COLOR_G_Y); -+ set_reg_field_value( -+ value, -+ black_color.black_color_r_cr, -+ CRTC_BLACK_COLOR, -+ CRTC_BLACK_COLOR_R_CR); -+ -+ dal_write_reg(tg->ctx, addr, value); -+} -+ -+/** -+ * blank_crtc -+ * Call ASIC Control Object to Blank CRTC. -+ */ -+ -+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg) -+{ -+ uint32_t addr = tg->regs[IDX_CRTC_BLANK_CONTROL]; -+ uint32_t value = dal_read_reg(tg->ctx, addr); -+ uint8_t counter = 100; -+ -+ set_reg_field_value( -+ value, -+ 1, -+ CRTC_BLANK_CONTROL, -+ CRTC_BLANK_DATA_EN); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ CRTC_BLANK_CONTROL, -+ CRTC_BLANK_DE_MODE); -+ -+ dal_write_reg(tg->ctx, addr, value); -+ -+ while (counter > 0) { -+ value = dal_read_reg(tg->ctx, addr); -+ -+ if (get_reg_field_value( -+ value, -+ CRTC_BLANK_CONTROL, -+ CRTC_BLANK_DATA_EN) == 1 && -+ get_reg_field_value( -+ value, -+ CRTC_BLANK_CONTROL, -+ CRTC_CURRENT_BLANK_STATE) == 1) -+ break; -+ -+ dc_service_sleep_in_milliseconds(tg->ctx, 1); -+ counter--; -+ } -+ -+ if (!counter) { -+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ "timing generator %d blank timing out.\n", -+ tg->controller_id); -+ return false; -+ } -+ -+ return true; -+} -+ -+/** -+ * unblank_crtc -+ * Call ASIC Control Object to UnBlank CRTC. -+ */ -+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg) -+{ -+ uint32_t addr = tg->regs[IDX_CRTC_BLANK_CONTROL]; -+ uint32_t value = dal_read_reg(tg->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ CRTC_BLANK_CONTROL, -+ CRTC_BLANK_DATA_EN); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ CRTC_BLANK_CONTROL, -+ CRTC_BLANK_DE_MODE); -+ -+ dal_write_reg(tg->ctx, addr, value); -+ -+ return true; -+} -+ -+/** -+ ***************************************************************************** -+ * 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 -+ * -+ ***************************************************************************** -+ */ -+bool dce110_timing_generator_is_in_vertical_blank(struct timing_generator *tg) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ addr = tg->regs[IDX_CRTC_STATUS]; -+ value = dal_read_reg(tg->ctx, addr); -+ field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK); -+ return field == 1; -+} -+ -+/** -+ ***************************************************************************** -+ * 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) -+{ -+ uint32_t addr = tg->regs[IDX_CRTC_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 = dal_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; -+ dal_write_reg(tg->ctx, addr, value); -+ -+ -+ addr = tg->regs[IDX_CRTC_STEREO_CONTROL]; -+ dal_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; -+ -+ result = dal_bios_parser_enable_crtc(tg->bp, tg->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; -+ -+ regval = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_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); -+ -+ dal_write_reg(tg->ctx, -+ tg->regs[IDX_CRTC_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, -+ struct dc_crtc_timing *dc_crtc_timing) -+{ -+ enum bp_result result; -+ struct bp_hw_crtc_timing_parameters bp_params; -+ uint32_t regval; -+ -+ 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; -+ -+ dc_service_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. -+ */ -+ dce110_timing_generator_apply_front_porch_workaround(tg, dc_crtc_timing); -+ -+ bp_params.controller_id = tg->controller_id; -+ -+ bp_params.h_total = dc_crtc_timing->h_total; -+ bp_params.h_addressable = -+ dc_crtc_timing->h_addressable; -+ bp_params.v_total = dc_crtc_timing->v_total; -+ bp_params.v_addressable = dc_crtc_timing->v_addressable; -+ -+ bp_params.h_sync_start = h_sync_start; -+ bp_params.h_sync_width = dc_crtc_timing->h_sync_width; -+ bp_params.v_sync_start = v_sync_start; -+ bp_params.v_sync_width = dc_crtc_timing->v_sync_width; -+ -+ /* Set overscan */ -+ bp_params.h_overscan_left = -+ dc_crtc_timing->h_border_left; -+ bp_params.h_overscan_right = -+ dc_crtc_timing->h_border_right; -+ bp_params.v_overscan_top = dc_crtc_timing->v_border_top; -+ bp_params.v_overscan_bottom = -+ dc_crtc_timing->v_border_bottom; -+ -+ /* Set flags */ -+ if (dc_crtc_timing->flags.HSYNC_POSITIVE_POLARITY == 1) -+ bp_params.flags.HSYNC_POSITIVE_POLARITY = 1; -+ -+ if (dc_crtc_timing->flags.VSYNC_POSITIVE_POLARITY == 1) -+ bp_params.flags.VSYNC_POSITIVE_POLARITY = 1; -+ -+ if (dc_crtc_timing->flags.INTERLACE == 1) -+ bp_params.flags.INTERLACE = 1; -+ -+ if (dc_crtc_timing->flags.HORZ_COUNT_BY_TWO == 1) -+ bp_params.flags.HORZ_COUNT_BY_TWO = 1; -+ -+ result = dal_bios_parser_program_crtc_timing(tg->bp, &bp_params); -+ -+ program_horz_count_by_2(tg, dc_crtc_timing); -+ -+ -+ regval = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_START_LINE_CONTROL]); -+ -+ if (dce110_timing_generator_get_vsynch_and_front_porch_size(dc_crtc_timing) <= 3) { -+ set_reg_field_value(regval, 3, -+ CRTC_START_LINE_CONTROL, -+ CRTC_ADVANCED_START_LINE_POSITION); -+ -+ set_reg_field_value(regval, 0, -+ CRTC_START_LINE_CONTROL, -+ CRTC_PREFETCH_EN); -+ } else { -+ set_reg_field_value(regval, 4, -+ CRTC_START_LINE_CONTROL, -+ CRTC_ADVANCED_START_LINE_POSITION); -+ -+ set_reg_field_value(regval, 1, -+ CRTC_START_LINE_CONTROL, -+ CRTC_PREFETCH_EN); -+ } -+ dal_write_reg(tg->ctx, -+ tg->regs[IDX_CRTC_START_LINE_CONTROL], regval); -+ -+ /* Enable stereo - only when we need to pack 3D frame. Other types -+ * of stereo handled in explicit call */ -+ -+ /* TODOSTEREO -+ if (hw_crtc_timing->flags.PACK_3D_FRAME) { -+ struct crtc_stereo_parameters stereo_params = { false }; -+ stereo_params.PROGRAM_STEREO = true; -+ stereo_params.PROGRAM_POLARITY = true; -+ stereo_params.FRAME_PACKED = true; -+ stereo_params.RIGHT_EYE_POLARITY = -+ hw_crtc_timing->flags.RIGHT_EYE_3D_POLARITY; -+ tg->funcs->enable_stereo(tg, &stereo_params); -+ }*/ -+ -+ return result == BP_RESULT_OK; -+} -+ -+/** -+ ***************************************************************************** -+ * Function: program_drr -+ * -+ * @brief -+ * Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*. -+ * -+ * @param [in] pHwCrtcTiming: point to H -+ * wCrtcTiming struct -+ ***************************************************************************** -+ */ -+void dce110_timing_generator_program_drr( -+ struct timing_generator *tg, -+ const struct hw_ranged_timing *timing) -+{ -+ /* register values */ -+ uint32_t v_total_min = 0; -+ uint32_t v_total_max = 0; -+ uint32_t v_total_cntl = 0; -+ uint32_t static_screen_cntl = 0; -+ -+ uint32_t addr = 0; -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_MIN]; -+ v_total_min = dal_read_reg(tg->ctx, addr); -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_MAX]; -+ v_total_max = dal_read_reg(tg->ctx, addr); -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_CONTROL]; -+ v_total_cntl = dal_read_reg(tg->ctx, addr); -+ -+ addr = tg->regs[IDX_CRTC_STATIC_SCREEN_CONTROL]; -+ static_screen_cntl = dal_read_reg(tg->ctx, addr); -+ -+ if (timing != NULL) { -+ /* Set Static Screen trigger events -+ * If CRTC_SET_V_TOTAL_MIN_MASK_EN is set, use legacy event mask -+ * register -+ */ -+ if (get_reg_field_value( -+ v_total_cntl, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_SET_V_TOTAL_MIN_MASK_EN)) { -+ set_reg_field_value(v_total_cntl, -+ /* TODO: add implementation -+ translate_to_dce_static_screen_events( -+ timing->control.event_mask.u_all), -+ */ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_SET_V_TOTAL_MIN_MASK); -+ } else { -+ set_reg_field_value(static_screen_cntl, -+ /* TODO: add implementation -+ translate_to_dce_static_screen_events( -+ timing->control.event_mask.u_all), -+ */ 0, -+ CRTC_STATIC_SCREEN_CONTROL, -+ CRTC_STATIC_SCREEN_EVENT_MASK); -+ } -+ -+ /* Number of consecutive static screen frames before interrupt -+ * is triggered. 0 is an invalid setting, which means we should -+ * leaving HW setting unchanged. */ -+ if (timing->control.static_frame_count != 0) { -+ set_reg_field_value( -+ static_screen_cntl, -+ timing->control.static_frame_count, -+ CRTC_STATIC_SCREEN_CONTROL, -+ CRTC_STATIC_SCREEN_FRAME_COUNT); -+ } -+ -+ /* This value is reduced by 1 based on the register definition -+ * of the VTOTAL value: -+ * CRTC_V_TOTAL should be set to Vertical total minus one. (E.g. -+ * for 525 lines, set to 524 = 0x20C) -+ */ -+ set_reg_field_value(v_total_min, -+ timing->vertical_total_min, -+ CRTC_V_TOTAL_MIN, -+ CRTC_V_TOTAL_MIN); -+ set_reg_field_value(v_total_max, -+ timing->vertical_total_max, -+ CRTC_V_TOTAL_MAX, -+ CRTC_V_TOTAL_MAX); -+ -+ /* set VTotalControl value according to ranged timing control. -+ */ -+ -+ if (timing->vertical_total_min != 0) { -+ set_reg_field_value(v_total_cntl, -+ 1, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MIN_SEL); -+ } else { -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MIN_SEL); -+ } -+ if (timing->vertical_total_max != 0) { -+ set_reg_field_value(v_total_cntl, -+ 1, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MAX_SEL); -+ } else { -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MAX_SEL); -+ } -+ set_reg_field_value(v_total_cntl, -+ timing->control.force_lock_on_event, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_FORCE_LOCK_ON_EVENT); -+ set_reg_field_value(v_total_cntl, -+ timing->control.lock_to_master_vsync, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_FORCE_LOCK_TO_MASTER_VSYNC); -+ } else { -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_SET_V_TOTAL_MIN_MASK); -+ set_reg_field_value(static_screen_cntl, -+ 0, -+ CRTC_STATIC_SCREEN_CONTROL, -+ CRTC_STATIC_SCREEN_EVENT_MASK); -+ set_reg_field_value(v_total_min, -+ 0, -+ CRTC_V_TOTAL_MIN, -+ CRTC_V_TOTAL_MIN); -+ set_reg_field_value(v_total_max, -+ 0, -+ CRTC_V_TOTAL_MAX, -+ CRTC_V_TOTAL_MAX); -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MIN_SEL); -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_V_TOTAL_MAX_SEL); -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_FORCE_LOCK_ON_EVENT); -+ set_reg_field_value(v_total_cntl, -+ 0, -+ CRTC_V_TOTAL_CONTROL, -+ CRTC_FORCE_LOCK_TO_MASTER_VSYNC); -+ } -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_MIN]; -+ dal_write_reg(tg->ctx, addr, v_total_min); -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_MAX]; -+ dal_write_reg(tg->ctx, addr, v_total_max); -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL_CONTROL]; -+ dal_write_reg(tg->ctx, addr, v_total_cntl); -+ -+ addr = tg->regs[IDX_CRTC_STATIC_SCREEN_CONTROL]; -+ dal_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) -+{ -+ uint32_t addr = tg->regs[IDX_CRTC_STATUS_FRAME_COUNT]; -+ uint32_t value = dal_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; -+ -+ value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_STATUS_POSITION]); -+ -+ *h_position = get_reg_field_value( -+ value, -+ CRTC_STATUS_POSITION, -+ CRTC_HORZ_COUNT); -+ -+ *v_position = get_reg_field_value( -+ value, -+ CRTC_STATUS_POSITION, -+ CRTC_VERT_COUNT); -+} -+ -+/** -+ ***************************************************************************** -+ * Function: get_crtc_scanoutpos -+ * -+ * @brief -+ * Returns CRTC vertical/horizontal counters -+ * -+ * @param [out] vpos, hpos -+ ***************************************************************************** -+ */ -+uint32_t dce110_timing_generator_get_crtc_scanoutpos( -+ struct timing_generator *tg, -+ int32_t *vbl, -+ int32_t *position) -+{ -+ /* 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 = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_V_BLANK_START_END]); -+ -+ *position = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_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 dc_context *ctx = tg->ctx; -+ uint32_t value = 0; -+ uint32_t addr = 0; -+ uint32_t tmp = 0; -+ -+ addr = tg->regs[IDX_CRTC_H_TOTAL]; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ timing->h_total - 1, -+ CRTC_H_TOTAL, -+ CRTC_H_TOTAL); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = tg->regs[IDX_CRTC_V_TOTAL]; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ timing->v_total - 1, -+ CRTC_V_TOTAL, -+ CRTC_V_TOTAL); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = tg->regs[IDX_CRTC_H_BLANK_START_END]; -+ value = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ addr = tg->regs[IDX_CRTC_V_BLANK_START_END]; -+ value = dal_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); -+ -+ dal_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; -+ -+ /* TODO: add support for other test patterns */ -+ switch (test_pattern) { -+ default: -+ value = 0; -+ addr = tg->regs[IDX_CRTC_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); -+ -+ dal_write_reg(ctx, addr, value); -+ -+ addr = tg->regs[IDX_CRTC_TEST_PATTERN_CONTROL]; -+ value = 0; -+ -+ set_reg_field_value( -+ value, -+ 1, -+ CRTC_TEST_PATTERN_CONTROL, -+ CRTC_TEST_PATTERN_EN); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ CRTC_TEST_PATTERN_CONTROL, -+ CRTC_TEST_PATTERN_MODE); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ CRTC_TEST_PATTERN_CONTROL, -+ CRTC_TEST_PATTERN_DYNAMIC_RANGE); -+ /* add color depth translation here */ -+ set_reg_field_value( -+ value, -+ 1, -+ CRTC_TEST_PATTERN_CONTROL, -+ CRTC_TEST_PATTERN_COLOR_FORMAT); -+ dal_write_reg(ctx, addr, value); -+ break; -+ } /* switch() */ -+} -+ -+/** -+* dce110_timing_generator_validate_timing -+* The timing generators support a maximum display size of is 8192 x 8192 pixels, -+* including both active display and blanking periods. Check H Total and V Total. -+*/ -+bool dce110_timing_generator_validate_timing( -+ struct timing_generator *tg, -+ const struct dc_crtc_timing *timing, -+ enum signal_type signal) -+{ -+ uint32_t h_blank; -+ uint32_t h_back_porch; -+ uint32_t hsync_offset = timing->h_border_right + -+ timing->h_front_porch; -+ uint32_t h_sync_start = timing->h_addressable + hsync_offset; -+ -+ 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 > tg->max_h_total || -+ timing->v_total > tg->max_v_total) -+ return false; -+ -+ h_blank = (timing->h_total - timing->h_addressable - -+ timing->h_border_right - -+ timing->h_border_left); -+ -+ if (h_blank < tg->min_h_blank) -+ return false; -+ -+ if (timing->h_front_porch < tg->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 < tg->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; -+ } -+ } -+} -+ -+void dce110_timing_generator_destroy(struct timing_generator **tg) -+{ -+ dc_service_free((*tg)->ctx, FROM_TIMING_GENERATOR(*tg)); -+ *tg = NULL; -+} -+ -+static bool timing_generator_dce110_construct(struct timing_generator *tg, -+ struct dc_context *ctx, -+ struct adapter_service *as, -+ enum controller_id id) -+{ -+ if (!as) -+ return false; -+ -+ switch (id) { -+ case CONTROLLER_ID_D0: -+ case CONTROLLER_ID_D1: -+ case CONTROLLER_ID_D2: -+ break; -+ default: -+ return false; -+ } -+ -+ if (!dce110_timing_generator_construct(tg, id)) -+ return false; -+ -+ tg->ctx = ctx; -+ tg->bp = dal_adapter_service_get_bios_parser(as); -+ tg->regs = tg_regs[id-1]; -+ -+ tg->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; -+ tg->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; -+ -+ tg->min_h_blank = 56; -+ tg->min_h_front_porch = 4; -+ tg->min_h_back_porch = 4; -+ -+ return true; -+} -+ -+struct timing_generator *dce110_timing_generator_create( -+ struct adapter_service *as, -+ struct dc_context *ctx, -+ enum controller_id id) -+{ -+ struct dce110_timing_generator *tg = -+ dc_service_alloc(ctx, sizeof(struct dce110_timing_generator)); -+ -+ if (!tg) -+ return NULL; -+ -+ if (timing_generator_dce110_construct(&tg->base, ctx, -+ as, id)) -+ return &tg->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, tg); -+ return NULL; -+} -+ -+/** -+ ***************************************************************************** -+ * 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; -+ uint32_t address = tg->regs[IDX_DCP_GSL_CONTROL]; -+ uint32_t check_point = FLIP_READY_BACK_LOOKUP; -+ -+ value = dal_read_reg(tg->ctx, address); -+ -+ /* This pipe will belong to GSL Group zero. */ -+ set_reg_field_value(value, -+ 1, -+ DCP_GSL_CONTROL, -+ DCP_GSL0_EN); -+ -+ set_reg_field_value(value, -+ gsl_params->timing_server, -+ DCP_GSL_CONTROL, -+ DCP_GSL_MASTER_EN); -+ -+ set_reg_field_value(value, -+ HFLIP_READY_DELAY, -+ DCP_GSL_CONTROL, -+ DCP_GSL_HSYNC_FLIP_FORCE_DELAY); -+ -+ /* Keep signal low (pending high) during 6 lines. -+ * Also defines minimum interval before re-checking signal. */ -+ set_reg_field_value(value, -+ HFLIP_CHECK_DELAY, -+ DCP_GSL_CONTROL, -+ DCP_GSL_HSYNC_FLIP_CHECK_DELAY); -+ -+ /* DCP_GSL_PURPOSE_SURFACE_FLIP */ -+ { -+ uint32_t value_crtc_vtotal; -+ -+ value_crtc_vtotal = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_V_TOTAL]); -+ -+ set_reg_field_value(value, -+ gsl_params->gsl_purpose, -+ DCP_GSL_CONTROL, -+ DCP_GSL_SYNC_SOURCE); -+ -+ /* Checkpoint relative to end of frame */ -+ check_point = get_reg_field_value(value_crtc_vtotal, -+ CRTC_V_TOTAL, -+ CRTC_V_TOTAL); -+ -+ dal_write_reg(tg->ctx, tg->regs[IDX_CRTC_GSL_WINDOW], 0); -+ } -+ -+ set_reg_field_value(value, -+ 1, -+ DCP_GSL_CONTROL, -+ DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); -+ -+ dal_write_reg(tg->ctx, address, value); -+ -+ /********************************************************************/ -+ address = tg->regs[IDX_CRTC_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); -+ -+ dal_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; -+ uint32_t address = tg->regs[IDX_DCP_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 = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_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); -+ -+ dal_write_reg(tg->ctx, address, value); -+ -+ /********************************************************************/ -+ address = tg->regs[IDX_CRTC_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); -+ -+ dal_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 addr = 0; -+ uint32_t value_1 = 0; -+ uint32_t field_1 = 0; -+ uint32_t value_2 = 0; -+ uint32_t field_2 = 0; -+ -+ addr = tg->regs[IDX_CRTC_STATUS_POSITION]; -+ value_1 = dal_read_reg(tg->ctx, addr); -+ value_2 = dal_read_reg(tg->ctx, addr); -+ -+ field_1 = get_reg_field_value( -+ value_1, CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); -+ field_2 = get_reg_field_value( -+ value_2, CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); -+ -+ if (field_1 == field_2) { -+ field_1 = get_reg_field_value( -+ value_1, CRTC_STATUS_POSITION, CRTC_VERT_COUNT); -+ field_2 = get_reg_field_value( -+ value_2, CRTC_STATUS_POSITION, CRTC_VERT_COUNT); -+ return field_1 != field_2; -+ } -+ -+ return true; -+} -+ -+/*TODO: Figure out if we need this function. */ -+void dce110_timing_generator_enable_advanced_request( -+ struct timing_generator *tg, -+ bool enable, -+ const struct dc_crtc_timing *timing) -+{ -+ uint32_t addr = tg->regs[IDX_CRTC_START_LINE_CONTROL]; -+ uint32_t value = dal_read_reg(tg->ctx, addr); -+ -+ if (enable && FROM_TIMING_GENERATOR(tg)->advanced_request_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 (dce110_timing_generator_get_vsynch_and_front_porch_size(timing) <= 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); -+ -+ dal_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; -+ uint32_t addr = tg->regs[IDX_CRTC_MASTER_UPDATE_LOCK]; -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ lock ? 1 : 0, -+ CRTC_MASTER_UPDATE_LOCK, -+ MASTER_UPDATE_LOCK); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+void dce110_timing_generator_enable_reset_trigger( -+ struct timing_generator *tg, -+ const struct trigger_params *trigger_params) -+{ -+ uint32_t value; -+ struct dc_context *dc_ctx = tg->ctx; -+ uint32_t rising_edge = 0; -+ uint32_t falling_edge = 0; -+ enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; -+ -+ /* Setup trigger edge */ -+ switch (trigger_params->edge) { -+ /* Default = based on current timing polarity */ -+ case TRIGGER_EDGE_DEFAULT: -+ { -+ uint32_t pol_value = dal_read_reg(tg->ctx, -+ tg->regs[IDX_CRTC_V_SYNC_A_CNTL]); -+ -+ /* Register spec has reversed definition: -+ * 0 for positive, 1 for negative */ -+ if (get_reg_field_value(pol_value, -+ CRTC_V_SYNC_A_CNTL, -+ CRTC_V_SYNC_A_POL) == 0) { -+ rising_edge = 1; -+ } else { -+ falling_edge = 1; -+ } -+ } -+ break; -+ case TRIGGER_EDGE_RISING: -+ rising_edge = 1; -+ break; -+ case TRIGGER_EDGE_FALLING: -+ falling_edge = 1; -+ break; -+ case TRIGGER_EDGE_BOTH: -+ rising_edge = 1; -+ falling_edge = 1; -+ break; -+ default: -+ DC_ERROR("Invalid Trigger Edge!\n"); -+ return; -+ } -+ -+ value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_TRIGB_CNTL]); -+ -+ switch(trigger_params->source) { -+ /* Currently supporting only a single group, the group zero. */ -+ case SYNC_SOURCE_GSL_GROUP0: -+ trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; -+ break; -+ default: -+ DC_ERROR("Unsupported GSL Group!\n"); -+ return; -+ } -+ -+ set_reg_field_value(value, -+ trig_src_select, -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_SOURCE_SELECT); -+ -+ set_reg_field_value(value, -+ TRIGGER_POLARITY_SELECT_LOGIC_ZERO, -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_POLARITY_SELECT); -+ -+ set_reg_field_value(value, -+ rising_edge, -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); -+ -+ set_reg_field_value(value, -+ falling_edge, -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); -+ -+ set_reg_field_value(value, -+ 0, /* send every signal */ -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_FREQUENCY_SELECT); -+ -+ set_reg_field_value(value, -+ 0, /* no delay */ -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_DELAY); -+ -+ set_reg_field_value(value, -+ 1, /* clear trigger status */ -+ CRTC_TRIGB_CNTL, -+ CRTC_TRIGB_CLEAR); -+ -+ dal_write_reg(tg->ctx, tg->regs[IDX_CRTC_TRIGB_CNTL], value); -+ -+ /**************************************************************/ -+ -+ value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_FORCE_COUNT_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); -+ -+ dal_write_reg(tg->ctx, tg->regs[IDX_CRTC_FORCE_COUNT_CNTL], value); -+} -+ -+void dce110_timing_generator_disable_reset_trigger( -+ struct timing_generator *tg) -+{ -+ uint32_t value; -+ -+ value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_FORCE_COUNT_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); -+ -+ dal_write_reg(tg->ctx, tg->regs[IDX_CRTC_FORCE_COUNT_CNTL], value); -+ -+ /********************************************************************/ -+ value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_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); -+ -+ dal_write_reg(tg->ctx, tg->regs[IDX_CRTC_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) -+{ -+ uint32_t value = dal_read_reg(tg->ctx, tg->regs[IDX_CRTC_FORCE_COUNT_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; -+ -+ switch (tg->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; -+ default: -+ break; -+ } -+ value = dal_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); -+ -+ dal_write_reg(tg->ctx, addr, value); -+} -+ -+ -+/** -+* set_overscan_color_black -+* -+* @param :black_color is one of the color space -+* :this routine will set overscan black color according to the color space. -+* @return none -+*/ -+ -+void dce110_timing_generator_set_overscan_color_black( -+ struct timing_generator *tg, -+ enum color_space black_color) -+{ -+ struct dc_context *ctx = tg->ctx; -+ uint32_t value = 0; -+ uint32_t addr; -+ -+ /* Overscan Color for YUV display modes: -+ * to achieve a black color for both the explicit and implicit overscan, -+ * the overscan color registers should be programmed to: */ -+ -+ switch (black_color) { -+ case COLOR_SPACE_YPBPR601: -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_BLUE); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_GREEN); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_RED); -+ break; -+ -+ case COLOR_SPACE_YPBPR709: -+ case COLOR_SPACE_YCBCR601: -+ case COLOR_SPACE_YCBCR709: -+ case COLOR_SPACE_YCBCR601_YONLY: -+ case COLOR_SPACE_YCBCR709_YONLY: -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_BLUE); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_GREEN); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_RED); -+ break; -+ -+ case COLOR_SPACE_N_MVPU_SUPER_AA: -+ /* In crossfire SuperAA mode, the slave overscan data is forced -+ * to 0 in the pixel mixer on the master. As a result, we need -+ * to adjust the blank color so that after blending the -+ * master+slave, it will appear black */ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_BLUE); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_GREEN); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_RED); -+ break; -+ -+ case COLOR_SPACE_SRGB_LIMITED_RANGE: -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_BLUE); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_GREEN); -+ -+ set_reg_field_value( -+ value, -+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE, -+ CRTC_OVERSCAN_COLOR, -+ CRTC_OVERSCAN_COLOR_RED); -+ break; -+ -+ default: -+ /* default is sRGB black 0. */ -+ break; -+ } -+ addr = tg->regs[IDX_CRTC_OVERSCAN_COLOR]; -+ dal_write_reg(ctx, addr, value); -+ addr = tg->regs[IDX_CRTC_BLACK_COLOR]; -+ dal_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 = tg->regs[IDX_CRTC_BLANK_DATA_COLOR]; -+ dal_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 -+ */ -+ -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h -new file mode 100644 -index 0000000..d95a2a0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.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_TIMING_GENERATOR_DCE110_H__ -+#define __DC_TIMING_GENERATOR_DCE110_H__ -+ -+ -+#include "../include/timing_generator_types.h" -+#include "../include/grph_object_id.h" -+ -+/* overscan in blank for YUV color space. For RGB, it is zero for black. */ -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV 0x1f4 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV 0x40 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV 0x1f4 -+ -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV 0x200 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV 0x40 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV 0x200 -+ -+/* overscan in blank for YUV color space when in SuperAA crossfire mode */ -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA 0x1a2 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA 0x20 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA 0x1a2 -+ -+/* OVERSCAN COLOR FOR RGB LIMITED RANGE -+ * (16~253) 16*4 (Multiple over 256 code leve) =64 (0x40) */ -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE 0x40 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE 0x40 -+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE 0X40 -+ -+struct dce110_timing_generator { -+ struct timing_generator base; -+ enum sync_source cached_gsl_group; -+ bool advanced_request_enable; -+}; -+ -+struct timing_generator *dce110_timing_generator_create( -+ struct adapter_service *as, -+ struct dc_context *ctx, -+ enum controller_id id); -+ -+void dce110_timing_generator_destroy(struct timing_generator **tg); -+ -+bool dce110_timing_generator_construct( -+ struct timing_generator *tg, -+ enum controller_id id); -+ -+void dce110_timing_generator_program_blank_color( -+ struct timing_generator *tg, -+ enum color_space color_space); -+ -+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg); -+ -+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg); -+ -+bool dce110_timing_generator_disable_crtc(struct timing_generator *tg); -+ -+bool dce110_timing_generator_is_in_vertical_blank(struct timing_generator *tg); -+ -+void dce110_timing_generator_program_blanking( -+ struct timing_generator *tg, -+ const struct dc_crtc_timing *timing); -+ -+bool dce110_timing_generator_program_timing_generator( -+ struct timing_generator *tg, -+ struct dc_crtc_timing *dc_crtc_timing); -+ -+void dce110_timing_generator_set_early_control( -+ struct timing_generator *tg, -+ uint32_t early_cntl); -+ -+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg); -+ -+bool dce110_timing_generator_validate_timing( -+ struct timing_generator *tg, -+ const struct dc_crtc_timing *timing, -+ enum signal_type signal); -+ -+void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg); -+ -+void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg); -+ -+void dce110_timing_generator_set_test_pattern( -+ struct timing_generator *tg, -+ /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' -+ * because this is not DP-specific (which is probably somewhere in DP -+ * encoder) */ -+ enum controller_dp_test_pattern test_pattern, -+ enum dc_color_depth color_depth); -+ -+void dce110_timing_generator_program_drr( -+ struct timing_generator *tg, -+ const struct hw_ranged_timing *timing); -+ -+uint32_t dce110_timing_generator_get_crtc_scanoutpos( -+ struct timing_generator *tg, -+ int32_t *vbl, -+ int32_t *position); -+ -+uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg); -+ -+void dce110_timing_generator_color_space_to_black_color( -+ enum color_space colorspace, -+ struct crtc_black_color *black_color); -+void dce110_timing_generator_apply_front_porch_workaround( -+ struct timing_generator *tg, -+ struct dc_crtc_timing *timing); -+int32_t dce110_timing_generator_get_vsynch_and_front_porch_size( -+ const struct dc_crtc_timing *timing); -+ -+void dce110_timing_generator_get_crtc_positions( -+ struct timing_generator *tg, -+ int32_t *h_position, -+ int32_t *v_position); -+ -+ -+/* TODO: Figure out if we need these functions*/ -+bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg); -+ -+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_timing_generator_set_overscan_color_black( -+ struct timing_generator *tg, -+ enum color_space black_color); -+ -+ -+/**** Sync-related interfaces ****/ -+void dce110_timing_generator_setup_global_swap_lock( -+ struct timing_generator *tg, -+ const struct dcp_gsl_params *gsl_params); -+void dce110_timing_generator_tear_down_global_swap_lock( -+ struct timing_generator *tg); -+ -+ -+void dce110_timing_generator_enable_reset_trigger( -+ struct timing_generator *tg, -+ const struct trigger_params *trigger_params); -+ -+void dce110_timing_generator_disable_reset_trigger( -+ struct timing_generator *tg); -+ -+bool dce110_timing_generator_did_triggered_reset_occur( -+ struct timing_generator *tg); -+ -+void dce110_timing_generator_disable_vga( -+ struct timing_generator *tg); -+ -+/**** End-of-Sync-related interfaces ****/ -+ -+#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c -new file mode 100644 -index 0000000..f3b3630 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.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 "dal_services.h" -+ -+/* include DCE11 register header files */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "dc_types.h" -+#include "core_types.h" -+ -+#include "include/grph_object_id.h" -+#include "include/fixed31_32.h" -+#include "include/logger_interface.h" -+ -+#include "dce110_transform.h" -+#include "dce110_transform_bit_depth.h" -+ -+static const struct dce110_transform_reg_offsets reg_offsets[] = { -+{ -+ .scl_offset = (mmSCL0_SCL_CONTROL - mmSCL0_SCL_CONTROL), -+ .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB0_LB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL1_SCL_CONTROL - mmSCL0_SCL_CONTROL), -+ .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB0_LB_DATA_FORMAT), -+}, -+{ .scl_offset = (mmSCL2_SCL_CONTROL - mmSCL0_SCL_CONTROL), -+ .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), -+ .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -+ .lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB0_LB_DATA_FORMAT), -+} -+}; -+ -+/*****************************************/ -+/* Constructor, Destructor */ -+/*****************************************/ -+ -+bool dce110_transform_construct( -+ struct dce110_transform *xfm110, -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ if ((inst < 1) || (inst > ARRAY_SIZE(reg_offsets))) -+ return false; -+ -+ xfm110->base.ctx = ctx; -+ -+ xfm110->base.inst = inst; -+ -+ xfm110->offsets = reg_offsets[inst - 1]; -+ -+ xfm110->lb_pixel_depth_supported = -+ LB_PIXEL_DEPTH_18BPP | -+ LB_PIXEL_DEPTH_24BPP | -+ LB_PIXEL_DEPTH_30BPP; -+ -+ return true; -+} -+ -+void dce110_transform_destroy(struct transform **xfm) -+{ -+ dc_service_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm)); -+ *xfm = NULL; -+} -+ -+struct transform *dce110_transform_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct dce110_transform *transform = -+ dc_service_alloc(ctx, sizeof(struct dce110_transform)); -+ -+ if (!transform) -+ return NULL; -+ -+ if (dce110_transform_construct(transform, -+ ctx, inst)) -+ return &transform->base; -+ -+ BREAK_TO_DEBUGGER(); -+ dc_service_free(ctx, transform); -+ return NULL; -+} -+ -+bool dce110_transform_power_up(struct transform *xfm) -+{ -+ return dce110_transform_power_up_line_buffer(xfm); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h -new file mode 100644 -index 0000000..edf016c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h -@@ -0,0 +1,91 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_TRANSFORM_DCE110_H__ -+#define __DAL_TRANSFORM_DCE110_H__ -+ -+#include "inc/transform.h" -+#include "include/grph_csc_types.h" -+ -+#define TO_DCE110_TRANSFORM(transform)\ -+ container_of(transform, struct dce110_transform, base) -+ -+struct dce110_transform_reg_offsets { -+ uint32_t scl_offset; -+ uint32_t dcfe_offset; -+ uint32_t dcp_offset; -+ uint32_t lb_offset; -+}; -+ -+struct dce110_transform { -+ struct transform base; -+ struct dce110_transform_reg_offsets offsets; -+ -+ uint32_t lb_pixel_depth_supported; -+}; -+ -+bool dce110_transform_construct(struct dce110_transform *xfm110, -+ struct dc_context *ctx, -+ uint32_t inst); -+ -+void dce110_transform_destroy(struct transform **xfm); -+ -+struct transform *dce110_transform_create( -+ struct dc_context *ctx, -+ uint32_t inst); -+ -+bool dce110_transform_power_up(struct transform *xfm); -+ -+/* SCALER RELATED */ -+bool dce110_transform_set_scaler( -+ struct transform *xfm, -+ const struct scaler_data *data); -+ -+void dce110_transform_set_scaler_bypass(struct transform *xfm); -+ -+bool dce110_transform_update_viewport( -+ struct transform *xfm, -+ const struct rect *view_port, -+ bool is_fbc_attached); -+ -+void dce110_transform_set_scaler_filter( -+ struct transform *xfm, -+ struct scaler_filter *filter); -+ -+/* GAMUT RELATED */ -+void dce110_transform_set_gamut_remap( -+ struct transform *xfm, -+ const struct grph_csc_adjustment *adjust); -+ -+/* BIT DEPTH RELATED */ -+bool dce110_transform_set_pixel_storage_depth( -+ struct transform *xfm, -+ enum lb_pixel_depth depth); -+ -+bool dce110_transform_get_current_pixel_storage_depth( -+ struct transform *xfm, -+ enum lb_pixel_depth *depth); -+ -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c -new file mode 100644 -index 0000000..747f2c7 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c -@@ -0,0 +1,840 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* include DCE11 register header files */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "dce110_transform.h" -+ -+#include "include/logger_interface.h" -+#include "include/fixed32_32.h" -+ -+#define DCP_REG(reg)\ -+ (reg + xfm110->offsets.dcp_offset) -+ -+#define LB_REG(reg)\ -+ (reg + xfm110->offsets.lb_offset) -+ -+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712 -+#define LB_BITS_PER_ENTRY 144 -+ -+enum dcp_out_trunc_round_mode { -+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, -+ DCP_OUT_TRUNC_ROUND_MODE_ROUND -+}; -+ -+enum dcp_out_trunc_round_depth { -+ DCP_OUT_TRUNC_ROUND_DEPTH_14BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_13BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_12BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_11BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_10BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_9BIT, -+ DCP_OUT_TRUNC_ROUND_DEPTH_8BIT -+}; -+ -+/* defines the various methods of bit reduction available for use */ -+enum dcp_bit_depth_reduction_mode { -+ DCP_BIT_DEPTH_REDUCTION_MODE_DITHER, -+ DCP_BIT_DEPTH_REDUCTION_MODE_ROUND, -+ DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE, -+ DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED, -+ DCP_BIT_DEPTH_REDUCTION_MODE_INVALID -+}; -+ -+enum dcp_spatial_dither_mode { -+ DCP_SPATIAL_DITHER_MODE_AAAA, -+ DCP_SPATIAL_DITHER_MODE_A_AA_A, -+ DCP_SPATIAL_DITHER_MODE_AABBAABB, -+ DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC, -+ DCP_SPATIAL_DITHER_MODE_INVALID -+}; -+ -+enum dcp_spatial_dither_depth { -+ DCP_SPATIAL_DITHER_DEPTH_30BPP, -+ DCP_SPATIAL_DITHER_DEPTH_24BPP -+}; -+ -+static bool set_clamp( -+ struct dce110_transform *xfm110, -+ enum dc_color_depth depth); -+ -+static bool set_round( -+ struct dce110_transform *xfm110, -+ enum dcp_out_trunc_round_mode mode, -+ enum dcp_out_trunc_round_depth depth); -+ -+static bool set_dither( -+ struct dce110_transform *xfm110, -+ bool dither_enable, -+ enum dcp_spatial_dither_mode dither_mode, -+ enum dcp_spatial_dither_depth dither_depth, -+ bool frame_random_enable, -+ bool rgb_random_enable, -+ bool highpass_random_enable); -+ -+/** -+ ******************************************************************************* -+ * dce110_transform_bit_depth_reduction_program -+ * -+ * @brief -+ * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, -+ * Dither) for dce110 -+ * -+ * @param depth : bit depth to set the clamp to (should match denorm) -+ * -+ * @return -+ * true if succeeds. -+ ******************************************************************************* -+ */ -+static bool program_bit_depth_reduction( -+ struct dce110_transform *xfm110, -+ enum dc_color_depth depth) -+{ -+ enum dcp_bit_depth_reduction_mode depth_reduction_mode; -+ enum dcp_spatial_dither_mode spatial_dither_mode; -+ bool frame_random_enable; -+ bool rgb_random_enable; -+ bool highpass_random_enable; -+ -+ if (depth > COLOR_DEPTH_121212) { -+ ASSERT_CRITICAL(false); /* Invalid clamp bit depth */ -+ return false; -+ } -+ -+ depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER; -+ -+ spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A; -+ -+ frame_random_enable = true; -+ rgb_random_enable = true; -+ highpass_random_enable = true; -+ -+ if (!set_clamp(xfm110, depth)) { -+ /* Failure in set_clamp() */ -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ switch (depth_reduction_mode) { -+ case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER: -+ /* Spatial Dither: Set round/truncate to bypass (12bit), -+ * enable Dither (30bpp) */ -+ set_round(xfm110, -+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, -+ DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); -+ -+ set_dither(xfm110, true, spatial_dither_mode, -+ DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, -+ rgb_random_enable, highpass_random_enable); -+ break; -+ case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND: -+ /* Round: Enable round (10bit), disable Dither */ -+ set_round(xfm110, -+ DCP_OUT_TRUNC_ROUND_MODE_ROUND, -+ DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); -+ -+ set_dither(xfm110, false, spatial_dither_mode, -+ DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, -+ rgb_random_enable, highpass_random_enable); -+ break; -+ case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /* Truncate */ -+ /* Truncate: Enable truncate (10bit), disable Dither */ -+ set_round(xfm110, -+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, -+ DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); -+ -+ set_dither(xfm110, false, spatial_dither_mode, -+ DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, -+ rgb_random_enable, highpass_random_enable); -+ break; -+ -+ case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /* Disabled */ -+ /* Truncate: Set round/truncate to bypass (12bit), -+ * disable Dither */ -+ set_round(xfm110, -+ DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, -+ DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); -+ -+ set_dither(xfm110, false, spatial_dither_mode, -+ DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, -+ rgb_random_enable, highpass_random_enable); -+ break; -+ default: -+ /* Invalid DCP Depth reduction mode */ -+ ASSERT_CRITICAL(false); -+ break; -+ } -+ -+ return true; -+} -+ -+/** -+ ******************************************************************************* -+ * set_clamp -+ * -+ * @param depth : bit depth to set the clamp to (should match denorm) -+ * -+ * @brief -+ * Programs clamp according to panel bit depth. -+ * -+ * @return -+ * true if succeeds -+ * -+ ******************************************************************************* -+ */ -+static bool set_clamp( -+ struct dce110_transform *xfm110, -+ enum dc_color_depth depth) -+{ -+ uint32_t clamp_max = 0; -+ -+ /* At the clamp block the data will be MSB aligned, so we set the max -+ * clamp accordingly. -+ * For example, the max value for 6 bits MSB aligned (14 bit bus) would -+ * be "11 1111 0000 0000" in binary, so 0x3F00. -+ */ -+ switch (depth) { -+ case COLOR_DEPTH_666: -+ /* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */ -+ clamp_max = 0x3F00; -+ break; -+ case COLOR_DEPTH_888: -+ /* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */ -+ clamp_max = 0x3FC0; -+ break; -+ case COLOR_DEPTH_101010: -+ /* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ -+ clamp_max = 0x3FFC; -+ break; -+ case COLOR_DEPTH_121212: -+ /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */ -+ clamp_max = 0x3FFF; -+ break; -+ default: -+ ASSERT_CRITICAL(false); /* Invalid clamp bit depth */ -+ return false; -+ } -+ -+ { -+ uint32_t value = 0; -+ /* always set min to 0 */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUT_CLAMP_CONTROL_B_CB, -+ OUT_CLAMP_MIN_B_CB); -+ -+ set_reg_field_value( -+ value, -+ clamp_max, -+ OUT_CLAMP_CONTROL_B_CB, -+ OUT_CLAMP_MAX_B_CB); -+ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmOUT_CLAMP_CONTROL_B_CB), -+ value); -+ } -+ -+ { -+ uint32_t value = 0; -+ /* always set min to 0 */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUT_CLAMP_CONTROL_G_Y, -+ OUT_CLAMP_MIN_G_Y); -+ -+ set_reg_field_value( -+ value, -+ clamp_max, -+ OUT_CLAMP_CONTROL_G_Y, -+ OUT_CLAMP_MAX_G_Y); -+ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmOUT_CLAMP_CONTROL_G_Y), -+ value); -+ } -+ -+ { -+ uint32_t value = 0; -+ /* always set min to 0 */ -+ set_reg_field_value( -+ value, -+ 0, -+ OUT_CLAMP_CONTROL_R_CR, -+ OUT_CLAMP_MIN_R_CR); -+ -+ set_reg_field_value( -+ value, -+ clamp_max, -+ OUT_CLAMP_CONTROL_R_CR, -+ OUT_CLAMP_MAX_R_CR); -+ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmOUT_CLAMP_CONTROL_R_CR), -+ value); -+ } -+ -+ return true; -+} -+ -+/** -+ ******************************************************************************* -+ * set_round -+ * -+ * @brief -+ * Programs Round/Truncate -+ * -+ * @param [in] mode :round or truncate -+ * @param [in] depth :bit depth to round/truncate to -+ OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode -+ POSSIBLE VALUES: -+ 00 - truncate to u0.12 -+ 01 - truncate to u0.11 -+ 02 - truncate to u0.10 -+ 03 - truncate to u0.9 -+ 04 - truncate to u0.8 -+ 05 - reserved -+ 06 - truncate to u0.14 -+ 07 - truncate to u0.13 set_reg_field_value( -+ value, -+ clamp_max, -+ OUT_CLAMP_CONTROL_R_CR, -+ OUT_CLAMP_MAX_R_CR); -+ 08 - round to u0.12 -+ 09 - round to u0.11 -+ 10 - round to u0.10 -+ 11 - round to u0.9 -+ 12 - round to u0.8 -+ 13 - reserved -+ 14 - round to u0.14 -+ 15 - round to u0.13 -+ -+ * @return -+ * true if succeeds. -+ ******************************************************************************* -+ */ -+static bool set_round( -+ struct dce110_transform *xfm110, -+ enum dcp_out_trunc_round_mode mode, -+ enum dcp_out_trunc_round_depth depth) -+{ -+ uint32_t depth_bits = 0; -+ uint32_t mode_bit = 0; -+ /* zero out all bits */ -+ uint32_t value = 0; -+ -+ /* set up bit depth */ -+ switch (depth) { -+ case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT: -+ depth_bits = 6; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT: -+ depth_bits = 7; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT: -+ depth_bits = 0; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT: -+ depth_bits = 1; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT: -+ depth_bits = 2; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT: -+ depth_bits = 3; -+ break; -+ case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT: -+ depth_bits = 4; -+ break; -+ default: -+ /* Invalid dcp_out_trunc_round_depth */ -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ set_reg_field_value( -+ value, -+ depth_bits, -+ OUT_ROUND_CONTROL, -+ OUT_ROUND_TRUNC_MODE); -+ -+ /* set up round or truncate */ -+ switch (mode) { -+ case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE: -+ mode_bit = 0; -+ break; -+ case DCP_OUT_TRUNC_ROUND_MODE_ROUND: -+ mode_bit = 1; -+ break; -+ default: -+ /* Invalid dcp_out_trunc_round_mode */ -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ depth_bits |= mode_bit << 3; -+ -+ set_reg_field_value( -+ value, -+ depth_bits, -+ OUT_ROUND_CONTROL, -+ OUT_ROUND_TRUNC_MODE); -+ -+ /* write the register */ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmOUT_ROUND_CONTROL), -+ value); -+ -+ return true; -+} -+ -+/** -+ ******************************************************************************* -+ * set_dither -+ * -+ * @brief -+ * Programs Dither -+ * -+ * @param [in] dither_enable : enable dither -+ * @param [in] dither_mode : dither mode to set -+ * @param [in] dither_depth : bit depth to dither to -+ * @param [in] frame_random_enable : enable frame random -+ * @param [in] rgb_random_enable : enable rgb random -+ * @param [in] highpass_random_enable : enable highpass random -+ * -+ * @return -+ * true if succeeds. -+ ******************************************************************************* -+ */ -+ -+static bool set_dither( -+ struct dce110_transform *xfm110, -+ bool dither_enable, -+ enum dcp_spatial_dither_mode dither_mode, -+ enum dcp_spatial_dither_depth dither_depth, -+ bool frame_random_enable, -+ bool rgb_random_enable, -+ bool highpass_random_enable) -+{ -+ uint32_t dither_depth_bits = 0; -+ uint32_t dither_mode_bits = 0; -+ /* zero out all bits */ -+ uint32_t value = 0; -+ -+ /* set up the fields */ -+ if (dither_enable) -+ set_reg_field_value( -+ value, -+ 1, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_SPATIAL_DITHER_EN); -+ -+ switch (dither_mode) { -+ case DCP_SPATIAL_DITHER_MODE_AAAA: -+ dither_mode_bits = 0; -+ break; -+ case DCP_SPATIAL_DITHER_MODE_A_AA_A: -+ dither_mode_bits = 1; -+ break; -+ case DCP_SPATIAL_DITHER_MODE_AABBAABB: -+ dither_mode_bits = 2; -+ break; -+ case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC: -+ dither_mode_bits = 3; -+ break; -+ default: -+ /* Invalid dcp_spatial_dither_mode */ -+ ASSERT_CRITICAL(false); -+ return false; -+ -+ } -+ set_reg_field_value( -+ value, -+ dither_mode_bits, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_SPATIAL_DITHER_MODE); -+ -+ switch (dither_depth) { -+ case DCP_SPATIAL_DITHER_DEPTH_30BPP: -+ dither_depth_bits = 0; -+ break; -+ case DCP_SPATIAL_DITHER_DEPTH_24BPP: -+ dither_depth_bits = 1; -+ break; -+ default: -+ /* Invalid dcp_spatial_dither_depth */ -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ set_reg_field_value( -+ value, -+ dither_depth_bits, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_SPATIAL_DITHER_DEPTH); -+ -+ if (frame_random_enable) -+ set_reg_field_value( -+ value, -+ 1, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_FRAME_RANDOM_ENABLE); -+ -+ if (rgb_random_enable) -+ set_reg_field_value( -+ value, -+ 1, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_RGB_RANDOM_ENABLE); -+ -+ if (highpass_random_enable) -+ set_reg_field_value( -+ value, -+ 1, -+ DCP_SPATIAL_DITHER_CNTL, -+ DCP_HIGHPASS_RANDOM_ENABLE); -+ -+ /* write the register */ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmDCP_SPATIAL_DITHER_CNTL), -+ value); -+ -+ return true; -+} -+ -+bool dce110_transform_get_max_num_of_supported_lines( -+ struct dce110_transform *xfm110, -+ enum lb_pixel_depth depth, -+ uint32_t pixel_width, -+ uint32_t *lines) -+{ -+ uint32_t pixels_per_entries = 0; -+ uint32_t max_pixels_supports = 0; -+ -+ if (pixel_width == 0) -+ return false; -+ -+ /* Find number of pixels that can fit into a single LB entry and -+ * take floor of the value since we cannot store a single pixel -+ * across multiple entries. */ -+ switch (depth) { -+ case LB_PIXEL_DEPTH_18BPP: -+ pixels_per_entries = LB_BITS_PER_ENTRY / 18; -+ break; -+ -+ case LB_PIXEL_DEPTH_24BPP: -+ pixels_per_entries = LB_BITS_PER_ENTRY / 24; -+ break; -+ -+ case LB_PIXEL_DEPTH_30BPP: -+ pixels_per_entries = LB_BITS_PER_ENTRY / 30; -+ break; -+ -+ case LB_PIXEL_DEPTH_36BPP: -+ pixels_per_entries = LB_BITS_PER_ENTRY / 36; -+ break; -+ -+ default: -+ dal_logger_write(xfm110->base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid LB pixel depth", -+ __func__); -+ break; -+ } -+ -+ if (pixels_per_entries == 0) -+ return false; -+ -+ max_pixels_supports = pixels_per_entries * LB_TOTAL_NUMBER_OF_ENTRIES; -+ -+ *lines = max_pixels_supports / pixel_width; -+ return true; -+} -+ -+void dce110_transform_enable_alpha( -+ struct dce110_transform *xfm110, -+ bool enable) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t value; -+ uint32_t addr = LB_REG(mmLB_DATA_FORMAT); -+ -+ value = dal_read_reg(ctx, addr); -+ -+ if (enable == 1) -+ set_reg_field_value( -+ value, -+ 1, -+ LB_DATA_FORMAT, -+ ALPHA_EN); -+ else -+ set_reg_field_value( -+ value, -+ 0, -+ LB_DATA_FORMAT, -+ ALPHA_EN); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static enum lb_pixel_depth translate_display_bpp_to_lb_depth( -+ uint32_t display_bpp) -+{ -+ switch (display_bpp) { -+ case 18: -+ return LB_PIXEL_DEPTH_18BPP; -+ case 24: -+ return LB_PIXEL_DEPTH_24BPP; -+ case 36: -+ case 42: -+ case 48: -+ return LB_PIXEL_DEPTH_36BPP; -+ case 30: -+ default: -+ return LB_PIXEL_DEPTH_30BPP; -+ } -+} -+ -+bool dce110_transform_get_next_lower_pixel_storage_depth( -+ struct dce110_transform *xfm110, -+ uint32_t display_bpp, -+ enum lb_pixel_depth depth, -+ enum lb_pixel_depth *lower_depth) -+{ -+ enum lb_pixel_depth depth_req_by_display = -+ translate_display_bpp_to_lb_depth(display_bpp); -+ uint32_t current_required_depth = depth_req_by_display; -+ uint32_t current_depth = depth; -+ -+ /* if required display depth < current we could go down, for example -+ * from LB_PIXEL_DEPTH_30BPP to LB_PIXEL_DEPTH_24BPP -+ */ -+ if (current_required_depth < current_depth) { -+ current_depth = current_depth >> 1; -+ if (xfm110->lb_pixel_depth_supported & current_depth) { -+ *lower_depth = current_depth; -+ return true; -+ } -+ } -+ return false; -+} -+ -+bool dce110_transform_is_prefetch_enabled( -+ struct dce110_transform *xfm110) -+{ -+ uint32_t value = dal_read_reg( -+ xfm110->base.ctx, LB_REG(mmLB_DATA_FORMAT)); -+ -+ if (get_reg_field_value(value, LB_DATA_FORMAT, PREFETCH) == 1) -+ return true; -+ -+ return false; -+} -+ -+bool dce110_transform_get_current_pixel_storage_depth( -+ struct transform *xfm, -+ enum lb_pixel_depth *depth) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ uint32_t value = 0; -+ -+ if (depth == NULL) -+ return false; -+ -+ value = dal_read_reg( -+ xfm->ctx, -+ LB_REG(mmLB_DATA_FORMAT)); -+ -+ switch (get_reg_field_value(value, LB_DATA_FORMAT, PIXEL_DEPTH)) { -+ case 0: -+ *depth = LB_PIXEL_DEPTH_30BPP; -+ break; -+ case 1: -+ *depth = LB_PIXEL_DEPTH_24BPP; -+ break; -+ case 2: -+ *depth = LB_PIXEL_DEPTH_18BPP; -+ break; -+ case 3: -+ *depth = LB_PIXEL_DEPTH_36BPP; -+ break; -+ default: -+ dal_logger_write(xfm->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid LB pixel depth", -+ __func__); -+ *depth = LB_PIXEL_DEPTH_30BPP; -+ break; -+ } -+ return true; -+ -+} -+ -+static void set_denormalization( -+ struct dce110_transform *xfm110, -+ enum dc_color_depth depth) -+{ -+ uint32_t value = dal_read_reg(xfm110->base.ctx, -+ DCP_REG(mmDENORM_CONTROL)); -+ -+ switch (depth) { -+ case COLOR_DEPTH_666: -+ /* 63/64 for 6 bit output color depth */ -+ set_reg_field_value( -+ value, -+ 1, -+ DENORM_CONTROL, -+ DENORM_MODE); -+ break; -+ case COLOR_DEPTH_888: -+ /* Unity for 8 bit output color depth -+ * because prescale is disabled by default */ -+ set_reg_field_value( -+ value, -+ 0, -+ DENORM_CONTROL, -+ DENORM_MODE); -+ break; -+ case COLOR_DEPTH_101010: -+ /* 1023/1024 for 10 bit output color depth */ -+ set_reg_field_value( -+ value, -+ 3, -+ DENORM_CONTROL, -+ DENORM_MODE); -+ break; -+ case COLOR_DEPTH_121212: -+ /* 4095/4096 for 12 bit output color depth */ -+ set_reg_field_value( -+ value, -+ 5, -+ DENORM_CONTROL, -+ DENORM_MODE); -+ break; -+ case COLOR_DEPTH_141414: -+ case COLOR_DEPTH_161616: -+ default: -+ /* not valid used case! */ -+ break; -+ } -+ -+ dal_write_reg(xfm110->base.ctx, -+ DCP_REG(mmDENORM_CONTROL), -+ value); -+ -+} -+ -+bool dce110_transform_set_pixel_storage_depth( -+ struct transform *xfm, -+ enum lb_pixel_depth depth) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ bool ret = true; -+ uint32_t value; -+ enum dc_color_depth color_depth; -+ -+ value = dal_read_reg( -+ xfm->ctx, -+ LB_REG(mmLB_DATA_FORMAT)); -+ switch (depth) { -+ case LB_PIXEL_DEPTH_18BPP: -+ color_depth = COLOR_DEPTH_666; -+ set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); -+ set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); -+ break; -+ case LB_PIXEL_DEPTH_24BPP: -+ color_depth = COLOR_DEPTH_888; -+ set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); -+ set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); -+ break; -+ case LB_PIXEL_DEPTH_30BPP: -+ color_depth = COLOR_DEPTH_101010; -+ set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); -+ set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); -+ break; -+ case LB_PIXEL_DEPTH_36BPP: -+ color_depth = COLOR_DEPTH_121212; -+ set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); -+ set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); -+ break; -+ default: -+ ret = false; -+ break; -+ } -+ -+ if (ret == true) { -+ set_denormalization(xfm110, color_depth); -+ ret = program_bit_depth_reduction(xfm110, color_depth); -+ -+ set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); -+ dal_write_reg( -+ xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); -+ if (!(xfm110->lb_pixel_depth_supported & depth)) { -+ /*we should use unsupported capabilities -+ * unless it is required by w/a*/ -+ dal_logger_write(xfm->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Capability not supported", -+ __func__); -+ } -+ } -+ -+ return ret; -+} -+ -+/* LB_MEMORY_CONFIG -+ * 00 - Use all three pieces of memory -+ * 01 - Use only one piece of memory of total 720x144 bits -+ * 10 - Use two pieces of memory of total 960x144 bits -+ * 11 - reserved -+ * -+ * LB_MEMORY_SIZE -+ * Total entries of LB memory. -+ * This number should be larger than 960. The default value is 1712(0x6B0) */ -+bool dce110_transform_power_up_line_buffer(struct transform *xfm) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ uint32_t value; -+ -+ value = dal_read_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL)); -+ -+ /*Use all three pieces of memory always*/ -+ set_reg_field_value(value, 0, LB_MEMORY_CTRL, LB_MEMORY_CONFIG); -+ /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ -+ set_reg_field_value(value, LB_TOTAL_NUMBER_OF_ENTRIES, LB_MEMORY_CTRL, -+ LB_MEMORY_SIZE); -+ -+ dal_write_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL), value); -+ -+ return true; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h -new file mode 100644 -index 0000000..ff100cc ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h -@@ -0,0 +1,51 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_TRANSFORM_BIT_DEPTH_DCE110_H__ -+#define __DC_TRANSFORM_BIT_DEPTH_DCE110_H__ -+ -+#include "dce110_transform.h" -+ -+bool dce110_transform_power_up_line_buffer(struct transform *xfm); -+ -+bool dce110_transform_get_max_num_of_supported_lines( -+ struct dce110_transform *xfm110, -+ enum lb_pixel_depth depth, -+ uint32_t pixel_width, -+ uint32_t *lines); -+ -+void dce110_transform_enable_alpha( -+ struct dce110_transform *xfm110, -+ bool enable); -+ -+bool dce110_transform_get_next_lower_pixel_storage_depth( -+ struct dce110_transform *xfm110, -+ uint32_t display_bpp, -+ enum lb_pixel_depth depth, -+ enum lb_pixel_depth *lower_depth); -+ -+bool dce110_transform_is_prefetch_enabled( -+ struct dce110_transform *xfm110); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c -new file mode 100644 -index 0000000..a5b5b01 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c -@@ -0,0 +1,297 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "dce110_transform.h" -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "include/fixed31_32.h" -+#include "include/hw_sequencer_types.h" -+#include "basics/conversion.h" -+#include "include/grph_object_id.h" -+ -+enum { -+ GAMUT_MATRIX_SIZE = 12 -+}; -+ -+#define DCP_REG(reg)\ -+ (reg + xfm110->offsets.dcp_offset) -+ -+#define DISP_BRIGHTNESS_DEFAULT_HW 0 -+#define DISP_BRIGHTNESS_MIN_HW -25 -+#define DISP_BRIGHTNESS_MAX_HW 25 -+#define DISP_BRIGHTNESS_STEP_HW 1 -+#define DISP_BRIGHTNESS_HW_DIVIDER 100 -+ -+#define DISP_HUE_DEFAULT_HW 0 -+#define DISP_HUE_MIN_HW -30 -+#define DISP_HUE_MAX_HW 30 -+#define DISP_HUE_STEP_HW 1 -+#define DISP_HUE_HW_DIVIDER 1 -+ -+#define DISP_CONTRAST_DEFAULT_HW 100 -+#define DISP_CONTRAST_MIN_HW 50 -+#define DISP_CONTRAST_MAX_HW 150 -+#define DISP_CONTRAST_STEP_HW 1 -+#define DISP_CONTRAST_HW_DIVIDER 100 -+ -+#define DISP_SATURATION_DEFAULT_HW 100 -+#define DISP_SATURATION_MIN_HW 0 -+#define DISP_SATURATION_MAX_HW 200 -+#define DISP_SATURATION_STEP_HW 1 -+#define DISP_SATURATION_HW_DIVIDER 100 -+ -+#define DISP_KELVIN_DEGRES_DEFAULT 6500 -+#define DISP_KELVIN_DEGRES_MIN 4000 -+#define DISP_KELVIN_DEGRES_MAX 10000 -+#define DISP_KELVIN_DEGRES_STEP 100 -+#define DISP_KELVIN_HW_DIVIDER 10000 -+ -+static void program_gamut_remap( -+ struct dce110_transform *xfm110, -+ const uint16_t *reg_val) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t value = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_CONTROL); -+ -+ /* the register controls ovl also */ -+ value = dal_read_reg(ctx, addr); -+ -+ if (reg_val) { -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C11_C12); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[0], -+ GAMUT_REMAP_C11_C12, -+ GAMUT_REMAP_C11); -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[1], -+ GAMUT_REMAP_C11_C12, -+ GAMUT_REMAP_C12); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C13_C14); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[2], -+ GAMUT_REMAP_C13_C14, -+ GAMUT_REMAP_C13); -+ -+ /* fixed S0.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[3], -+ GAMUT_REMAP_C13_C14, -+ GAMUT_REMAP_C14); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C21_C22); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[4], -+ GAMUT_REMAP_C21_C22, -+ GAMUT_REMAP_C21); -+ -+ /* fixed S0.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[5], -+ GAMUT_REMAP_C21_C22, -+ GAMUT_REMAP_C22); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C23_C24); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[6], -+ GAMUT_REMAP_C23_C24, -+ GAMUT_REMAP_C23); -+ -+ /* fixed S0.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[7], -+ GAMUT_REMAP_C23_C24, -+ GAMUT_REMAP_C24); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C31_C32); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[8], -+ GAMUT_REMAP_C31_C32, -+ GAMUT_REMAP_C31); -+ -+ /* fixed S0.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[9], -+ GAMUT_REMAP_C31_C32, -+ GAMUT_REMAP_C32); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ { -+ uint32_t reg_data = 0; -+ uint32_t addr = DCP_REG(mmGAMUT_REMAP_C33_C34); -+ -+ /* fixed S2.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[10], -+ GAMUT_REMAP_C33_C34, -+ GAMUT_REMAP_C33); -+ -+ /* fixed S0.13 format */ -+ set_reg_field_value( -+ reg_data, -+ reg_val[11], -+ GAMUT_REMAP_C33_C34, -+ GAMUT_REMAP_C34); -+ -+ dal_write_reg(ctx, addr, reg_data); -+ } -+ -+ set_reg_field_value( -+ value, -+ 1, -+ GAMUT_REMAP_CONTROL, -+ GRPH_GAMUT_REMAP_MODE); -+ -+ } else -+ set_reg_field_value( -+ value, -+ 0, -+ GAMUT_REMAP_CONTROL, -+ GRPH_GAMUT_REMAP_MODE); -+ -+ addr = DCP_REG(mmGAMUT_REMAP_CONTROL); -+ dal_write_reg(ctx, addr, value); -+ -+} -+ -+/** -+ ***************************************************************************** -+ * Function: dal_transform_wide_gamut_set_gamut_remap -+ * -+ * @param [in] const struct grph_csc_adjustment *adjust -+ * -+ * @return -+ * void -+ * -+ * @note calculate and apply color temperature adjustment to in Rgb color space -+ * -+ * @see -+ * -+ ***************************************************************************** -+ */ -+void dce110_transform_set_gamut_remap( -+ struct transform *xfm, -+ const struct grph_csc_adjustment *adjust) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ -+ if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW || -+ adjust->temperature_divider == 0) -+ program_gamut_remap(xfm110, NULL); -+ else { -+ struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE]; -+ uint16_t arr_reg_val[GAMUT_MATRIX_SIZE]; -+ -+ arr_matrix[0] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[0], -+ adjust->temperature_divider); -+ arr_matrix[1] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[1], -+ adjust->temperature_divider); -+ arr_matrix[2] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[2], -+ adjust->temperature_divider); -+ arr_matrix[3] = dal_fixed31_32_zero; -+ -+ arr_matrix[4] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[3], -+ adjust->temperature_divider); -+ arr_matrix[5] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[4], -+ adjust->temperature_divider); -+ arr_matrix[6] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[5], -+ adjust->temperature_divider); -+ arr_matrix[7] = dal_fixed31_32_zero; -+ -+ arr_matrix[8] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[6], -+ adjust->temperature_divider); -+ arr_matrix[9] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[7], -+ adjust->temperature_divider); -+ arr_matrix[10] = -+ dal_fixed31_32_from_fraction( -+ adjust->temperature_matrix[8], -+ adjust->temperature_divider); -+ arr_matrix[11] = dal_fixed31_32_zero; -+ -+ convert_float_matrix( -+ arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE); -+ -+ program_gamut_remap(xfm110, arr_reg_val); -+ } -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c -new file mode 100644 -index 0000000..f313d2c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c -@@ -0,0 +1,818 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* include DCE11 register header files */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "dce110_transform.h" -+ -+#define UP_SCALER_RATIO_MAX 16000 -+#define DOWN_SCALER_RATIO_MAX 250 -+#define SCALER_RATIO_DIVIDER 1000 -+ -+#define SCL_REG(reg)\ -+ (reg + xfm110->offsets.scl_offset) -+ -+#define DCFE_REG(reg)\ -+ (reg + xfm110->offsets.dcfe_offset) -+ -+static void disable_enhanced_sharpness(struct dce110_transform *xfm110) -+{ -+ uint32_t value; -+ -+ value = dal_read_reg(xfm110->base.ctx, -+ SCL_REG(mmSCL_F_SHARP_CONTROL)); -+ -+ set_reg_field_value(value, 0, -+ SCL_F_SHARP_CONTROL, SCL_HF_SHARP_EN); -+ -+ set_reg_field_value(value, 0, -+ SCL_F_SHARP_CONTROL, SCL_VF_SHARP_EN); -+ -+ set_reg_field_value(value, 0, -+ SCL_F_SHARP_CONTROL, SCL_HF_SHARP_SCALE_FACTOR); -+ -+ set_reg_field_value(value, 0, -+ SCL_F_SHARP_CONTROL, SCL_VF_SHARP_SCALE_FACTOR); -+ -+ dal_write_reg(xfm110->base.ctx, -+ SCL_REG(mmSCL_F_SHARP_CONTROL), value); -+} -+ -+/** -+* Function: -+* void setup_scaling_configuration -+* -+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps -+* Input: data -+* -+* Output: -+ void -+*/ -+static bool setup_scaling_configuration( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t addr; -+ uint32_t value; -+ -+ if (data->taps.h_taps + data->taps.v_taps <= 2) { -+ dce110_transform_set_scaler_bypass(&xfm110->base); -+ return false; -+ } -+ -+ { -+ addr = SCL_REG(mmSCL_MODE); -+ value = dal_read_reg(ctx, addr); -+ -+ if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END) -+ set_reg_field_value(value, 1, SCL_MODE, SCL_MODE); -+ else -+ set_reg_field_value(value, 2, SCL_MODE, SCL_MODE); -+ -+ set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ { -+ addr = SCL_REG(mmSCL_TAP_CONTROL); -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value(value, data->taps.h_taps - 1, -+ SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS); -+ -+ set_reg_field_value(value, data->taps.v_taps - 1, -+ SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ { -+ addr = SCL_REG(mmSCL_CONTROL); -+ value = dal_read_reg(ctx, addr); -+ /* 1 - Replaced out of bound pixels with edge */ -+ set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE); -+ -+ /* 1 - Replaced out of bound pixels with the edge pixel. */ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ return true; -+} -+ -+/** -+* Function: -+* void program_overscan -+* -+* Purpose: Programs overscan border -+* Input: overscan -+* -+* Output: -+ void -+*/ -+static void program_overscan( -+ struct dce110_transform *xfm110, -+ const struct overscan_info *overscan) -+{ -+ uint32_t overscan_left_right = 0; -+ uint32_t overscan_top_bottom = 0; -+ -+ set_reg_field_value(overscan_left_right, overscan->left, -+ EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); -+ -+ set_reg_field_value(overscan_left_right, overscan->right, -+ EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); -+ -+ set_reg_field_value(overscan_top_bottom, overscan->top, -+ EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); -+ -+ set_reg_field_value(overscan_top_bottom, overscan->bottom, -+ EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); -+ -+ dal_write_reg(xfm110->base.ctx, -+ SCL_REG(mmEXT_OVERSCAN_LEFT_RIGHT), -+ overscan_left_right); -+ -+ dal_write_reg(xfm110->base.ctx, -+ SCL_REG(mmEXT_OVERSCAN_TOP_BOTTOM), -+ overscan_top_bottom); -+} -+ -+static void program_two_taps_filter( -+ struct dce110_transform *xfm110, -+ bool enable, -+ bool vertical) -+{ -+ uint32_t addr; -+ uint32_t value; -+ /* 1: Hard coded 2 tap filter -+ * 0: Programmable 2 tap filter from coefficient RAM -+ */ -+ if (vertical) { -+ addr = SCL_REG(mmSCL_VERT_FILTER_CONTROL); -+ value = dal_read_reg(xfm110->base.ctx, addr); -+ set_reg_field_value( -+ value, -+ enable ? 1 : 0, -+ SCL_VERT_FILTER_CONTROL, -+ SCL_V_2TAP_HARDCODE_COEF_EN); -+ -+ } else { -+ addr = SCL_REG(mmSCL_HORZ_FILTER_CONTROL); -+ value = dal_read_reg(xfm110->base.ctx, addr); -+ set_reg_field_value( -+ value, -+ enable ? 1 : 0, -+ SCL_HORZ_FILTER_CONTROL, -+ SCL_H_2TAP_HARDCODE_COEF_EN); -+ } -+ -+ dal_write_reg(xfm110->base.ctx, addr, value); -+} -+ -+static void set_coeff_update_complete(struct dce110_transform *xfm110) -+{ -+ uint32_t value; -+ uint32_t addr = SCL_REG(mmSCL_UPDATE); -+ -+ value = dal_read_reg(xfm110->base.ctx, addr); -+ set_reg_field_value(value, 1, -+ SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+} -+ -+static void program_filter( -+ struct dce110_transform *xfm110, -+ enum ram_filter_type filter_type, -+ struct scaler_filter_params *scl_filter_params, -+ uint32_t *coeffs, -+ uint32_t coeffs_num) -+{ -+ uint32_t phase = 0; -+ uint32_t array_idx = 0; -+ uint32_t pair = 0; -+ -+ uint32_t taps_pairs = (scl_filter_params->taps + 1) / 2; -+ uint32_t phases_to_program = scl_filter_params->phases / 2 + 1; -+ -+ uint32_t i; -+ uint32_t addr; -+ uint32_t select_addr; -+ uint32_t select; -+ uint32_t data; -+ /* We need to disable power gating on coeff memory to do programming */ -+ -+ uint32_t pwr_ctrl_orig; -+ uint32_t pwr_ctrl_off; -+ -+ addr = DCFE_REG(mmDCFE_MEM_PWR_CTRL); -+ pwr_ctrl_orig = dal_read_reg(xfm110->base.ctx, addr); -+ pwr_ctrl_off = pwr_ctrl_orig; -+ set_reg_field_value( -+ pwr_ctrl_off, -+ 1, -+ DCFE_MEM_PWR_CTRL, -+ SCL_COEFF_MEM_PWR_DIS); -+ dal_write_reg(xfm110->base.ctx, addr, pwr_ctrl_off); -+ -+ addr = DCFE_REG(mmDCFE_MEM_PWR_STATUS); -+ /* Wait to disable gating: */ -+ for (i = 0; -+ i < 10 && -+ get_reg_field_value( -+ dal_read_reg(xfm110->base.ctx, addr), -+ DCFE_MEM_PWR_STATUS, -+ SCL_COEFF_MEM_PWR_STATE); -+ i++) -+ dc_service_delay_in_microseconds(xfm110->base.ctx, 1); -+ -+ ASSERT(i < 10); -+ -+ select_addr = SCL_REG(mmSCL_COEF_RAM_SELECT); -+ select = dal_read_reg(xfm110->base.ctx, select_addr); -+ -+ set_reg_field_value( -+ select, -+ filter_type, -+ SCL_COEF_RAM_SELECT, -+ SCL_C_RAM_FILTER_TYPE); -+ set_reg_field_value( -+ select, -+ 0, -+ SCL_COEF_RAM_SELECT, -+ SCL_C_RAM_TAP_PAIR_IDX); -+ set_reg_field_value( -+ select, -+ 0, -+ SCL_COEF_RAM_SELECT, -+ SCL_C_RAM_PHASE); -+ -+ data = 0; -+ -+ for (phase = 0; phase < phases_to_program; phase++) { -+ /* we always program N/2 + 1 phases, total phases N, but N/2-1 -+ * are just mirror phase 0 is unique and phase N/2 is unique -+ * if N is even -+ */ -+ -+ set_reg_field_value( -+ select, -+ phase, -+ SCL_COEF_RAM_SELECT, -+ SCL_C_RAM_PHASE); -+ -+ for (pair = 0; pair < taps_pairs; pair++) { -+ set_reg_field_value( -+ select, -+ pair, -+ SCL_COEF_RAM_SELECT, -+ SCL_C_RAM_TAP_PAIR_IDX); -+ dal_write_reg(xfm110->base.ctx, select_addr, select); -+ -+ /* even tap write enable */ -+ set_reg_field_value( -+ data, -+ 1, -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_EVEN_TAP_COEF_EN); -+ /* even tap data */ -+ set_reg_field_value( -+ data, -+ coeffs[array_idx], -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_EVEN_TAP_COEF); -+ -+ /* if we have odd number of taps and the last pair is -+ * here then we do not need to program -+ */ -+ if (scl_filter_params->taps % 2 && -+ pair == taps_pairs - 1) { -+ /* odd tap write disable */ -+ set_reg_field_value( -+ data, -+ 0, -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_ODD_TAP_COEF_EN); -+ set_reg_field_value( -+ data, -+ 0, -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_ODD_TAP_COEF); -+ array_idx += 1; -+ } else { -+ /* odd tap write enable */ -+ set_reg_field_value( -+ data, -+ 1, -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_ODD_TAP_COEF_EN); -+ /* dbg_val: 0x1000 / sclFilterParams->taps; */ -+ set_reg_field_value( -+ data, -+ coeffs[array_idx + 1], -+ SCL_COEF_RAM_TAP_DATA, -+ SCL_C_RAM_ODD_TAP_COEF); -+ -+ array_idx += 2; -+ } -+ -+ dal_write_reg( -+ xfm110->base.ctx, -+ SCL_REG(mmSCL_COEF_RAM_TAP_DATA), -+ data); -+ } -+ } -+ -+ ASSERT(coeffs_num == array_idx); -+ -+ /* reset the power gating register */ -+ dal_write_reg( -+ xfm110->base.ctx, -+ DCFE_REG(mmDCFE_MEM_PWR_CTRL), -+ pwr_ctrl_orig); -+ -+ set_coeff_update_complete(xfm110); -+} -+ -+/* -+ * -+ * Populates an array with filter coefficients in 1.1.12 fixed point form -+*/ -+static bool get_filter_coefficients( -+ struct dce110_transform *xfm110, -+ uint32_t taps, -+ uint32_t **data_tab, -+ uint32_t *data_size) -+{ -+ uint32_t num = 0; -+ uint32_t i; -+ const struct fixed31_32 *filter = -+ dal_scaler_filter_get( -+ xfm110->base.filter, -+ data_tab, -+ &num); -+ uint32_t *data_row; -+ -+ if (!filter) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ data_row = *data_tab; -+ -+ for (i = 0; i < num; ++i) { -+ /* req. format sign fixed 1.1.12, the values are always between -+ * [-1; 1] -+ * -+ * Each phase is mirrored as follows : -+ * 0 : Phase 0 -+ * 1 : Phase 1 or Phase 64 - 1 / 128 - 1 -+ * N : Phase N or Phase 64 - N / 128 - N -+ * -+ * Convert from Fixed31_32 to 1.1.12 by using floor on value -+ * shifted by number of required fractional bits(12) -+ */ -+ struct fixed31_32 value = filter[i]; -+ -+ data_row[i] = -+ dal_fixed31_32_floor(dal_fixed31_32_shl(value, 12)) & -+ 0x3FFC; -+ } -+ *data_size = num; -+ -+ return true; -+} -+ -+static bool program_multi_taps_filter( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data, -+ bool horizontal) -+{ -+ struct scaler_filter_params filter_params; -+ enum ram_filter_type filter_type; -+ uint32_t src_size; -+ uint32_t dst_size; -+ -+ uint32_t *filter_data = NULL; -+ uint32_t filter_data_size = 0; -+ -+ /* 16 phases total for DCE11 */ -+ filter_params.phases = 16; -+ -+ if (horizontal) { -+ filter_params.taps = data->taps.h_taps; -+ filter_params.sharpness = data->h_sharpness; -+ filter_params.flags.bits.HORIZONTAL = 1; -+ -+ src_size = data->viewport.width; -+ dst_size = -+ dal_fixed31_32_floor( -+ dal_fixed31_32_div( -+ dal_fixed31_32_from_int( -+ data->viewport.width), -+ data->ratios->horz)); -+ -+ filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL; -+ } else { -+ filter_params.taps = data->taps.v_taps; -+ filter_params.sharpness = data->v_sharpness; -+ filter_params.flags.bits.HORIZONTAL = 0; -+ -+ src_size = data->viewport.height; -+ dst_size = -+ dal_fixed31_32_floor( -+ dal_fixed31_32_div( -+ dal_fixed31_32_from_int( -+ data->viewport.height), -+ data->ratios->vert)); -+ -+ filter_type = FILTER_TYPE_RGB_Y_VERTICAL; -+ } -+ -+ /* 1. Generate the coefficients */ -+ if (!dal_scaler_filter_generate( -+ xfm110->base.filter, -+ &filter_params, -+ src_size, -+ dst_size)) -+ return false; -+ -+ /* 2. Convert coefficients to fixed point format 1.12 (note coeff. -+ * could be negative(!) and range is [ from -1 to 1 ]) */ -+ if (!get_filter_coefficients( -+ xfm110, -+ filter_params.taps, -+ &filter_data, -+ &filter_data_size)) -+ return false; -+ -+ /* 3. Program the filter */ -+ program_filter( -+ xfm110, -+ filter_type, -+ &filter_params, -+ filter_data, -+ filter_data_size); -+ -+ /* 4. Program the alpha if necessary */ -+ if (data->flags.bits.SHOULD_PROGRAM_ALPHA) { -+ if (horizontal) -+ filter_type = FILTER_TYPE_ALPHA_HORIZONTAL; -+ else -+ filter_type = FILTER_TYPE_ALPHA_VERTICAL; -+ -+ program_filter( -+ xfm110, -+ filter_type, -+ &filter_params, -+ filter_data, -+ filter_data_size); -+ } -+ -+ return true; -+} -+ -+static void program_viewport( -+ struct dce110_transform *xfm110, -+ const struct rect *view_port) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t value = 0; -+ uint32_t addr = 0; -+ -+ addr = SCL_REG(mmVIEWPORT_START); -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ view_port->x, -+ VIEWPORT_START, -+ VIEWPORT_X_START); -+ set_reg_field_value( -+ value, -+ view_port->y, -+ VIEWPORT_START, -+ VIEWPORT_Y_START); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = SCL_REG(mmVIEWPORT_SIZE); -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ view_port->height, -+ VIEWPORT_SIZE, -+ VIEWPORT_HEIGHT); -+ set_reg_field_value( -+ value, -+ view_port->width, -+ VIEWPORT_SIZE, -+ VIEWPORT_WIDTH); -+ dal_write_reg(ctx, addr, value); -+ -+ /* TODO: add stereo support */ -+} -+ -+static void calculate_inits( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data, -+ struct scl_ratios_inits *inits) -+{ -+ struct fixed31_32 h_init; -+ struct fixed31_32 v_init; -+ struct fixed31_32 v_init_bot; -+ -+ inits->bottom_enable = 0; -+ inits->h_int_scale_ratio = -+ dal_fixed31_32_u2d19(data->ratios->horz) << 5; -+ inits->v_int_scale_ratio = -+ dal_fixed31_32_u2d19(data->ratios->vert) << 5; -+ -+ h_init = -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_add( -+ data->ratios->horz, -+ dal_fixed31_32_from_int(data->taps.h_taps + 1)), -+ 2); -+ inits->h_init.integer = dal_fixed31_32_floor(h_init); -+ inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5; -+ -+ v_init = -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_add( -+ data->ratios->vert, -+ dal_fixed31_32_from_int(data->taps.v_taps + 1)), -+ 2); -+ inits->v_init.integer = dal_fixed31_32_floor(v_init); -+ inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5; -+ -+ if (data->flags.bits.INTERLACED) { -+ v_init_bot = -+ dal_fixed31_32_add( -+ dal_fixed31_32_div_int( -+ dal_fixed31_32_add( -+ data->ratios->vert, -+ dal_fixed31_32_from_int( -+ data->taps.v_taps + 1)), -+ 2), -+ data->ratios->vert); -+ inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot); -+ inits->v_init_bottom.fraction = -+ dal_fixed31_32_u0d19(v_init_bot) << 5; -+ -+ inits->bottom_enable = 1; -+ } -+} -+ -+static void program_scl_ratios_inits( -+ struct dce110_transform *xfm110, -+ struct scl_ratios_inits *inits) -+{ -+ uint32_t addr = SCL_REG(mmSCL_HORZ_FILTER_SCALE_RATIO); -+ uint32_t value = 0; -+ -+ set_reg_field_value( -+ value, -+ inits->h_int_scale_ratio, -+ SCL_HORZ_FILTER_SCALE_RATIO, -+ SCL_H_SCALE_RATIO); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+ -+ addr = SCL_REG(mmSCL_VERT_FILTER_SCALE_RATIO); -+ value = 0; -+ set_reg_field_value( -+ value, -+ inits->v_int_scale_ratio, -+ SCL_VERT_FILTER_SCALE_RATIO, -+ SCL_V_SCALE_RATIO); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+ -+ addr = SCL_REG(mmSCL_HORZ_FILTER_INIT); -+ value = 0; -+ set_reg_field_value( -+ value, -+ inits->h_init.integer, -+ SCL_HORZ_FILTER_INIT, -+ SCL_H_INIT_INT); -+ set_reg_field_value( -+ value, -+ inits->h_init.fraction, -+ SCL_HORZ_FILTER_INIT, -+ SCL_H_INIT_FRAC); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+ -+ addr = SCL_REG(mmSCL_VERT_FILTER_INIT); -+ value = 0; -+ set_reg_field_value( -+ value, -+ inits->v_init.integer, -+ SCL_VERT_FILTER_INIT, -+ SCL_V_INIT_INT); -+ set_reg_field_value( -+ value, -+ inits->v_init.fraction, -+ SCL_VERT_FILTER_INIT, -+ SCL_V_INIT_FRAC); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+ -+ if (inits->bottom_enable) { -+ addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT); -+ value = 0; -+ set_reg_field_value( -+ value, -+ inits->v_init_bottom.integer, -+ SCL_VERT_FILTER_INIT_BOT, -+ SCL_V_INIT_INT_BOT); -+ set_reg_field_value( -+ value, -+ inits->v_init_bottom.fraction, -+ SCL_VERT_FILTER_INIT_BOT, -+ SCL_V_INIT_FRAC_BOT); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+ } -+ -+ addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL); -+ value = 0; -+ set_reg_field_value( -+ value, -+ 0, -+ SCL_AUTOMATIC_MODE_CONTROL, -+ SCL_V_CALC_AUTO_RATIO_EN); -+ set_reg_field_value( -+ value, -+ 0, -+ SCL_AUTOMATIC_MODE_CONTROL, -+ SCL_H_CALC_AUTO_RATIO_EN); -+ dal_write_reg(xfm110->base.ctx, addr, value); -+} -+ -+static void get_viewport( -+ struct dce110_transform *xfm110, -+ struct rect *current_view_port) -+{ -+ uint32_t value_start; -+ uint32_t value_size; -+ -+ if (current_view_port == NULL) -+ return; -+ -+ value_start = dal_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_START)); -+ value_size = dal_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_SIZE)); -+ -+ current_view_port->x = get_reg_field_value( -+ value_start, -+ VIEWPORT_START, -+ VIEWPORT_X_START); -+ current_view_port->y = get_reg_field_value( -+ value_start, -+ VIEWPORT_START, -+ VIEWPORT_Y_START); -+ current_view_port->height = get_reg_field_value( -+ value_size, -+ VIEWPORT_SIZE, -+ VIEWPORT_HEIGHT); -+ current_view_port->width = get_reg_field_value( -+ value_size, -+ VIEWPORT_SIZE, -+ VIEWPORT_WIDTH); -+} -+ -+ -+bool dce110_transform_set_scaler( -+ struct transform *xfm, -+ const struct scaler_data *data) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ bool is_scaling_required; -+ struct dc_context *ctx = xfm->ctx; -+ -+ { -+ uint32_t addr = SCL_REG(mmSCL_BYPASS_CONTROL); -+ uint32_t value = dal_read_reg(xfm->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ SCL_BYPASS_CONTROL, -+ SCL_BYPASS_MODE); -+ dal_write_reg(xfm->ctx, addr, value); -+ } -+ -+ disable_enhanced_sharpness(xfm110); -+ -+ /* 3. Program overscan */ -+ program_overscan(xfm110, &data->overscan); -+ -+ /* 4. Program taps and configuration */ -+ is_scaling_required = setup_scaling_configuration(xfm110, data); -+ if (is_scaling_required) { -+ /* 5. Calculate and program ratio, filter initialization */ -+ struct scl_ratios_inits inits = { 0 }; -+ -+ calculate_inits(xfm110, data, &inits); -+ -+ program_scl_ratios_inits(xfm110, &inits); -+ -+ /* 6. Program vertical filters */ -+ if (data->taps.v_taps > 2) { -+ program_two_taps_filter(xfm110, false, true); -+ -+ if (!program_multi_taps_filter(xfm110, data, false)) { -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_DCP, -+ LOG_MINOR_DCP_SCALER, -+ "Failed vertical taps programming\n"); -+ return false; -+ } -+ } else -+ program_two_taps_filter(xfm110, true, true); -+ -+ /* 7. Program horizontal filters */ -+ if (data->taps.h_taps > 2) { -+ program_two_taps_filter(xfm110, false, false); -+ -+ if (!program_multi_taps_filter(xfm110, data, true)) { -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_DCP, -+ LOG_MINOR_DCP_SCALER, -+ "Failed horizontal taps programming\n"); -+ return false; -+ } -+ } else -+ program_two_taps_filter(xfm110, true, false); -+ } -+ -+ return true; -+} -+ -+void dce110_transform_set_scaler_bypass(struct transform *xfm) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ uint32_t sclv_mode; -+ -+ disable_enhanced_sharpness(xfm110); -+ -+ sclv_mode = dal_read_reg(xfm->ctx, SCL_REG(mmSCL_MODE)); -+ set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_MODE); -+ set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_PSCL_EN); -+ dal_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode); -+} -+ -+bool dce110_transform_update_viewport( -+ struct transform *xfm, -+ const struct rect *view_port, -+ bool is_fbc_attached) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ bool program_req = false; -+ struct rect current_view_port; -+ -+ if (view_port == NULL) -+ return program_req; -+ -+ get_viewport(xfm110, ¤t_view_port); -+ -+ if (current_view_port.x != view_port->x || -+ current_view_port.y != view_port->y || -+ current_view_port.height != view_port->height || -+ current_view_port.width != view_port->width) -+ program_req = true; -+ -+ if (program_req) { -+ /*underlay viewport is programmed with scaler -+ *program_viewport function pointer is not exposed*/ -+ program_viewport(xfm110, view_port); -+ } -+ -+ return program_req; -+} -+ -+void dce110_transform_set_scaler_filter( -+ struct transform *xfm, -+ struct scaler_filter *filter) -+{ -+ xfm->filter = filter; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c -new file mode 100644 -index 0000000..bcf20bb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c -@@ -0,0 +1,531 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "dce110_transform.h" -+ -+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\ -+ "TRANSFORM SCALER:%s()\n", __func__) -+ -+/* -+***************************************************************************** -+* Function: calculateViewport -+* -+* @brief -+* Calculates all of the data required to set the viewport -+* -+* @param [in] pData: scaler settings data -+* @param [out] pLumaVp: luma viewport information -+* @param [out] pChromaVp: chroma viewport information -+* @param [out] srcResCx2: source chroma resolution times 2 - for multi-taps -+* -+***************************************************************************** -+*/ -+static void calculate_viewport( -+ const struct scaler_data *scl_data, -+ struct rect *luma_viewport, -+ struct rect *chroma_viewport) -+{ -+ /*Do not set chroma vp for rgb444 pixel format*/ -+ luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2; -+ luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2; -+ luma_viewport->width = -+ scl_data->viewport.width - scl_data->viewport.width % 2; -+ luma_viewport->height = -+ scl_data->viewport.height - scl_data->viewport.height % 2; -+ -+ -+ if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) { -+ luma_viewport->width += luma_viewport->width % 2; -+ -+ chroma_viewport->x = luma_viewport->x / 2; -+ chroma_viewport->width = luma_viewport->width / 2; -+ } else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) { -+ luma_viewport->height += luma_viewport->height % 2; -+ luma_viewport->width += luma_viewport->width % 2; -+ /*for 420 video chroma is 1/4 the area of luma, scaled -+ *vertically and horizontally -+ */ -+ chroma_viewport->x = luma_viewport->x / 2; -+ chroma_viewport->y = luma_viewport->y / 2; -+ chroma_viewport->height = luma_viewport->height / 2; -+ chroma_viewport->width = luma_viewport->width / 2; -+ } -+} -+ -+ -+static void program_viewport( -+ struct dce110_transform *xfm110, -+ struct rect *luma_view_port, -+ struct rect *chroma_view_port) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t value = 0; -+ uint32_t addr = 0; -+ -+ if (luma_view_port->width != 0 && luma_view_port->height != 0) { -+ addr = mmSCLV_VIEWPORT_START; -+ value = 0; -+ set_reg_field_value( -+ value, -+ luma_view_port->x, -+ SCLV_VIEWPORT_START, -+ VIEWPORT_X_START); -+ set_reg_field_value( -+ value, -+ luma_view_port->y, -+ SCLV_VIEWPORT_START, -+ VIEWPORT_Y_START); -+ dal_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); -+ dal_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); -+ dal_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); -+ dal_write_reg(ctx, addr, value); -+ } -+ /* TODO: add stereo support */ -+} -+ -+ -+/* Until and For MPO video play story, to reduce time for implementation, -+ * below limits are applied for now: 2_TAPS only -+ * Use auto-calculated filter values -+ * Following routines will be empty for now: -+ * -+ * programSclRatiosInits -- calcualate scaler ratio manually -+ * calculateInits --- calcualate scaler ratio manually -+ * programFilter -- multi-taps -+ * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS -+ * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS -+ * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally -+ */ -+ -+/** -+* Function: -+* void setup_scaling_configuration -+* -+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps -+* Input: data -+* -+* Output: -+ void -+*/ -+static bool setup_scaling_configuration( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data) -+{ -+ bool is_scaling_needed = false; -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t value = 0; -+ -+ if (data->taps.h_taps + data->taps.v_taps > 2) { -+ set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); -+ set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); -+ is_scaling_needed = true; -+ } else { -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); -+ } -+ -+ if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { -+ set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); -+ set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); -+ is_scaling_needed = true; -+ } else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 && -+ data->dal_pixel_format != PIXEL_FORMAT_422BPP16) { -+ set_reg_field_value( -+ value, -+ get_reg_field_value(value, SCLV_MODE, SCL_MODE), -+ SCLV_MODE, -+ SCL_MODE_C); -+ set_reg_field_value( -+ value, -+ get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), -+ SCLV_MODE, -+ SCL_PSCL_EN_C); -+ } else { -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); -+ } -+ dal_write_reg(ctx, mmSCLV_MODE, value); -+ -+ { -+ value = dal_read_reg(ctx, mmSCLV_TAP_CONTROL); -+ -+ set_reg_field_value(value, data->taps.h_taps - 1, -+ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); -+ -+ set_reg_field_value(value, data->taps.v_taps - 1, -+ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); -+ -+ set_reg_field_value(value, data->taps.h_taps_c - 1, -+ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); -+ -+ set_reg_field_value(value, data->taps.v_taps_c - 1, -+ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); -+ -+ dal_write_reg(ctx, mmSCLV_TAP_CONTROL, value); -+ } -+ -+ { -+ /* we can ignore this register because we are ok with hw -+ * default 0 -- change to 1 according to dal2 code*/ -+ value = dal_read_reg(ctx, mmSCLV_CONTROL); -+ /* 0 - Replaced out of bound pixels with black pixel -+ * (or any other required color) */ -+ set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); -+ -+ /* 1 - Replaced out of bound pixels with the edge pixel. */ -+ dal_write_reg(ctx, mmSCLV_CONTROL, value); -+ } -+ -+ return is_scaling_needed; -+} -+ -+/** -+* Function: -+* void program_overscan -+* -+* Purpose: Programs overscan border -+* Input: overscan -+* -+* Output: -+ void -+*/ -+static void program_overscan( -+ struct dce110_transform *xfm110, -+ const struct overscan_info *overscan) -+{ -+ uint32_t overscan_left_right = 0; -+ uint32_t overscan_top_bottom = 0; -+ -+ set_reg_field_value(overscan_left_right, overscan->left, -+ SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); -+ -+ set_reg_field_value(overscan_left_right, overscan->right, -+ SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); -+ -+ set_reg_field_value(overscan_top_bottom, overscan->top, -+ SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); -+ -+ set_reg_field_value(overscan_top_bottom, overscan->bottom, -+ SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); -+ -+ dal_write_reg(xfm110->base.ctx, -+ mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, -+ overscan_left_right); -+ -+ dal_write_reg(xfm110->base.ctx, -+ mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, -+ overscan_top_bottom); -+} -+/* -+static void setup_auto_scaling(struct dce110_transform *xfm110) -+{ -+ uint32_t value = 0; -+ set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL, -+ SCL_V_CALC_AUTO_RATIO_EN); -+ set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL, -+ SCL_H_CALC_AUTO_RATIO_EN); -+ dal_write_reg(xfm->ctx, -+ xfm->regs[IDX_SCL_AUTOMATIC_MODE_CONTROL], -+ value); -+} -+*/ -+ -+static void program_two_taps_filter_horz( -+ struct dce110_transform *xfm110, -+ bool hardcode_coff) -+{ -+ uint32_t value = 0; -+ -+ if (hardcode_coff) -+ set_reg_field_value( -+ value, -+ 1, -+ SCLV_HORZ_FILTER_CONTROL, -+ SCL_H_2TAP_HARDCODE_COEF_EN); -+ -+ dal_write_reg(xfm110->base.ctx, -+ mmSCLV_HORZ_FILTER_CONTROL, -+ value); -+} -+ -+static void program_two_taps_filter_vert( -+ struct dce110_transform *xfm110, -+ bool hardcode_coff) -+{ -+ uint32_t value = 0; -+ -+ if (hardcode_coff) -+ set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL, -+ SCL_V_2TAP_HARDCODE_COEF_EN); -+ -+ dal_write_reg(xfm110->base.ctx, -+ mmSCLV_VERT_FILTER_CONTROL, -+ value); -+} -+ -+static void set_coeff_update_complete( -+ struct dce110_transform *xfm110) -+{ -+ /*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto -+ * calculation are implemented. Coefficient RAM is not used -+ * Do not check this flag yet -+ */ -+ -+ /*uint32_t value; -+ uint32_t addr = xfm->regs[IDX_SCL_UPDATE]; -+ -+ value = dal_read_reg(xfm->ctx, addr); -+ set_reg_field_value(value, 0, -+ SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE); -+ dal_write_reg(xfm->ctx, addr, value);*/ -+} -+ -+static bool program_multi_taps_filter( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data, -+ bool horizontal) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ -+ NOT_IMPLEMENTED(); -+ return false; -+} -+ -+static void calculate_inits( -+ struct dce110_transform *xfm110, -+ const struct scaler_data *data, -+ struct sclv_ratios_inits *inits, -+ struct rect *luma_viewport, -+ struct rect *chroma_viewport) -+{ -+ if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 || -+ data->dal_pixel_format == PIXEL_FORMAT_422BPP16) -+ inits->chroma_enable = true; -+ -+ /* TODO: implement rest of this function properly */ -+ if (inits->chroma_enable) { -+ inits->h_int_scale_ratio_luma = 0x1000000; -+ inits->v_int_scale_ratio_luma = 0x1000000; -+ inits->h_int_scale_ratio_chroma = 0x800000; -+ inits->v_int_scale_ratio_chroma = 0x800000; -+ } -+} -+ -+static void program_scl_ratios_inits( -+ struct dce110_transform *xfm110, -+ struct sclv_ratios_inits *inits) -+{ -+ struct dc_context *ctx = xfm110->base.ctx; -+ uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; -+ uint32_t value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ inits->h_int_scale_ratio_luma, -+ SCLV_HORZ_FILTER_SCALE_RATIO, -+ SCL_H_SCALE_RATIO); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = mmSCLV_VERT_FILTER_SCALE_RATIO; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ inits->v_int_scale_ratio_luma, -+ SCLV_VERT_FILTER_SCALE_RATIO, -+ SCL_V_SCALE_RATIO); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ inits->h_int_scale_ratio_chroma, -+ SCLV_HORZ_FILTER_SCALE_RATIO_C, -+ SCL_H_SCALE_RATIO_C); -+ dal_write_reg(ctx, addr, value); -+ -+ addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; -+ value = dal_read_reg(ctx, addr); -+ set_reg_field_value( -+ value, -+ inits->v_int_scale_ratio_chroma, -+ SCLV_VERT_FILTER_SCALE_RATIO_C, -+ SCL_V_SCALE_RATIO_C); -+ dal_write_reg(ctx, addr, value); -+} -+ -+void dce110_transform_underlay_set_scalerv_bypass(struct transform *xfm) -+{ -+ uint32_t addr = mmSCLV_MODE; -+ uint32_t value = dal_read_reg(xfm->ctx, addr); -+ -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); -+ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); -+ dal_write_reg(xfm->ctx, addr, value); -+} -+ -+bool dce110_transform_underlay_is_scaling_enabled(struct transform *xfm) -+{ -+ uint32_t value = dal_read_reg(xfm->ctx, mmSCLV_MODE); -+ uint8_t scl_mode = get_reg_field_value(value, SCLV_MODE, SCL_MODE); -+ -+ return scl_mode == 0; -+} -+ -+/* TODO: sync this one with DAL2 */ -+bool dce110_transform_underlay_set_scaler( -+ struct transform *xfm, -+ const struct scaler_data *data) -+{ -+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm); -+ bool is_scaling_required; -+ struct rect luma_viewport = {0}; -+ struct rect chroma_viewport = {0}; -+ struct dc_context *ctx = xfm->ctx; -+ -+ /* 1. Lock Scaler TODO: enable?*/ -+ /*set_scaler_update_lock(xfm, true);*/ -+ -+ /* 2. Calculate viewport, viewport programming should happen after init -+ * calculations as they may require an adjustment in the viewport. -+ */ -+ -+ calculate_viewport(data, &luma_viewport, &chroma_viewport); -+ -+ /* 3. Program overscan */ -+ program_overscan(xfm110, &data->overscan); -+ -+ /* 4. Program taps and configuration */ -+ is_scaling_required = setup_scaling_configuration(xfm110, data); -+ -+ if (is_scaling_required) { -+ /* 5. Calculate and program ratio, filter initialization */ -+ -+ struct sclv_ratios_inits inits = { 0 }; -+ -+ calculate_inits( -+ xfm110, -+ data, -+ &inits, -+ &luma_viewport, -+ &chroma_viewport); -+ -+ program_scl_ratios_inits(xfm110, &inits); -+ -+ /*scaler coeff of 2-TAPS use hardware auto calculated value*/ -+ -+ /* 6. Program vertical filters */ -+ if (data->taps.v_taps > 2) { -+ program_two_taps_filter_vert(xfm110, false); -+ -+ if (!program_multi_taps_filter(xfm110, data, false)) { -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_DCP, -+ LOG_MINOR_DCP_SCALER, -+ "Failed vertical taps programming\n"); -+ return false; -+ } -+ } else -+ program_two_taps_filter_vert(xfm110, true); -+ -+ /* 7. Program horizontal filters */ -+ if (data->taps.h_taps > 2) { -+ program_two_taps_filter_horz(xfm110, false); -+ -+ if (!program_multi_taps_filter(xfm110, data, true)) { -+ dal_logger_write(ctx->logger, -+ LOG_MAJOR_DCP, -+ LOG_MINOR_DCP_SCALER, -+ "Failed horizontal taps programming\n"); -+ return false; -+ } -+ } else -+ program_two_taps_filter_horz(xfm110, true); -+ } -+ -+ /* 8. Program the viewport */ -+ if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT) -+ program_viewport(xfm110, &luma_viewport, &chroma_viewport); -+ -+ /* 9. Unlock the Scaler TODO: enable?*/ -+ /* Every call to "set_scaler_update_lock(xfm, TRUE)" -+ * must have a corresponding call to -+ * "set_scaler_update_lock(xfm, FALSE)" */ -+ /*set_scaler_update_lock(xfm, false);*/ -+ -+ /* TODO: investigate purpose/need of SHOULD_UNLOCK */ -+ if (data->flags.bits.SHOULD_UNLOCK == false) -+ set_coeff_update_complete(xfm110); -+ -+ return true; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/Makefile b/drivers/gpu/drm/amd/dal/dc/dcs/Makefile -new file mode 100644 -index 0000000..a266942 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dcs/Makefile -@@ -0,0 +1,10 @@ -+# -+# 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. -+ -+DCS = ddc_service.o ddc_i2caux_helper.o -+ -+AMD_DAL_DCS = $(addprefix $(AMDDALPATH)/dc/dcs/,$(DCS)) -+ -+AMD_DAL_FILES += $(AMD_DAL_DCS) -diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c -new file mode 100644 -index 0000000..a4442d6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c -@@ -0,0 +1,159 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "ddc_i2caux_helper.h" -+#include "include/ddc_service_types.h" -+#include "include/vector.h" -+ -+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 = dc_service_alloc(ctx, sizeof(struct i2c_payloads)); -+ -+ if (!payloads) -+ return NULL; -+ -+ if (dal_vector_construct( -+ &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) -+ return payloads; -+ -+ dc_service_free(ctx, payloads); -+ return NULL; -+ -+} -+ -+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) -+{ -+ return (struct i2c_payload *)p->payloads.container; -+} -+ -+uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) -+{ -+ return p->payloads.count; -+} -+ -+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) -+{ -+ if (!p || !*p) -+ return; -+ dal_vector_destruct(&(*p)->payloads); -+ dc_service_free((*p)->payloads.ctx, *p); -+ *p = NULL; -+ -+} -+ -+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) -+{ -+ struct aux_payloads *payloads; -+ -+ payloads = dc_service_alloc(ctx, sizeof(struct aux_payloads)); -+ -+ if (!payloads) -+ return NULL; -+ -+ if (dal_vector_construct( -+ &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) -+ return payloads; -+ -+ dc_service_free(ctx, payloads); -+ return NULL; -+} -+ -+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) -+{ -+ return (struct aux_payload *)p->payloads.container; -+} -+ -+uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) -+{ -+ return p->payloads.count; -+} -+ -+ -+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) -+{ -+ if (!p || !*p) -+ return; -+ -+ dal_vector_destruct(&(*p)->payloads); -+ dc_service_free((*p)->payloads.ctx, *p); -+ *p = NULL; -+} -+ -+#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) -+ -+void dal_ddc_i2c_payloads_add( -+ struct i2c_payloads *payloads, -+ uint32_t address, -+ uint32_t len, -+ uint8_t *data, -+ bool write) -+{ -+ uint32_t payload_size = EDID_SEGMENT_SIZE; -+ uint32_t pos; -+ -+ for (pos = 0; pos < len; pos += payload_size) { -+ struct i2c_payload payload = { -+ .write = write, -+ .address = address, -+ .length = DDC_MIN(payload_size, len - pos), -+ .data = data + pos }; -+ dal_vector_append(&payloads->payloads, &payload); -+ } -+ -+} -+ -+void dal_ddc_aux_payloads_add( -+ struct aux_payloads *payloads, -+ uint32_t address, -+ uint32_t len, -+ uint8_t *data, -+ bool write) -+{ -+ uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; -+ uint32_t pos; -+ -+ for (pos = 0; pos < len; pos += payload_size) { -+ struct aux_payload payload = { -+ .i2c_over_aux = true, -+ .write = write, -+ .address = address, -+ .length = DDC_MIN(payload_size, len - pos), -+ .data = data + pos }; -+ dal_vector_append(&payloads->payloads, &payload); -+ } -+} -+ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h -new file mode 100644 -index 0000000..bb628cd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h -@@ -0,0 +1,60 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2CAUX_HELPER_H__ -+#define __DAL_I2CAUX_HELPER_H__ -+ -+#include "include/i2caux_interface.h" -+ -+#define EDID_SEGMENT_SIZE 256 -+ -+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); -+ -+#endif /* __DAL_I2CAUX_HELPER_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c -new file mode 100644 -index 0000000..5436704 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c -@@ -0,0 +1,1034 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/adapter_service_interface.h" -+#include "include/i2caux_interface.h" -+#include "include/ddc_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 "ddc_i2caux_helper.h" -+#include "ddc_service.h" -+#include "dal_services_types.h" -+ -+#define AUX_POWER_UP_WA_DELAY 500 -+#define I2C_OVER_AUX_DEFER_WA_DELAY 70 -+ -+/* CV smart dongle slave address for retrieving supported HDTV modes*/ -+#define CV_SMART_DONGLE_ADDRESS 0x20 -+/* DVI-HDMI dongle slave address for retrieving dongle signature*/ -+#define DVI_HDMI_DONGLE_ADDRESS 0x68 -+static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; -+struct dvi_hdmi_dongle_signature_data { -+ int8_t vendor[3];/* "AMD" */ -+ uint8_t version[2]; -+ uint8_t size; -+ int8_t id[11];/* "6140063500G"*/ -+}; -+/* DP-HDMI dongle slave address for retrieving dongle signature*/ -+#define DP_HDMI_DONGLE_ADDRESS 0x40 -+static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR"; -+#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04 -+ -+struct dp_hdmi_dongle_signature_data { -+ int8_t id[15];/* "DP-HDMI ADAPTOR"*/ -+ uint8_t eot;/* end of transmition '\x4' */ -+}; -+ -+/* Address range from 0x00 to 0x1F.*/ -+#define DP_ADAPTOR_TYPE2_SIZE 0x20 -+#define DP_ADAPTOR_TYPE2_REG_ID 0x10 -+#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D -+/* Identifies adaptor as Dual-mode adaptor */ -+#define DP_ADAPTOR_TYPE2_ID 0xA0 -+/* MHz*/ -+#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 -+/* MHz*/ -+#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 -+/* kHZ*/ -+#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 -+/* kHZ*/ -+#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 -+ -+#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW -+ -+enum edid_read_result { -+ EDID_READ_RESULT_EDID_MATCH = 0, -+ EDID_READ_RESULT_EDID_MISMATCH, -+ EDID_READ_RESULT_CHECKSUM_READ_ERR, -+ EDID_READ_RESULT_VENDOR_READ_ERR -+}; -+ -+/* SCDC Address defines (HDMI 2.0)*/ -+#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 -+#define HDMI_SCDC_ADDRESS 0x54 -+#define HDMI_SCDC_SINK_VERSION 0x01 -+#define HDMI_SCDC_SOURCE_VERSION 0x02 -+#define HDMI_SCDC_UPDATE_0 0x10 -+#define HDMI_SCDC_TMDS_CONFIG 0x20 -+#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 -+#define HDMI_SCDC_CONFIG_0 0x30 -+#define HDMI_SCDC_STATUS_FLAGS 0x40 -+#define HDMI_SCDC_ERR_DETECT 0x50 -+#define HDMI_SCDC_TEST_CONFIG 0xC0 -+ -+ -+union hdmi_scdc_update_read_data -+{ -+ uint8_t byte[2]; -+ struct -+ { -+ uint8_t STATUS_UPDATE:1; -+ uint8_t CED_UPDATE:1; -+ uint8_t RR_TEST:1; -+ uint8_t RESERVED:5; -+ uint8_t RESERVED2:8; -+ } fields; -+}; -+ -+union hdmi_scdc_status_flags_data -+{ -+ uint8_t byte[2]; -+ struct -+ { -+ uint8_t CLOCK_DETECTED:1; -+ uint8_t CH0_LOCKED:1; -+ uint8_t CH1_LOCKED:1; -+ uint8_t CH2_LOCKED:1; -+ uint8_t RESERVED:4; -+ uint8_t RESERVED2:8; -+ } fields; -+}; -+ -+union hdmi_scdc_ced_data -+{ -+ uint8_t byte[7]; -+ struct -+ { -+ uint8_t CH0_8LOW:8; -+ uint8_t CH0_7HIGH:7; -+ uint8_t CH0_VALID:1; -+ uint8_t CH1_8LOW:8; -+ uint8_t CH1_7HIGH:7; -+ uint8_t CH1_VALID:1; -+ uint8_t CH2_8LOW:8; -+ uint8_t CH2_7HIGH:7; -+ uint8_t CH2_VALID:1; -+ uint8_t CHECKSUM:8; -+ } fields; -+}; -+ -+union hdmi_scdc_test_config_Data -+{ -+ uint8_t byte; -+ struct -+ { -+ uint8_t TEST_READ_REQUEST_DELAY:7; -+ uint8_t TEST_READ_REQUEST: 1; -+ } fields; -+}; -+ -+ -+ -+union ddc_wa { -+ struct { -+ uint32_t DP_SKIP_POWER_OFF:1; -+ uint32_t DP_AUX_POWER_UP_WA_DELAY:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+struct ddc_flags { -+ uint8_t EDID_QUERY_DONE_ONCE:1; -+ uint8_t IS_INTERNAL_DISPLAY:1; -+ uint8_t FORCE_READ_REPEATED_START:1; -+ uint8_t EDID_STRESS_READ:1; -+ -+}; -+ -+struct ddc_service { -+ struct ddc *ddc_pin; -+ struct ddc_flags flags; -+ union ddc_wa wa; -+ enum ddc_transaction_type transaction_type; -+ enum display_dongle_type dongle_type; -+ struct dp_receiver_id_info dp_receiver_id_info; -+ struct adapter_service *as; -+ struct dc_context *ctx; -+ -+ uint32_t address; -+ uint32_t edid_buf_len; -+ uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; -+}; -+ -+static bool construct( -+ struct ddc_service *ddc_service, -+ struct ddc_service_init_data *init_data) -+{ -+ enum connector_id connector_id = -+ dal_graphics_object_id_get_connector_id(init_data->id); -+ -+ ddc_service->ctx = init_data->ctx; -+ ddc_service->as = init_data->as; -+ ddc_service->ddc_pin = dal_adapter_service_obtain_ddc( -+ init_data->as, init_data->id); -+ -+ ddc_service->flags.EDID_QUERY_DONE_ONCE = false; -+ -+ ddc_service->flags.FORCE_READ_REPEATED_START = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_DDC_READ_FORCE_REPEATED_START); -+ -+ ddc_service->flags.EDID_STRESS_READ = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_EDID_STRESS_READ); -+ -+ -+ ddc_service->flags.IS_INTERNAL_DISPLAY = -+ connector_id == CONNECTOR_ID_EDP || -+ connector_id == CONNECTOR_ID_LVDS; -+ -+ ddc_service->wa.raw = 0; -+ return true; -+} -+ -+struct ddc_service *dal_ddc_service_create( -+ struct ddc_service_init_data *init_data) -+{ -+ struct ddc_service *ddc_service; -+ -+ ddc_service = dc_service_alloc(init_data->ctx, sizeof(struct ddc_service)); -+ -+ if (!ddc_service) -+ return NULL; -+ -+ if (construct(ddc_service, init_data)) -+ return ddc_service; -+ -+ dc_service_free(init_data->ctx, ddc_service); -+ return NULL; -+} -+ -+static void destruct(struct ddc_service *ddc) -+{ -+ if (ddc->ddc_pin) -+ dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin); -+} -+ -+void dal_ddc_service_destroy(struct ddc_service **ddc) -+{ -+ if (!ddc || !*ddc) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ destruct(*ddc); -+ dc_service_free((*ddc)->ctx, *ddc); -+ *ddc = NULL; -+} -+ -+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc) -+{ -+ return DDC_SERVICE_TYPE_CONNECTOR; -+} -+ -+void dal_ddc_service_set_transaction_type( -+ struct ddc_service *ddc, -+ enum ddc_transaction_type type) -+{ -+ ddc->transaction_type = type; -+} -+ -+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc) -+{ -+ switch (ddc->transaction_type) { -+ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: -+ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: -+ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER: -+ return true; -+ default: -+ break; -+ } -+ return false; -+} -+ -+void ddc_service_set_dongle_type(struct ddc_service *ddc, -+ enum display_dongle_type dongle_type) -+{ -+ ddc->dongle_type = dongle_type; -+} -+ -+static uint32_t defer_delay_converter_wa( -+ struct ddc_service *ddc, -+ uint32_t defer_delay) -+{ -+ struct dp_receiver_id_info dp_rec_info = {0}; -+ -+ if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) && -+ (dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) && -+ !dal_strncmp(dp_rec_info.branch_name, -+ DP_DVI_CONVERTER_ID_4, -+ sizeof(dp_rec_info.branch_name))) -+ return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ? -+ defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY; -+ -+ return defer_delay; -+ -+} -+ -+#define DP_TRANSLATOR_DELAY 5 -+ -+static uint32_t get_defer_delay(struct ddc_service *ddc) -+{ -+ uint32_t defer_delay = 0; -+ -+ switch (ddc->transaction_type) { -+ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: -+ if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) || -+ (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) || -+ (DISPLAY_DONGLE_DP_HDMI_CONVERTER == -+ ddc->dongle_type)) { -+ -+ defer_delay = DP_TRANSLATOR_DELAY; -+ -+ defer_delay = -+ defer_delay_converter_wa(ddc, defer_delay); -+ -+ } else /*sink has a delay different from an Active Converter*/ -+ defer_delay = 0; -+ break; -+ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: -+ defer_delay = DP_TRANSLATOR_DELAY; -+ break; -+ default: -+ break; -+ } -+ return defer_delay; -+} -+ -+static bool i2c_read( -+ struct ddc_service *ddc, -+ uint32_t address, -+ uint8_t *buffer, -+ uint32_t len) -+{ -+ uint8_t offs_data = 0; -+ struct i2c_payload payloads[2] = { -+ { -+ .write = true, -+ .address = address, -+ .length = 1, -+ .data = &offs_data }, -+ { -+ .write = false, -+ .address = address, -+ .length = len, -+ .data = buffer } }; -+ -+ struct i2c_command command = { -+ .payloads = payloads, -+ .number_of_payloads = 2, -+ .engine = DDC_I2C_COMMAND_ENGINE, -+ .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; -+ -+ return dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &command); -+} -+ -+static uint8_t aux_read_edid_block( -+ struct ddc_service *ddc, -+ uint8_t address, -+ uint8_t index, -+ uint8_t *buf) -+{ -+ struct aux_command cmd = { -+ .payloads = NULL, -+ .number_of_payloads = 0, -+ .defer_delay = get_defer_delay(ddc), -+ .max_defer_write_retry = 0 }; -+ -+ uint8_t retrieved = 0; -+ uint8_t base_offset = -+ (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; -+ uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; -+ -+ for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; -+ retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { -+ -+ uint8_t offset = base_offset + retrieved; -+ -+ struct aux_payload payloads[3] = { -+ { -+ .i2c_over_aux = true, -+ .write = true, -+ .address = DDC_EDID_SEGMENT_ADDRESS, -+ .length = 1, -+ .data = &segment }, -+ { -+ .i2c_over_aux = true, -+ .write = true, -+ .address = address, -+ .length = 1, -+ .data = &offset }, -+ { -+ .i2c_over_aux = true, -+ .write = false, -+ .address = address, -+ .length = DEFAULT_AUX_MAX_DATA_SIZE, -+ .data = &buf[retrieved] } }; -+ -+ if (segment == 0) { -+ cmd.payloads = &payloads[1]; -+ cmd.number_of_payloads = 2; -+ } else { -+ cmd.payloads = payloads; -+ cmd.number_of_payloads = 3; -+ } -+ -+ if (!dal_i2caux_submit_aux_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &cmd)) -+ /* cannot read, break*/ -+ break; -+ } -+ -+ /* Reset segment to 0. Needed by some panels */ -+ if (0 != segment) { -+ struct aux_payload payloads[1] = { { -+ .i2c_over_aux = true, -+ .write = true, -+ .address = DDC_EDID_SEGMENT_ADDRESS, -+ .length = 1, -+ .data = &segment } }; -+ bool result = false; -+ -+ segment = 0; -+ -+ cmd.number_of_payloads = ARRAY_SIZE(payloads); -+ cmd.payloads = payloads; -+ -+ result = dal_i2caux_submit_aux_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &cmd); -+ -+ if (false == result) -+ dal_logger_write( -+ ddc->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, -+ "%s: Writing of EDID Segment (0x30) failed!\n", -+ __func__); -+ } -+ -+ return retrieved; -+} -+ -+static uint8_t i2c_read_edid_block( -+ struct ddc_service *ddc, -+ uint8_t address, -+ uint8_t index, -+ uint8_t *buf) -+{ -+ bool ret = false; -+ uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * -+ DDC_EDID_BLOCK_SIZE; -+ uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; -+ -+ struct i2c_command cmd = { -+ .payloads = NULL, -+ .number_of_payloads = 0, -+ .engine = DDC_I2C_COMMAND_ENGINE, -+ .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; -+ -+ struct i2c_payload payloads[3] = { -+ { -+ .write = true, -+ .address = DDC_EDID_SEGMENT_ADDRESS, -+ .length = 1, -+ .data = &segment }, -+ { -+ .write = true, -+ .address = address, -+ .length = 1, -+ .data = &offset }, -+ { -+ .write = false, -+ .address = address, -+ .length = DDC_EDID_BLOCK_SIZE, -+ .data = buf } }; -+/* -+ * Some I2C engines don't handle stop/start between write-offset and read-data -+ * commands properly. For those displays, we have to force the newer E-DDC -+ * behavior of repeated-start which can be enabled by runtime parameter. */ -+/* Originally implemented for OnLive using NXP receiver chip */ -+ -+ if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { -+ /* base block, use use DDC2B, submit as 2 commands */ -+ cmd.payloads = &payloads[1]; -+ cmd.number_of_payloads = 1; -+ -+ if (dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &cmd)) { -+ -+ cmd.payloads = &payloads[2]; -+ cmd.number_of_payloads = 1; -+ -+ ret = dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &cmd); -+ } -+ -+ } else { -+ /* -+ * extension block use E-DDC, submit as 1 command -+ * or if repeated-start is forced by runtime parameter -+ */ -+ if (segment != 0) { -+ /* include segment offset in command*/ -+ cmd.payloads = payloads; -+ cmd.number_of_payloads = 3; -+ } else { -+ /* we are reading first segment, -+ * segment offset is not required */ -+ cmd.payloads = &payloads[1]; -+ cmd.number_of_payloads = 2; -+ } -+ -+ ret = dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &cmd); -+ } -+ -+ return ret ? DDC_EDID_BLOCK_SIZE : 0; -+} -+ -+static uint32_t query_edid_block( -+ struct ddc_service *ddc, -+ uint8_t address, -+ uint8_t index, -+ uint8_t *buf, -+ uint32_t size) -+{ -+ uint32_t size_retrieved = 0; -+ -+ if (size < DDC_EDID_BLOCK_SIZE) -+ return 0; -+ -+ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { -+ -+ ASSERT(index < 2); -+ size_retrieved = -+ aux_read_edid_block(ddc, address, index, buf); -+ } else { -+ size_retrieved = -+ i2c_read_edid_block(ddc, address, index, buf); -+ } -+ -+ return size_retrieved; -+} -+ -+#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 -+#define DDC_TEST_ACK_ADDRESS 0x260 -+#define DDC_DPCD_EDID_TEST_ACK 0x04 -+#define DDC_DPCD_EDID_TEST_MASK 0x04 -+#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 -+ -+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) -+{ -+ dc_service_memmove(edid_buf, -+ ddc->edid_buf, ddc->edid_buf_len); -+} -+ -+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( -+ struct ddc_service *ddc, -+ struct display_sink_capability *sink_cap) -+{ -+ uint8_t i; -+ bool is_valid_hdmi_signature; -+ enum display_dongle_type *dongle = &sink_cap->dongle_type; -+ uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; -+ bool is_type2_dongle = false; -+ struct dp_hdmi_dongle_signature_data *dongle_signature; -+ -+ /* Assume we have no valid DP passive dongle connected */ -+ *dongle = DISPLAY_DONGLE_NONE; -+ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; -+ -+ /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ -+ if (!i2c_read( -+ ddc, -+ DP_HDMI_DONGLE_ADDRESS, -+ type2_dongle_buf, -+ sizeof(type2_dongle_buf))) { -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Detected DP-DVI dongle.\n"); -+ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; -+ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; -+ return; -+ } -+ -+ /* Check if Type 2 dongle.*/ -+ if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) -+ is_type2_dongle = true; -+ -+ dongle_signature = -+ (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf; -+ -+ is_valid_hdmi_signature = true; -+ -+ /* Check EOT */ -+ if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) { -+ is_valid_hdmi_signature = false; -+ } -+ -+ /* Check signature */ -+ for (i = 0; i < sizeof(dongle_signature->id); ++i) { -+ /* If its not the right signature, -+ * skip mismatch in subversion byte.*/ -+ if (dongle_signature->id[i] != -+ dp_hdmi_dongle_signature_str[i] && i != 3) { -+ -+ if (is_type2_dongle) { -+ is_valid_hdmi_signature = false; -+ break; -+ } -+ -+ } -+ } -+ -+ if (is_type2_dongle) { -+ uint32_t max_tmds_clk = -+ type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK]; -+ -+ max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2; -+ -+ if (0 == max_tmds_clk || -+ max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK || -+ max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) { -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Invalid Maximum TMDS clock"); -+ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; -+ } else { -+ if (is_valid_hdmi_signature == true) { -+ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Detected Type 2 DP-HDMI Maximum TMDS " -+ "clock, max TMDS clock: %d MHz", -+ max_tmds_clk); -+ } else { -+ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Detected Type 2 DP-HDMI (no valid HDMI" -+ " signature) Maximum TMDS clock, max " -+ "TMDS clock: %d MHz", -+ max_tmds_clk); -+ } -+ -+ /* Multiply by 1000 to convert to kHz. */ -+ sink_cap->max_hdmi_pixel_clock = -+ max_tmds_clk * 1000; -+ } -+ -+ } else { -+ if (is_valid_hdmi_signature == true) { -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Detected Type 1 DP-HDMI dongle.\n"); -+ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; -+ } -+ else { -+ dal_logger_write(ddc->ctx->logger, -+ LOG_MAJOR_DCS, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ "Detected Type 1 DP-HDMI dongle (no valid HDMI " -+ "signature).\n"); -+ -+ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; -+ } -+ } -+ -+ return; -+} -+ -+enum { -+ DP_SINK_CAP_SIZE = -+ DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 -+}; -+ -+bool dal_ddc_service_query_ddc_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ uint8_t *write_buf, -+ uint32_t write_size, -+ uint8_t *read_buf, -+ uint32_t read_size) -+{ -+ bool ret; -+ uint32_t payload_size = -+ dal_ddc_service_is_in_aux_transaction_mode(ddc) ? -+ DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE; -+ -+ uint32_t write_payloads = -+ (write_size + payload_size - 1) / payload_size; -+ -+ uint32_t read_payloads = -+ (read_size + payload_size - 1) / payload_size; -+ -+ uint32_t payloads_num = write_payloads + read_payloads; -+ -+ if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) -+ return false; -+ -+ /*TODO: len of payload data for i2c and aux is uint8!!!!, -+ * but we want to read 256 over i2c!!!!*/ -+ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { -+ -+ struct aux_payloads *payloads = -+ dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); -+ -+ struct aux_command command = { -+ .payloads = dal_ddc_aux_payloads_get(payloads), -+ .number_of_payloads = 0, -+ .defer_delay = get_defer_delay(ddc), -+ .max_defer_write_retry = 0 }; -+ -+ dal_ddc_aux_payloads_add( -+ payloads, address, write_size, write_buf, true); -+ -+ dal_ddc_aux_payloads_add( -+ payloads, address, read_size, read_buf, false); -+ -+ command.number_of_payloads = -+ dal_ddc_aux_payloads_get_count(payloads); -+ -+ ret = dal_i2caux_submit_aux_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &command); -+ -+ dal_ddc_aux_payloads_destroy(&payloads); -+ -+ } else { -+ struct i2c_payloads *payloads = -+ dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); -+ -+ struct i2c_command command = { -+ .payloads = dal_ddc_i2c_payloads_get(payloads), -+ .number_of_payloads = 0, -+ .engine = DDC_I2C_COMMAND_ENGINE, -+ .speed = -+ dal_adapter_service_get_sw_i2c_speed(ddc->as) }; -+ -+ dal_ddc_i2c_payloads_add( -+ payloads, address, write_size, write_buf, true); -+ -+ dal_ddc_i2c_payloads_add( -+ payloads, address, read_size, read_buf, false); -+ -+ command.number_of_payloads = -+ dal_ddc_i2c_payloads_get_count(payloads); -+ -+ ret = dal_i2caux_submit_i2c_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &command); -+ -+ dal_ddc_i2c_payloads_destroy(&payloads); -+ } -+ -+ return ret; -+} -+ -+bool dal_ddc_service_get_dp_receiver_id_info( -+ struct ddc_service *ddc, -+ struct dp_receiver_id_info *info) -+{ -+ if (!info) -+ return false; -+ -+ *info = ddc->dp_receiver_id_info; -+ return true; -+} -+ -+enum ddc_result dal_ddc_service_read_dpcd_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t len) -+{ -+ struct aux_payload read_payload = { -+ .i2c_over_aux = false, -+ .write = false, -+ .address = address, -+ .length = len, -+ .data = data, -+ }; -+ struct aux_command command = { -+ .payloads = &read_payload, -+ .number_of_payloads = 1, -+ .defer_delay = 0, -+ .max_defer_write_retry = 0, -+ }; -+ -+ if (len > DEFAULT_AUX_MAX_DATA_SIZE) { -+ BREAK_TO_DEBUGGER(); -+ return DDC_RESULT_FAILED_INVALID_OPERATION; -+ } -+ -+ if (dal_i2caux_submit_aux_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &command)) -+ return DDC_RESULT_SUCESSFULL; -+ -+ return DDC_RESULT_FAILED_OPERATION; -+} -+ -+enum ddc_result dal_ddc_service_write_dpcd_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ const uint8_t *data, -+ uint32_t len) -+{ -+ struct aux_payload write_payload = { -+ .i2c_over_aux = false, -+ .write = true, -+ .address = address, -+ .length = len, -+ .data = (uint8_t *)data, -+ }; -+ struct aux_command command = { -+ .payloads = &write_payload, -+ .number_of_payloads = 1, -+ .defer_delay = 0, -+ .max_defer_write_retry = 0, -+ }; -+ -+ if (len > DEFAULT_AUX_MAX_DATA_SIZE) { -+ BREAK_TO_DEBUGGER(); -+ return DDC_RESULT_FAILED_INVALID_OPERATION; -+ } -+ -+ if (dal_i2caux_submit_aux_command( -+ dal_adapter_service_get_i2caux(ddc->as), -+ ddc->ddc_pin, -+ &command)) -+ return DDC_RESULT_SUCESSFULL; -+ -+ return DDC_RESULT_FAILED_OPERATION; -+} -+ -+/*test only function*/ -+void dal_ddc_service_set_ddc_pin( -+ struct ddc_service *ddc_service, -+ struct ddc *ddc) -+{ -+ ddc_service->ddc_pin = ddc; -+} -+ -+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service) -+{ -+ return ddc_service->ddc_pin; -+} -+ -+ -+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service) -+{ -+ dc_service_memset(&ddc_service->dp_receiver_id_info, -+ 0, sizeof(struct dp_receiver_id_info)); -+} -+ -+void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, -+ uint32_t pix_clk, -+ bool lte_340_scramble) -+{ -+ bool over_340_mhz = pix_clk > 340000 ? 1 : 0; -+ uint8_t slave_address = HDMI_SCDC_ADDRESS; -+ uint8_t offset = HDMI_SCDC_SINK_VERSION; -+ uint8_t sink_version = 0; -+ uint8_t write_buffer[2] = {0}; -+ /*Lower than 340 Scramble bit from SCDC caps*/ -+ -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, -+ sizeof(offset), &sink_version, sizeof(sink_version)); -+ if (sink_version == 1) { -+ /*Source Version = 1*/ -+ write_buffer[0] = HDMI_SCDC_SOURCE_VERSION; -+ write_buffer[1] = 1; -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, -+ write_buffer, sizeof(write_buffer), NULL, 0); -+ /*Read Request from SCDC caps*/ -+ } -+ write_buffer[0] = HDMI_SCDC_TMDS_CONFIG; -+ -+ if (over_340_mhz) -+ { -+ write_buffer[1] = 3; -+ } -+ else if (lte_340_scramble) -+ { -+ write_buffer[1] = 1; -+ } -+ else -+ { -+ write_buffer[1] = 0; -+ } -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer, -+ sizeof(write_buffer), NULL, 0); -+} -+ -+void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) -+{ -+ uint8_t slave_address = HDMI_SCDC_ADDRESS; -+ uint8_t offset = HDMI_SCDC_TMDS_CONFIG; -+ uint8_t tmds_config = 0; -+ -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, -+ sizeof(offset), &tmds_config, sizeof(tmds_config)); -+ if (tmds_config & 0x1){ -+ union hdmi_scdc_status_flags_data status_data = {{0}}; -+ uint8_t scramble_status = 0; -+ -+ offset = HDMI_SCDC_SCRAMBLER_STATUS; -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, -+ &offset, sizeof(offset),&scramble_status, -+ sizeof(scramble_status)); -+ offset = HDMI_SCDC_STATUS_FLAGS; -+ dal_ddc_service_query_ddc_data(ddc_service, slave_address, -+ &offset, sizeof(offset),status_data.byte, -+ sizeof(status_data.byte)); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h -new file mode 100644 -index 0000000..e5217b7 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h -@@ -0,0 +1,38 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DDC_SERVICE_H__ -+#define __DAL_DDC_SERVICE_H__ -+ -+#include "include/ddc_service_types.h" -+ -+void dal_ddc_service_set_ddc_pin( -+ struct ddc_service *ddc_service, -+ struct ddc *ddc); -+ -+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); -+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service); -+ -+#endif /* __DAL_DDC_SERVICE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/Makefile b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile -new file mode 100644 -index 0000000..7380910 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile -@@ -0,0 +1,24 @@ -+# -+# Makefile for the 'gpio' sub-component of DAL. -+# It provides the control and status of HW GPIO pins. -+ -+GPIO = ddc.o dvo.o gpio_base.o gpio_service.o hw_ddc.o hw_dvo.o hw_factory.o \ -+ hw_gpio.o hw_gpio_pad.o hw_gpio_pin.o hw_hpd.o hw_translate.o irq.o -+ -+AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO)) -+ -+AMD_DAL_FILES += $(AMD_DAL_GPIO) -+ -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o hw_hpd_dce110.o \ -+ hw_ddc_dce110.o -+ -+AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110)) -+ -+AMD_DAL_FILES += $(AMD_DAL_GPIO_DCE110) -+endif -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c -new file mode 100644 -index 0000000..f026464 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c -@@ -0,0 +1,883 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "../hw_gpio_pin.h" -+#include "../hw_gpio.h" -+#include "../hw_ddc.h" -+ -+/* -+ * Header of this unit -+ */ -+#include "hw_ddc_dce110.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#define ADDR_DDC_SETUP pin->addr.dc_i2c_ddc_setup -+/* -+ * This unit -+ */ -+static void destruct( -+ struct hw_ddc_dce110 *pin) -+{ -+ dal_hw_ddc_destruct(&pin->base); -+} -+ -+static void destroy( -+ struct hw_gpio_pin **ptr) -+{ -+ struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(*ptr); -+ -+ destruct(pin); -+ -+ dc_service_free((*ptr)->ctx, pin); -+ -+ *ptr = NULL; -+} -+ -+struct hw_ddc_dce110_init { -+ struct hw_gpio_pin_reg hw_gpio_data_reg; -+ struct hw_ddc_mask hw_ddc_mask; -+ struct hw_ddc_dce110_addr hw_ddc_dce110_addr; -+}; -+ -+static const struct hw_ddc_dce110_init -+ hw_ddc_dce110_init_data[GPIO_DDC_LINE_COUNT] = { -+ /* GPIO_DDC_LINE_DDC1 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_A, -+ DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_EN, -+ DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_Y, -+ DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK, -+ DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK, -+ DC_GPIO_DDC1_MASK__AUX1_POL_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC1_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC2 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC2_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_A, -+ DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_EN, -+ DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_Y, -+ DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK, -+ DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK, -+ DC_GPIO_DDC2_MASK__AUX2_POL_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC2_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC3 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC3_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_A, -+ DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_EN, -+ DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_Y, -+ DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK, -+ DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK, -+ DC_GPIO_DDC3_MASK__AUX3_POL_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC3_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC4 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC4_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_A, -+ DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_EN, -+ DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_Y, -+ DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK, -+ DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK, -+ DC_GPIO_DDC4_MASK__AUX4_POL_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC4_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC5 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC5_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_A, -+ DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_EN, -+ DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_Y, -+ DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK, -+ DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK, -+ DC_GPIO_DDC5_MASK__AUX5_POL_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC5_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC6 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC6_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_A, -+ DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_EN, -+ DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_Y, -+ DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK, -+ DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK, -+ DC_GPIO_DDC6_MASK__AUX6_POL_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC6_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC_VGA */ -+ { -+ { -+ { -+ mmDC_GPIO_DDCVGA_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_A, -+ DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_EN, -+ DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_Y, -+ DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK, -+ DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK, -+ DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDCVGA_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_I2CPAD */ -+ { -+ { -+ { -+ mmDC_GPIO_I2CPAD_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_A, -+ DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_EN, -+ DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_Y, -+ DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK, -+ 0, -+ 0, -+ 0 -+ }, -+ { -+ 0 -+ } -+ } -+}; -+ -+static const struct hw_ddc_dce110_init -+ hw_ddc_dce110_init_clock[GPIO_DDC_LINE_COUNT] = { -+ /* GPIO_DDC_LINE_DDC1 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_A, -+ DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_EN, -+ DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC1_Y, -+ DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK, -+ DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK, -+ DC_GPIO_DDC1_MASK__AUX1_POL_MASK, -+ DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC1_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC2 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC2_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_A, -+ DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_EN, -+ DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC2_Y, -+ DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK, -+ DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK, -+ DC_GPIO_DDC2_MASK__AUX2_POL_MASK, -+ DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC2_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC3 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC3_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_A, -+ DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_EN, -+ DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC3_Y, -+ DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK, -+ DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK, -+ DC_GPIO_DDC3_MASK__AUX3_POL_MASK, -+ DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC3_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC4 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC4_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_A, -+ DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_EN, -+ DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC4_Y, -+ DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK, -+ DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK, -+ DC_GPIO_DDC4_MASK__AUX4_POL_MASK, -+ DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC4_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC5 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC5_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_A, -+ DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_EN, -+ DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC5_Y, -+ DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK, -+ DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK, -+ DC_GPIO_DDC5_MASK__AUX5_POL_MASK, -+ DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC5_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC6 */ -+ { -+ { -+ { -+ mmDC_GPIO_DDC6_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_A, -+ DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_EN, -+ DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDC6_Y, -+ DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK, -+ DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK, -+ DC_GPIO_DDC6_MASK__AUX6_POL_MASK, -+ DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDC6_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_DDC_VGA */ -+ { -+ { -+ { -+ mmDC_GPIO_DDCVGA_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_A, -+ DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_EN, -+ DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK -+ }, -+ { -+ mmDC_GPIO_DDCVGA_Y, -+ DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK, -+ DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK, -+ DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK, -+ DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK -+ }, -+ { -+ mmDC_I2C_DDCVGA_SETUP -+ } -+ }, -+ /* GPIO_DDC_LINE_I2CPAD */ -+ { -+ { -+ { -+ mmDC_GPIO_I2CPAD_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_A, -+ DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_EN, -+ DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK -+ }, -+ { -+ mmDC_GPIO_I2CPAD_Y, -+ DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK -+ } -+ }, -+ { -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK, -+ DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK, -+ 0, -+ 0, -+ 0 -+ }, -+ { -+ 0 -+ } -+ } -+}; -+ -+static void setup_i2c_polling( -+ struct dc_context *ctx, -+ const uint32_t addr, -+ bool enable_detect, -+ bool detect_mode) -+{ -+ uint32_t value; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ enable_detect, -+ DC_I2C_DDC1_SETUP, -+ DC_I2C_DDC1_ENABLE); -+ -+ set_reg_field_value( -+ value, -+ enable_detect, -+ DC_I2C_DDC1_SETUP, -+ DC_I2C_DDC1_EDID_DETECT_ENABLE); -+ -+ if (enable_detect) -+ set_reg_field_value( -+ value, -+ detect_mode, -+ DC_I2C_DDC1_SETUP, -+ DC_I2C_DDC1_EDID_DETECT_MODE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static enum gpio_result set_config( -+ struct hw_gpio_pin *ptr, -+ const struct gpio_config_data *config_data) -+{ -+ struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(ptr); -+ struct hw_gpio *hw_gpio = NULL; -+ uint32_t addr; -+ uint32_t regval; -+ uint32_t ddc_data_pd_en = 0; -+ uint32_t ddc_clk_pd_en = 0; -+ uint32_t aux_pad_mode = 0; -+ -+ hw_gpio = &pin->base.base; -+ -+ if (hw_gpio == NULL) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_NULL_HANDLE; -+ } -+ -+ /* switch dual mode GPIO to I2C/AUX mode */ -+ -+ addr = hw_gpio->pin_reg.DC_GPIO_DATA_MASK.addr; -+ -+ regval = dal_read_reg(ptr->ctx, addr); -+ -+ ddc_data_pd_en = get_reg_field_value( -+ regval, -+ DC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1DATA_PD_EN); -+ -+ ddc_clk_pd_en = get_reg_field_value( -+ regval, -+ DC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1CLK_PD_EN); -+ -+ aux_pad_mode = get_reg_field_value( -+ regval, -+ DC_GPIO_DDC1_MASK, -+ AUX_PAD1_MODE); -+ -+ switch (config_data->config.ddc.type) { -+ case GPIO_DDC_CONFIG_TYPE_MODE_I2C: -+ /* On plug-in, there is a transient level on the pad -+ * which must be discharged through the internal pull-down. -+ * Enable internal pull-down, 2.5msec discharge time -+ * is required for detection of AUX mode */ -+ if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) { -+ if (!ddc_data_pd_en || !ddc_clk_pd_en) { -+ set_reg_field_value( -+ regval, -+ 1, -+ DC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1DATA_PD_EN); -+ -+ set_reg_field_value( -+ regval, -+ 1, -+ DC_GPIO_DDC1_MASK, -+ DC_GPIO_DDC1CLK_PD_EN); -+ -+ dal_write_reg(ptr->ctx, addr, regval); -+ -+ if (config_data->type == -+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) -+ /* should not affect normal I2C R/W */ -+ /* [anaumov] in DAL2, there was -+ * dc_service_delay_in_microseconds(2500); */ -+ dc_service_sleep_in_milliseconds(ptr->ctx, 3); -+ } -+ } else { -+ uint32_t reg2 = regval; -+ uint32_t sda_pd_dis = 0; -+ uint32_t scl_pd_dis = 0; -+ -+ sda_pd_dis = get_reg_field_value( -+ reg2, -+ DC_GPIO_I2CPAD_MASK, -+ DC_GPIO_SDA_PD_DIS); -+ -+ scl_pd_dis = get_reg_field_value( -+ reg2, -+ DC_GPIO_I2CPAD_MASK, -+ DC_GPIO_SCL_PD_DIS); -+ -+ if (sda_pd_dis) { -+ sda_pd_dis = 0; -+ -+ dal_write_reg(ptr->ctx, addr, reg2); -+ -+ if (config_data->type == -+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) -+ /* should not affect normal I2C R/W */ -+ /* [anaumov] in DAL2, there was -+ * dc_service_delay_in_microseconds(2500); */ -+ dc_service_sleep_in_milliseconds(ptr->ctx, 3); -+ } -+ -+ if (!scl_pd_dis) { -+ scl_pd_dis = 1; -+ -+ dal_write_reg(ptr->ctx, addr, reg2); -+ -+ if (config_data->type == -+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) -+ /* should not affect normal I2C R/W */ -+ /* [anaumov] in DAL2, there was -+ * dc_service_delay_in_microseconds(2500); */ -+ dc_service_sleep_in_milliseconds(ptr->ctx, 3); -+ } -+ } -+ -+ if (aux_pad_mode) { -+ /* let pins to get de-asserted -+ * before setting pad to I2C mode */ -+ if (config_data->config.ddc.data_en_bit_present || -+ config_data->config.ddc.clock_en_bit_present) -+ /* [anaumov] in DAL2, there was -+ * dc_service_delay_in_microseconds(2000); */ -+ dc_service_sleep_in_milliseconds(ptr->ctx, 2); -+ -+ /* set the I2C pad mode */ -+ /* read the register again, -+ * some bits may have been changed */ -+ regval = dal_read_reg(ptr->ctx, addr); -+ -+ set_reg_field_value( -+ regval, -+ 0, -+ DC_GPIO_DDC1_MASK, -+ AUX_PAD1_MODE); -+ -+ dal_write_reg(ptr->ctx, addr, regval); -+ } -+ -+ return GPIO_RESULT_OK; -+ case GPIO_DDC_CONFIG_TYPE_MODE_AUX: -+ /* set the AUX pad mode */ -+ if (!aux_pad_mode) { -+ set_reg_field_value( -+ regval, -+ 1, -+ DC_GPIO_DDC1_MASK, -+ AUX_PAD1_MODE); -+ -+ dal_write_reg(ptr->ctx, addr, regval); -+ } -+ -+ return GPIO_RESULT_OK; -+ case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT: -+ if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && -+ (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { -+ setup_i2c_polling( -+ ptr->ctx, ADDR_DDC_SETUP, 1, 0); -+ return GPIO_RESULT_OK; -+ } -+ break; -+ case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT: -+ if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && -+ (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { -+ setup_i2c_polling( -+ ptr->ctx, ADDR_DDC_SETUP, 1, 1); -+ return GPIO_RESULT_OK; -+ } -+ break; -+ case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING: -+ if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && -+ (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { -+ setup_i2c_polling( -+ ptr->ctx, ADDR_DDC_SETUP, 0, 0); -+ return GPIO_RESULT_OK; -+ } -+ break; -+ } -+ -+ BREAK_TO_DEBUGGER(); -+ -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+} -+ -+static const struct hw_gpio_pin_funcs funcs = { -+ .destroy = destroy, -+ .open = dal_hw_ddc_open, -+ .get_value = dal_hw_gpio_get_value, -+ .set_value = dal_hw_gpio_set_value, -+ .set_config = set_config, -+ .change_mode = dal_hw_gpio_change_mode, -+ .close = dal_hw_gpio_close, -+}; -+ -+ -+static bool construct( -+ struct hw_ddc_dce110 *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ const struct hw_ddc_dce110_init *init; -+ -+ if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (!dal_hw_ddc_construct(&pin->base, id, en, ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ pin->base.base.base.funcs = &funcs; -+ -+ switch (id) { -+ case GPIO_ID_DDC_DATA: -+ init = hw_ddc_dce110_init_data + en; -+ -+ pin->base.base.pin_reg = init->hw_gpio_data_reg; -+ pin->base.mask = init->hw_ddc_mask; -+ pin->addr = init->hw_ddc_dce110_addr; -+ -+ return true; -+ case GPIO_ID_DDC_CLOCK: -+ init = hw_ddc_dce110_init_clock + en; -+ -+ pin->base.base.pin_reg = init->hw_gpio_data_reg; -+ pin->base.mask = init->hw_ddc_mask; -+ pin->addr = init->hw_ddc_dce110_addr; -+ -+ return true; -+ default: -+ ASSERT_CRITICAL(false); -+ } -+ -+ return false; -+} -+ -+struct hw_gpio_pin *dal_hw_ddc_dce110_create( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ struct hw_ddc_dce110 *pin = dc_service_alloc(ctx, sizeof(struct hw_ddc_dce110)); -+ -+ if (!pin) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(pin, id, en, ctx)) -+ return &pin->base.base.base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(ctx, pin); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h -new file mode 100644 -index 0000000..6830369 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h -@@ -0,0 +1,46 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_DDC_DCE110_H__ -+#define __DAL_HW_DDC_DCE110_H__ -+ -+struct hw_ddc_dce110_addr { -+ uint32_t dc_i2c_ddc_setup; -+}; -+ -+struct hw_ddc_dce110 { -+ struct hw_ddc base; -+ struct hw_ddc_dce110_addr addr; -+}; -+ -+#define DDC_DCE110_FROM_BASE(ddc_base) \ -+ container_of((HW_DDC_FROM_BASE(ddc_base)), struct hw_ddc_dce110, base) -+ -+struct hw_gpio_pin *dal_hw_ddc_dce110_create( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c -new file mode 100644 -index 0000000..85644c5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c -@@ -0,0 +1,84 @@ -+/* -+ * 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 "dal_services.h" -+#include "include/gpio_types.h" -+#include "../hw_factory.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "../hw_gpio_pin.h" -+#include "../hw_gpio.h" -+#include "../hw_ddc.h" -+#include "../hw_hpd.h" -+ -+#include "hw_factory_dce110.h" -+#include "hw_hpd_dce110.h" -+#include "hw_ddc_dce110.h" -+ -+/* fucntion table */ -+static const struct hw_factory_funcs funcs = { -+ .create_dvo = NULL, -+ .create_ddc_data = dal_hw_ddc_dce110_create, -+ .create_ddc_clock = dal_hw_ddc_dce110_create, -+ .create_generic = NULL, -+ .create_hpd = dal_hw_hpd_dce110_create, -+ .create_gpio_pad = NULL, -+ .create_sync = NULL, -+ .create_gsl = NULL, -+}; -+ -+/* -+ * dal_hw_factory_dce110_init -+ * -+ * @brief -+ * Initialize HW factory function pointers and pin info -+ * -+ * @param -+ * struct hw_factory *factory - [out] struct of function pointers -+ */ -+void dal_hw_factory_dce110_init(struct hw_factory *factory) -+{ -+ /*TODO check ASIC CAPs*/ -+ factory->number_of_pins[GPIO_ID_DVO1] = 24; -+ factory->number_of_pins[GPIO_ID_DVO12] = 2; -+ factory->number_of_pins[GPIO_ID_DVO24] = 1; -+ factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; -+ factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; -+ factory->number_of_pins[GPIO_ID_GENERIC] = 7; -+ factory->number_of_pins[GPIO_ID_HPD] = 6; -+ factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; -+ factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; -+ factory->number_of_pins[GPIO_ID_SYNC] = 2; -+ factory->number_of_pins[GPIO_ID_GSL] = 4; -+ -+ factory->funcs = &funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h -new file mode 100644 -index 0000000..ecf06ed ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h -@@ -0,0 +1,32 @@ -+/* -+ * Copyright 2013-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_FACTORY_DCE110_H__ -+#define __DAL_HW_FACTORY_DCE110_H__ -+ -+/* Initialize HW factory function pointers and pin info */ -+void dal_hw_factory_dce110_init(struct hw_factory *factory); -+ -+#endif /* __DAL_HW_FACTORY_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c -new file mode 100644 -index 0000000..34405e9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_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 "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "../hw_gpio_pin.h" -+#include "../hw_gpio.h" -+#include "../hw_hpd.h" -+ -+/* -+ * Header of this unit -+ */ -+#include "hw_hpd_dce110.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+/* -+ * This unit -+ */ -+ -+static void destruct( -+ struct hw_hpd_dce110 *pin) -+{ -+ dal_hw_hpd_destruct(&pin->base); -+} -+ -+static void destroy( -+ struct hw_gpio_pin **ptr) -+{ -+ struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(*ptr); -+ -+ destruct(pin); -+ -+ dc_service_free((*ptr)->ctx, pin); -+ -+ *ptr = NULL; -+} -+ -+struct hw_gpio_generic_dce110_init { -+ struct hw_gpio_pin_reg hw_gpio_data_reg; -+ struct hw_hpd_dce110_addr addr; -+}; -+ -+static const struct hw_gpio_generic_dce110_init -+ hw_gpio_generic_dce110_init[GPIO_HPD_COUNT] = { -+ /* GPIO_HPD_1 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK -+ } -+ }, -+ { -+ mmHPD0_DC_HPD_INT_STATUS, -+ mmHPD0_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ }, -+ /* GPIO_HPD_2 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK -+ } -+ }, -+ { -+ mmHPD1_DC_HPD_INT_STATUS, -+ mmHPD1_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ }, -+ /* GPIO_HPD_3 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK -+ } -+ }, -+ { -+ mmHPD2_DC_HPD_INT_STATUS, -+ mmHPD2_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ }, -+ /* GPIO_HPD_4 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK -+ } -+ }, -+ { -+ mmHPD3_DC_HPD_INT_STATUS, -+ mmHPD3_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ }, -+ /* GPIO_HPD_5 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK -+ } -+ }, -+ { -+ mmHPD4_DC_HPD_INT_STATUS, -+ mmHPD4_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ }, -+ /* GPIO_HPD_6 */ -+ { -+ { -+ { -+ mmDC_GPIO_HPD_MASK, -+ DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_A, -+ DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_EN, -+ DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK -+ }, -+ { -+ mmDC_GPIO_HPD_Y, -+ DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK -+ } -+ }, -+ { -+ mmHPD5_DC_HPD_INT_STATUS, -+ mmHPD5_DC_HPD_TOGGLE_FILT_CNTL -+ } -+ } -+}; -+ -+static enum gpio_result get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value) -+{ -+ struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr); -+ -+ /* in Interrupt mode we ask for SENSE bit */ -+ -+ if (ptr->mode == GPIO_MODE_INTERRUPT) { -+ uint32_t regval; -+ uint32_t hpd_delayed = 0; -+ uint32_t hpd_sense = 0; -+ -+ regval = dal_read_reg( -+ ptr->ctx, -+ pin->addr.DC_HPD_INT_STATUS); -+ -+ hpd_delayed = get_reg_field_value( -+ regval, -+ DC_HPD_INT_STATUS, -+ DC_HPD_SENSE_DELAYED); -+ -+ hpd_sense = get_reg_field_value( -+ regval, -+ DC_HPD_INT_STATUS, -+ DC_HPD_SENSE); -+ -+ *value = hpd_delayed; -+ return GPIO_RESULT_OK; -+ } -+ -+ /* in any other modes, operate as normal GPIO */ -+ -+ return dal_hw_gpio_get_value(ptr, value); -+} -+ -+static enum gpio_result set_config( -+ struct hw_gpio_pin *ptr, -+ const struct gpio_config_data *config_data) -+{ -+ struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr); -+ -+ if (!config_data) -+ return GPIO_RESULT_INVALID_DATA; -+ -+ { -+ uint32_t value; -+ -+ value = dal_read_reg( -+ ptr->ctx, -+ pin->addr.DC_HPD_TOGGLE_FILT_CNTL); -+ -+ set_reg_field_value( -+ value, -+ config_data->config.hpd.delay_on_connect / 10, -+ DC_HPD_TOGGLE_FILT_CNTL, -+ DC_HPD_CONNECT_INT_DELAY); -+ -+ set_reg_field_value( -+ value, -+ config_data->config.hpd.delay_on_disconnect / 10, -+ DC_HPD_TOGGLE_FILT_CNTL, -+ DC_HPD_DISCONNECT_INT_DELAY); -+ -+ dal_write_reg( -+ ptr->ctx, -+ pin->addr.DC_HPD_TOGGLE_FILT_CNTL, -+ value); -+ -+ } -+ -+ return GPIO_RESULT_OK; -+} -+ -+static const struct hw_gpio_pin_funcs funcs = { -+ .destroy = destroy, -+ .open = dal_hw_gpio_open, -+ .get_value = get_value, -+ .set_value = dal_hw_gpio_set_value, -+ .set_config = set_config, -+ .change_mode = dal_hw_gpio_change_mode, -+ .close = dal_hw_gpio_close, -+}; -+ -+static bool construct( -+ struct hw_hpd_dce110 *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ const struct hw_gpio_generic_dce110_init *init; -+ -+ if (id != GPIO_ID_HPD) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (!dal_hw_hpd_construct(&pin->base, id, en, ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ pin->base.base.base.funcs = &funcs; -+ -+ init = hw_gpio_generic_dce110_init + en; -+ -+ pin->base.base.pin_reg = init->hw_gpio_data_reg; -+ -+ pin->addr = init->addr; -+ -+ return true; -+} -+ -+struct hw_gpio_pin *dal_hw_hpd_dce110_create( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ struct hw_hpd_dce110 *pin = dc_service_alloc(ctx, sizeof(struct hw_hpd_dce110)); -+ -+ if (!pin) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(pin, id, en, ctx)) -+ return &pin->base.base.base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(ctx, pin); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h -new file mode 100644 -index 0000000..d032f4b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_HPD_DCE110_H__ -+#define __DAL_HW_HPD_DCE110_H__ -+ -+struct hw_hpd_dce110_addr { -+ uint32_t DC_HPD_INT_STATUS; -+ uint32_t DC_HPD_TOGGLE_FILT_CNTL; -+}; -+ -+struct hw_hpd_dce110 { -+ struct hw_hpd base; -+ struct hw_hpd_dce110_addr addr; -+}; -+ -+#define HPD_DCE110_FROM_BASE(hpd_base) \ -+ container_of((HW_HPD_FROM_BASE(hpd_base)), struct hw_hpd_dce110, base) -+ -+struct hw_gpio_pin *dal_hw_hpd_dce110_create( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ -+#endif /*__DAL_HW_HPD_DCE110_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c -new file mode 100644 -index 0000000..05ac0b2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c -@@ -0,0 +1,440 @@ -+/* -+ * 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 "dal_services.h" -+#include "include/gpio_types.h" -+#include "../hw_translate.h" -+ -+/* -+ * Header of this unit -+ */ -+#include "hw_translate_dce110.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+#include "../hw_gpio_pin.h" -+#include "../hw_dvo.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) { -+ /* DVO */ -+ case mmDC_GPIO_DVODATA_A: -+ switch (mask) { -+ case BUNDLE_A_MASK: -+ *id = GPIO_ID_DVO12; -+ *en = GPIO_DVO12_A; -+ return true; -+ case BUNDLE_B_MASK: -+ *id = GPIO_ID_DVO12; -+ *en = GPIO_DVO12_B; -+ return true; -+ case DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A_MASK: -+ *id = GPIO_ID_DVO24; -+ *en = 0; -+ return true; -+ default: -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ break; -+ /* 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_DVO12: -+ info->offset = mmDC_GPIO_DVODATA_A; -+ switch (en) { -+ case GPIO_DVO12_A: -+ info->mask = BUNDLE_A_MASK; -+ break; -+ case GPIO_DVO12_B: -+ info->mask = BUNDLE_B_MASK; -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ result = false; -+ } -+ break; -+ 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_DVO24: -+ info->offset = mmDC_GPIO_DVODATA_A; -+ info->mask = DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A_MASK; -+ break; -+ case GPIO_ID_DVO1: -+ case GPIO_ID_VIP_PAD: -+ default: -+ ASSERT_CRITICAL(false); -+ result = false; -+ } -+ -+ if (result) { -+ info->offset_y = info->offset + 2; -+ info->offset_en = info->offset + 1; -+ info->offset_mask = info->offset - 1; -+ -+ info->mask_y = info->mask; -+ info->mask_en = info->mask; -+ info->mask_mask = info->mask; -+ } -+ -+ return result; -+} -+ -+/* function table */ -+static const struct hw_translate_funcs funcs = { -+ .offset_to_id = offset_to_id, -+ .id_to_offset = id_to_offset, -+}; -+ -+/* -+ * dal_hw_translate_dce110_init -+ * -+ * @brief -+ * Initialize Hw translate function pointers. -+ * -+ * @param -+ * struct hw_translate *tr - [out] struct of function pointers -+ * -+ */ -+void dal_hw_translate_dce110_init(struct hw_translate *tr) -+{ -+ tr->funcs = &funcs; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h -new file mode 100644 -index 0000000..4d16e09 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2013-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_TRANSLATE_DCE110_H__ -+#define __DAL_HW_TRANSLATE_DCE110_H__ -+ -+struct hw_translate; -+ -+/* Initialize Hw translate function pointers */ -+void dal_hw_translate_dce110_init(struct hw_translate *tr); -+ -+#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c -new file mode 100644 -index 0000000..548b1cf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c -@@ -0,0 +1,290 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/gpio_interface.h" -+#include "include/ddc_interface.h" -+#include "include/gpio_service_interface.h" -+#include "hw_gpio_pin.h" -+#include "hw_translate.h" -+#include "hw_factory.h" -+#include "gpio_service.h" -+#include "gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "ddc.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+enum gpio_result dal_ddc_open( -+ struct ddc *ddc, -+ enum gpio_mode mode, -+ enum gpio_ddc_config_type config_type) -+{ -+ enum gpio_result result; -+ -+ struct gpio_ddc_open_options data_options; -+ struct gpio_ddc_open_options clock_options; -+ struct gpio_config_data config_data; -+ -+ result = dal_gpio_open_ex(ddc->pin_data, mode, &data_options); -+ -+ if (result != GPIO_RESULT_OK) { -+ BREAK_TO_DEBUGGER(); -+ return result; -+ } -+ -+ result = dal_gpio_open_ex(ddc->pin_clock, mode, &clock_options); -+ -+ if (result != GPIO_RESULT_OK) { -+ BREAK_TO_DEBUGGER(); -+ goto failure; -+ } -+ -+ /* DDC clock and data pins should belong -+ * to the same DDC block id, -+ * we use the data pin to set the pad mode. */ -+ -+ if (mode == GPIO_MODE_INPUT) -+ /* this is from detect_sink_type, -+ * we need extra delay there */ -+ config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; -+ else -+ config_data.type = GPIO_CONFIG_TYPE_DDC; -+ -+ config_data.config.ddc.type = config_type; -+ config_data.config.ddc.data_en_bit_present = -+ data_options.en_bit_present; -+ config_data.config.ddc.clock_en_bit_present = -+ clock_options.en_bit_present; -+ -+ result = dal_gpio_set_config(ddc->pin_data, &config_data); -+ -+ if (result == GPIO_RESULT_OK) -+ return result; -+ -+ BREAK_TO_DEBUGGER(); -+ -+ dal_gpio_close(ddc->pin_clock); -+ -+failure: -+ dal_gpio_close(ddc->pin_data); -+ -+ return result; -+} -+ -+enum gpio_result dal_ddc_get_clock( -+ const struct ddc *ddc, -+ uint32_t *value) -+{ -+ return dal_gpio_get_value(ddc->pin_clock, value); -+} -+ -+enum gpio_result dal_ddc_set_clock( -+ const struct ddc *ddc, -+ uint32_t value) -+{ -+ return dal_gpio_set_value(ddc->pin_clock, value); -+} -+ -+enum gpio_result dal_ddc_get_data( -+ const struct ddc *ddc, -+ uint32_t *value) -+{ -+ return dal_gpio_get_value(ddc->pin_data, value); -+} -+ -+enum gpio_result dal_ddc_set_data( -+ const struct ddc *ddc, -+ uint32_t value) -+{ -+ return dal_gpio_set_value(ddc->pin_data, value); -+} -+ -+enum gpio_result dal_ddc_change_mode( -+ struct ddc *ddc, -+ enum gpio_mode mode) -+{ -+ enum gpio_result result; -+ -+ enum gpio_mode original_mode = -+ dal_gpio_get_mode(ddc->pin_data); -+ -+ result = dal_gpio_change_mode(ddc->pin_data, mode); -+ -+ /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR -+ * in case of failures; -+ * set_mode() is so that, in case of failure, -+ * we must explicitly set original mode */ -+ -+ if (result != GPIO_RESULT_OK) -+ goto failure; -+ -+ result = dal_gpio_change_mode(ddc->pin_clock, mode); -+ -+ if (result == GPIO_RESULT_OK) -+ return result; -+ -+ dal_gpio_change_mode(ddc->pin_clock, original_mode); -+ -+failure: -+ dal_gpio_change_mode(ddc->pin_data, original_mode); -+ -+ return result; -+} -+ -+bool dal_ddc_is_hw_supported( -+ const struct ddc *ddc) -+{ -+ return ddc->hw_info.hw_supported; -+} -+ -+enum gpio_ddc_line dal_ddc_get_line( -+ const struct ddc *ddc) -+{ -+ return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data); -+} -+ -+bool dal_ddc_check_line_aborted( -+ const struct ddc *self) -+{ -+ /* No arbitration with VBIOS is performed since DCE 6.0 */ -+ -+ return false; -+} -+ -+enum gpio_result dal_ddc_set_config( -+ struct ddc *ddc, -+ enum gpio_ddc_config_type config_type) -+{ -+ struct gpio_config_data config_data; -+ -+ config_data.type = GPIO_CONFIG_TYPE_DDC; -+ -+ config_data.config.ddc.type = config_type; -+ config_data.config.ddc.data_en_bit_present = false; -+ config_data.config.ddc.clock_en_bit_present = false; -+ -+ return dal_gpio_set_config(ddc->pin_data, &config_data); -+} -+ -+void dal_ddc_close( -+ struct ddc *ddc) -+{ -+ dal_gpio_close(ddc->pin_clock); -+ dal_gpio_close(ddc->pin_data); -+} -+ -+/* -+ * @brief -+ * Creation and destruction -+ */ -+ -+struct ddc *dal_gpio_create_ddc( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ struct gpio_ddc_hw_info *info) -+{ -+ enum gpio_id id; -+ uint32_t en; -+ struct ddc *ddc; -+ -+ if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) -+ return NULL; -+ -+ ddc = dc_service_alloc(service->ctx, sizeof(struct ddc)); -+ -+ if (!ddc) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ ddc->pin_data = dal_gpio_service_create_gpio_ex( -+ service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); -+ -+ if (!ddc->pin_data) { -+ BREAK_TO_DEBUGGER(); -+ goto failure_1; -+ } -+ -+ ddc->pin_clock = dal_gpio_service_create_gpio_ex( -+ service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); -+ -+ if (!ddc->pin_clock) { -+ BREAK_TO_DEBUGGER(); -+ goto failure_2; -+ } -+ -+ ddc->hw_info = *info; -+ -+ ddc->ctx = service->ctx; -+ -+ return ddc; -+ -+failure_2: -+ dal_gpio_service_destroy_gpio(&ddc->pin_data); -+ -+failure_1: -+ dc_service_free(service->ctx, ddc); -+ -+ return NULL; -+} -+ -+static void destruct(struct ddc *ddc) -+{ -+ dal_ddc_close(ddc); -+ dal_gpio_service_destroy_gpio(&ddc->pin_data); -+ dal_gpio_service_destroy_gpio(&ddc->pin_clock); -+ -+} -+ -+void dal_gpio_destroy_ddc( -+ struct ddc **ddc) -+{ -+ if (!ddc || !*ddc) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ destruct(*ddc); -+ dc_service_free((*ddc)->ctx, *ddc); -+ -+ *ddc = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h -new file mode 100644 -index 0000000..2631571 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h -@@ -0,0 +1,45 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DDC_H__ -+#define __DAL_DDC_H__ -+ -+struct ddc { -+ struct gpio *pin_data; -+ struct gpio *pin_clock; -+ struct gpio_ddc_hw_info hw_info; -+ struct dc_context *ctx; -+}; -+ -+struct ddc *dal_gpio_create_ddc( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ struct gpio_ddc_hw_info *info); -+ -+void dal_gpio_destroy_ddc( -+ struct ddc **ddc); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dvo.c b/drivers/gpu/drm/amd/dal/dc/gpio/dvo.c -new file mode 100644 -index 0000000..a237d25 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dvo.c -@@ -0,0 +1,138 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_interface.h" -+#include "include/dvo_interface.h" -+#include "include/gpio_service_interface.h" -+#include "hw_gpio_pin.h" -+#include "hw_translate.h" -+#include "hw_factory.h" -+#include "gpio_service.h" -+#include "gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "dvo.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+enum gpio_result dal_dvo_open( -+ struct dvo *dvo, -+ enum gpio_mode mode) -+{ -+ return dal_gpio_open(dvo->pin, mode); -+} -+ -+enum gpio_result dal_dvo_get_value( -+ const struct dvo *dvo, -+ uint32_t *value) -+{ -+ return dal_gpio_get_value(dvo->pin, value); -+} -+ -+enum gpio_result dal_dvo_set_value( -+ const struct dvo *dvo, -+ uint32_t value) -+{ -+ return dal_gpio_set_value(dvo->pin, value); -+} -+ -+void dal_dvo_close( -+ struct dvo *dvo) -+{ -+ dal_gpio_close(dvo->pin); -+} -+ -+/* -+ * @brief -+ * Creation and destruction -+ */ -+ -+struct dvo *dal_dvo_create( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ struct dvo *dvo; -+ -+ switch (id) { -+ case GPIO_ID_DVO12: -+ if ((en < GPIO_DVO12_MIN) || (en > GPIO_DVO12_MAX)) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ break; -+ case GPIO_ID_DVO24: -+ if ((en < GPIO_DVO24_MIN) || (en > GPIO_DVO24_MAX)) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ dvo = dc_service_alloc(service->ctx, sizeof(struct dvo)); -+ -+ if (!dvo) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ dvo->pin = NULL; -+ dvo->ctx = service->ctx; -+ -+ return dvo; -+} -+ -+void dal_dvo_destroy( -+ struct dvo **dvo) -+{ -+ if (!dvo || !*dvo) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ dal_dvo_close(*dvo); -+ -+ dc_service_free((*dvo)->ctx, *dvo); -+ -+ *dvo = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dvo.h b/drivers/gpu/drm/amd/dal/dc/gpio/dvo.h -new file mode 100644 -index 0000000..0d98b51 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dvo.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_DVO_H__ -+#define __DAL_DVO_H__ -+ -+struct dvo { -+ struct gpio *pin; -+ struct dc_context *ctx; -+}; -+ -+struct dvo *dal_dvo_create( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en); -+ -+void dal_dvo_destroy( -+ struct dvo **dvo); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h -new file mode 100644 -index 0000000..7fcbb69 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h -@@ -0,0 +1,48 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GPIO_H__ -+#define __DAL_GPIO_H__ -+ -+struct gpio { -+ struct gpio_service *service; -+ struct hw_gpio_pin *pin; -+ enum gpio_id id; -+ uint32_t en; -+ enum gpio_mode mode; -+ /* when GPIO comes from VBIOS, it has defined output state */ -+ enum gpio_pin_output_state output_state; -+}; -+ -+struct gpio *dal_gpio_create( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_pin_output_state output_state); -+ -+void dal_gpio_destroy( -+ struct gpio **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c -new file mode 100644 -index 0000000..6115f59 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c -@@ -0,0 +1,279 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/gpio_interface.h" -+#include "include/gpio_service_interface.h" -+#include "hw_gpio_pin.h" -+#include "hw_translate.h" -+#include "hw_factory.h" -+#include "gpio_service.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "gpio.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+/* -+ * @brief -+ * Public API -+ */ -+ -+enum gpio_result dal_gpio_open( -+ struct gpio *gpio, -+ enum gpio_mode mode) -+{ -+ return dal_gpio_open_ex(gpio, mode, NULL); -+} -+ -+enum gpio_result dal_gpio_open_ex( -+ struct gpio *gpio, -+ enum gpio_mode mode, -+ void *options) -+{ -+ if (gpio->pin) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_ALREADY_OPENED; -+ } -+ -+ gpio->mode = mode; -+ -+ return dal_gpio_service_open( -+ gpio->service, gpio->id, gpio->en, mode, options, &gpio->pin); -+} -+ -+enum gpio_result dal_gpio_get_value( -+ const struct gpio *gpio, -+ uint32_t *value) -+{ -+ if (!gpio->pin) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_NULL_HANDLE; -+ } -+ -+ return gpio->pin->funcs->get_value(gpio->pin, value); -+} -+ -+enum gpio_result dal_gpio_set_value( -+ const struct gpio *gpio, -+ uint32_t value) -+{ -+ if (!gpio->pin) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_NULL_HANDLE; -+ } -+ -+ return gpio->pin->funcs->set_value(gpio->pin, value); -+} -+ -+enum gpio_mode dal_gpio_get_mode( -+ const struct gpio *gpio) -+{ -+ return gpio->mode; -+} -+ -+enum gpio_result dal_gpio_change_mode( -+ struct gpio *gpio, -+ enum gpio_mode mode) -+{ -+ if (!gpio->pin) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_NULL_HANDLE; -+ } -+ -+ return gpio->pin->funcs->change_mode(gpio->pin, mode); -+} -+ -+enum gpio_id dal_gpio_get_id( -+ const struct gpio *gpio) -+{ -+ return gpio->id; -+} -+ -+uint32_t dal_gpio_get_enum( -+ const struct gpio *gpio) -+{ -+ return gpio->en; -+} -+ -+enum gpio_result dal_gpio_set_config( -+ struct gpio *gpio, -+ const struct gpio_config_data *config_data) -+{ -+ if (!gpio->pin) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_NULL_HANDLE; -+ } -+ -+ return gpio->pin->funcs->set_config(gpio->pin, config_data); -+} -+ -+enum gpio_result dal_gpio_get_pin_info( -+ const struct gpio *gpio, -+ struct gpio_pin_info *pin_info) -+{ -+ return gpio->service->translate.funcs->id_to_offset( -+ gpio->id, gpio->en, pin_info) ? -+ GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA; -+} -+ -+enum sync_source dal_gpio_get_sync_source( -+ const struct gpio *gpio) -+{ -+ switch (gpio->id) { -+ case GPIO_ID_GENERIC: -+ switch (gpio->en) { -+ case GPIO_GENERIC_A: -+ return SYNC_SOURCE_IO_GENERIC_A; -+ case GPIO_GENERIC_B: -+ return SYNC_SOURCE_IO_GENERIC_B; -+ case GPIO_GENERIC_C: -+ return SYNC_SOURCE_IO_GENERIC_C; -+ case GPIO_GENERIC_D: -+ return SYNC_SOURCE_IO_GENERIC_D; -+ case GPIO_GENERIC_E: -+ return SYNC_SOURCE_IO_GENERIC_E; -+ case GPIO_GENERIC_F: -+ return SYNC_SOURCE_IO_GENERIC_F; -+ default: -+ return SYNC_SOURCE_NONE; -+ } -+ break; -+ case GPIO_ID_SYNC: -+ switch (gpio->en) { -+ case GPIO_SYNC_HSYNC_A: -+ return SYNC_SOURCE_IO_HSYNC_A; -+ case GPIO_SYNC_VSYNC_A: -+ return SYNC_SOURCE_IO_VSYNC_A; -+ case GPIO_SYNC_HSYNC_B: -+ return SYNC_SOURCE_IO_HSYNC_B; -+ case GPIO_SYNC_VSYNC_B: -+ return SYNC_SOURCE_IO_VSYNC_B; -+ default: -+ return SYNC_SOURCE_NONE; -+ } -+ break; -+ case GPIO_ID_HPD: -+ switch (gpio->en) { -+ case GPIO_HPD_1: -+ return SYNC_SOURCE_IO_HPD1; -+ case GPIO_HPD_2: -+ return SYNC_SOURCE_IO_HPD2; -+ default: -+ return SYNC_SOURCE_NONE; -+ } -+ break; -+ case GPIO_ID_GSL: -+ switch (gpio->en) { -+ case GPIO_GSL_GENLOCK_CLOCK: -+ return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK; -+ case GPIO_GSL_GENLOCK_VSYNC: -+ return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC; -+ case GPIO_GSL_SWAPLOCK_A: -+ return SYNC_SOURCE_GSL_IO_SWAPLOCK_A; -+ case GPIO_GSL_SWAPLOCK_B: -+ return SYNC_SOURCE_GSL_IO_SWAPLOCK_B; -+ default: -+ return SYNC_SOURCE_NONE; -+ } -+ break; -+ default: -+ return SYNC_SOURCE_NONE; -+ } -+} -+ -+enum gpio_pin_output_state dal_gpio_get_output_state( -+ const struct gpio *gpio) -+{ -+ return gpio->output_state; -+} -+ -+void dal_gpio_close( -+ struct gpio *gpio) -+{ -+ if (!gpio) -+ return; -+ -+ dal_gpio_service_close(gpio->service, &gpio->pin); -+ -+ gpio->mode = GPIO_MODE_UNKNOWN; -+} -+ -+/* -+ * @brief -+ * Creation and destruction -+ */ -+ -+struct gpio *dal_gpio_create( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_pin_output_state output_state) -+{ -+ struct gpio *gpio = dc_service_alloc(service->ctx, sizeof(struct gpio)); -+ -+ if (!gpio) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ gpio->service = service; -+ gpio->pin = NULL; -+ gpio->id = id; -+ gpio->en = en; -+ gpio->mode = GPIO_MODE_UNKNOWN; -+ gpio->output_state = output_state; -+ -+ return gpio; -+} -+ -+void dal_gpio_destroy( -+ struct gpio **gpio) -+{ -+ if (!gpio || !*gpio) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ dal_gpio_close(*gpio); -+ -+ dc_service_free((*gpio)->service->ctx, *gpio); -+ -+ *gpio = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c -new file mode 100644 -index 0000000..08e046b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c -@@ -0,0 +1,470 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "dal_services.h" -+#include "include/gpio_interface.h" -+#include "include/ddc_interface.h" -+#include "include/dvo_interface.h" -+#include "include/irq_interface.h" -+#include "include/gpio_service_interface.h" -+#include "hw_translate.h" -+#include "hw_factory.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "gpio_service.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#include "hw_gpio_pin.h" -+#include "gpio.h" -+#include "dvo.h" -+#include "ddc.h" -+#include "irq.h" -+ -+/* -+ * This unit -+ */ -+ -+/* -+ * @brief -+ * Public API. -+ */ -+ -+struct gpio_service *dal_gpio_service_create( -+ enum dce_version dce_version, -+ struct dc_context *ctx) -+{ -+ struct gpio_service *service; -+ -+ uint32_t index_of_id; -+ -+ service = dc_service_alloc(ctx, sizeof(struct gpio_service)); -+ -+ if (!service) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (!dal_hw_translate_init(&service->translate, dce_version)) { -+ BREAK_TO_DEBUGGER(); -+ goto failure_1; -+ } -+ -+ if (!dal_hw_factory_init(&service->factory, dce_version)) { -+ 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 = dc_service_alloc( -+ ctx, -+ number_of_uints * sizeof(uint32_t)); -+ -+ if (!slot) { -+ BREAK_TO_DEBUGGER(); -+ goto failure_2; -+ } -+ -+ do { -+ slot[index_of_uint] = 0; -+ -+ ++index_of_uint; -+ } while (index_of_uint < number_of_uints); -+ } else -+ slot = NULL; -+ -+ service->busyness[index_of_id] = slot; -+ -+ ++index_of_id; -+ } while (index_of_id < GPIO_ID_COUNT); -+ } -+ -+ return service; -+ -+failure_2: -+ while (index_of_id) { -+ uint32_t *slot; -+ -+ --index_of_id; -+ -+ slot = service->busyness[index_of_id]; -+ -+ if (slot) -+ dc_service_free(ctx, slot); -+ }; -+ -+failure_1: -+ dc_service_free(ctx, service); -+ -+ return NULL; -+} -+ -+struct gpio *dal_gpio_service_create_gpio( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ enum gpio_pin_output_state output_state) -+{ -+ enum gpio_id id; -+ uint32_t en; -+ -+ if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ return dal_gpio_create(service, id, en, output_state); -+} -+ -+struct gpio *dal_gpio_service_create_gpio_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_pin_output_state output_state) -+{ -+ return dal_gpio_create(service, id, en, output_state); -+} -+ -+void dal_gpio_service_destroy_gpio( -+ struct gpio **gpio) -+{ -+ dal_gpio_destroy(gpio); -+} -+ -+struct ddc *dal_gpio_service_create_ddc( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ struct gpio_ddc_hw_info *info) -+{ -+ return dal_gpio_create_ddc(service, offset, mask, info); -+} -+ -+void dal_gpio_service_destroy_ddc( -+ struct ddc **ddc) -+{ -+ dal_gpio_destroy_ddc(ddc); -+} -+ -+struct dvo *dal_gpio_service_create_dvo( -+ 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)) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ return dal_dvo_create(service, id, en); -+} -+ -+struct dvo *dal_gpio_service_create_dvo_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ return dal_dvo_create(service, id, en); -+} -+ -+void dal_gpio_service_destroy_dvo( -+ struct dvo **dvo) -+{ -+ dal_dvo_destroy(dvo); -+} -+ -+struct irq *dal_gpio_service_create_irq( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask) -+{ -+ enum gpio_id id; -+ uint32_t en; -+ -+ if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ return dal_gpio_create_irq(service, id, en); -+} -+ -+struct irq *dal_gpio_service_create_irq_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ return dal_gpio_create_irq(service, id, en); -+} -+ -+void dal_gpio_service_destroy_irq( -+ struct irq **irq) -+{ -+ dal_gpio_destroy_irq(irq); -+} -+ -+void dal_gpio_service_destroy( -+ struct gpio_service **ptr) -+{ -+ if (!ptr || !*ptr) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ /* free business storage */ -+ { -+ uint32_t index_of_id = 0; -+ -+ do { -+ uint32_t *slot = (*ptr)->busyness[index_of_id]; -+ -+ if (slot) -+ dc_service_free((*ptr)->ctx, slot); -+ -+ ++index_of_id; -+ } while (index_of_id < GPIO_ID_COUNT); -+ } -+ -+ dc_service_free((*ptr)->ctx, *ptr); -+ -+ *ptr = NULL; -+} -+ -+/* -+ * @brief -+ * Private API. -+ */ -+ -+static bool is_pin_busy( -+ const struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ const uint32_t bits_per_uint = sizeof(uint32_t) << 3; -+ -+ const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); -+ -+ return 0 != (*slot & (1 << (en % bits_per_uint))); -+} -+ -+static bool is_some_pin_busy( -+ const struct gpio_service *service, -+ enum gpio_id id) -+{ -+ const uint32_t bits_per_uint = sizeof(uint32_t) << 3; -+ -+ uint32_t index_of_uint = 0; -+ -+ uint32_t number_of_uints = -+ service->factory.number_of_pins[id]; -+ -+ number_of_uints = (number_of_uints + bits_per_uint - 1) / bits_per_uint; -+ -+ while (index_of_uint < number_of_uints) { -+ if (service->busyness[id][index_of_uint]) -+ return true; -+ -+ ++index_of_uint; -+ }; -+ -+ return false; -+} -+ -+static void set_pin_busy( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ const uint32_t bits_per_uint = sizeof(uint32_t) << 3; -+ -+ service->busyness[id][en / bits_per_uint] |= -+ (1 << (en % bits_per_uint)); -+} -+ -+static void set_pin_free( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ const uint32_t bits_per_uint = sizeof(uint32_t) << 3; -+ -+ service->busyness[id][en / bits_per_uint] &= -+ ~(1 << (en % bits_per_uint)); -+} -+ -+enum gpio_result dal_gpio_service_open( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_mode mode, -+ void *options, -+ struct hw_gpio_pin **ptr) -+{ -+ struct hw_gpio_pin *pin; -+ -+ if (!service->busyness[id]) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_OPEN_FAILED; -+ } -+ -+ if (is_pin_busy(service, id, en)) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_DEVICE_BUSY; -+ } -+ -+ switch (id) { -+ case GPIO_ID_DVO1: -+ /* [anaumov] not implemented, commented with "to do" */ -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ case GPIO_ID_DVO12: -+ if (!service->busyness[GPIO_ID_DVO24]) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_OPEN_FAILED; -+ } -+ -+ if (is_some_pin_busy(service, GPIO_ID_DVO24)) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_DEVICE_BUSY; -+ } -+ -+ pin = service->factory.funcs->create_dvo( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_DVO24: -+ if (!service->busyness[GPIO_ID_DVO12]) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_OPEN_FAILED; -+ } -+ -+ if (is_some_pin_busy(service, GPIO_ID_DVO12)) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_DEVICE_BUSY; -+ } -+ -+ pin = service->factory.funcs->create_dvo( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_DDC_DATA: -+ pin = service->factory.funcs->create_ddc_data( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_DDC_CLOCK: -+ pin = service->factory.funcs->create_ddc_clock( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_GENERIC: -+ pin = service->factory.funcs->create_generic( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_HPD: -+ pin = service->factory.funcs->create_hpd( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_GPIO_PAD: -+ pin = service->factory.funcs->create_gpio_pad( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_SYNC: -+ pin = service->factory.funcs->create_sync( -+ service->ctx, id, en); -+ break; -+ case GPIO_ID_GSL: -+ pin = service->factory.funcs->create_gsl( -+ service->ctx, id, en); -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+ -+ if (!pin) { -+ ASSERT_CRITICAL(false); -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+ -+ if (!pin->funcs->open(pin, mode, options)) { -+ ASSERT_CRITICAL(false); -+ dal_gpio_service_close(service, &pin); -+ return GPIO_RESULT_OPEN_FAILED; -+ } -+ -+ set_pin_busy(service, id, en); -+ *ptr = pin; -+ return GPIO_RESULT_OK; -+} -+ -+void dal_gpio_service_close( -+ struct gpio_service *service, -+ struct hw_gpio_pin **ptr) -+{ -+ struct hw_gpio_pin *pin; -+ -+ if (!ptr) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ pin = *ptr; -+ -+ if (pin) { -+ set_pin_free(service, pin->id, pin->en); -+ -+ pin->funcs->close(pin); -+ -+ pin->funcs->destroy(ptr); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h -new file mode 100644 -index 0000000..a17c438 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h -@@ -0,0 +1,57 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GPIO_SERVICE_H__ -+#define __DAL_GPIO_SERVICE_H__ -+ -+struct hw_translate; -+struct hw_factory; -+ -+struct gpio_service { -+ struct dc_context *ctx; -+ struct hw_translate translate; -+ struct hw_factory factory; -+ /* -+ * @brief -+ * Business storage. -+ * For each member of 'enum gpio_id', -+ * store array of bits (packed into uint32_t slots), -+ * index individual bit by 'en' value */ -+ uint32_t *busyness[GPIO_ID_COUNT]; -+}; -+ -+enum gpio_result dal_gpio_service_open( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_mode mode, -+ void *options, -+ struct hw_gpio_pin **ptr); -+ -+void dal_gpio_service_close( -+ struct gpio_service *service, -+ struct hw_gpio_pin **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c -new file mode 100644 -index 0000000..0608f16 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c -@@ -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 -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "hw_gpio_pin.h" -+#include "hw_gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_ddc.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+#define FROM_HW_GPIO(ptr) \ -+ container_of((ptr), struct hw_ddc, base) -+ -+#define FROM_HW_GPIO_PIN(ptr) \ -+ FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base)) -+ -+bool dal_hw_ddc_open( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode, -+ void *options) -+{ -+ struct hw_ddc *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ uint32_t en; -+ -+ if (!options) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ /* get the EN bit before overwriting it */ -+ -+ dal_hw_gpio_get_reg_value( -+ ptr->ctx, -+ &pin->base.pin_reg.DC_GPIO_DATA_EN, -+ &en); -+ -+ ((struct gpio_ddc_open_options *)options)->en_bit_present = (en != 0); -+ -+ return dal_hw_gpio_open(ptr, mode, options); -+} -+ -+bool dal_hw_ddc_construct( -+ struct hw_ddc *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) -+ return false; -+ -+ pin->mask.DC_GPIO_DDC_MASK_MASK = 0; -+ pin->mask.DC_GPIO_DDC_PD_EN_MASK = 0; -+ pin->mask.DC_GPIO_DDC_RECV_MASK = 0; -+ pin->mask.AUX_PAD_MODE_MASK = 0; -+ pin->mask.AUX_POL_MASK = 0; -+ pin->mask.DC_GPIO_DDCCLK_STR_MASK = 0; -+ -+ return true; -+} -+ -+void dal_hw_ddc_destruct( -+ struct hw_ddc *pin) -+{ -+ dal_hw_gpio_destruct(&pin->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h -new file mode 100644 -index 0000000..a3a727c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h -@@ -0,0 +1,60 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_DDC_H__ -+#define __DAL_HW_DDC_H__ -+ -+struct hw_ddc_mask { -+ uint32_t DC_GPIO_DDC_MASK_MASK; -+ uint32_t DC_GPIO_DDC_PD_EN_MASK; -+ uint32_t DC_GPIO_DDC_RECV_MASK; -+ uint32_t AUX_PAD_MODE_MASK; -+ uint32_t AUX_POL_MASK; -+ uint32_t DC_GPIO_DDCCLK_STR_MASK; -+}; -+ -+struct hw_ddc { -+ struct hw_gpio base; -+ struct hw_ddc_mask mask; -+}; -+ -+#define HW_DDC_FROM_BASE(hw_gpio) \ -+ container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base) -+ -+bool dal_hw_ddc_construct( -+ struct hw_ddc *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+void dal_hw_ddc_destruct( -+ struct hw_ddc *pin); -+ -+bool dal_hw_ddc_open( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode, -+ void *options); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.c -new file mode 100644 -index 0000000..a5a07f0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.c -@@ -0,0 +1,318 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "hw_gpio_pin.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_dvo.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+#define FROM_HW_GPIO_PIN(ptr) \ -+ container_of((ptr), struct hw_dvo, base) -+ -+static void store_dvo_registers( -+ struct hw_dvo *pin) -+{ -+ pin->store.dvo_mask = dal_read_reg( -+ pin->base.ctx, pin->addr.DC_GPIO_DVODATA_MASK); -+ pin->store.dvo_en = dal_read_reg( -+ pin->base.ctx, pin->addr.DC_GPIO_DVODATA_EN); -+ pin->store.dvo_data_a = dal_read_reg( -+ pin->base.ctx, pin->addr.DC_GPIO_DVODATA_A); -+} -+ -+static void restore_dvo_registers( -+ struct hw_dvo *pin) -+{ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_MASK; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ data &= ~pin->dvo_mask; -+ data |= pin->store.dvo_mask & pin->dvo_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+ } -+ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_EN; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ data &= ~pin->dvo_mask; -+ data |= pin->store.dvo_en & pin->dvo_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+ } -+ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_A; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ data &= ~pin->dvo_mask; -+ data |= pin->store.dvo_data_a & pin->dvo_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+ } -+} -+ -+static void program_dvo( -+ struct hw_dvo *pin, -+ bool output) -+{ -+ /* Turn on Mask bits for the requested channel, -+ * this will enable the channel for software control. */ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_MASK; -+ -+ uint32_t mask = dal_read_reg(pin->base.ctx, addr); -+ -+ uint32_t data = pin->dvo_mask | mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+ } -+ -+ /* Turn off/on the Enable bits on the requested channel, -+ * this will set it to Input/Output mode. */ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_EN; -+ -+ uint32_t enable = dal_read_reg(pin->base.ctx, addr); -+ -+ uint32_t data = output ? -+ (pin->dvo_mask | enable) : -+ (~pin->dvo_mask & enable); -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+ } -+} -+ -+static void program_dvo_strength( -+ struct hw_dvo *pin) -+{ -+ const uint32_t addr = pin->addr.DVO_STRENGTH_CONTROL; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ data &= ~pin->dvo_strength_mask; -+ data |= pin->dvo_strength & pin->dvo_strength_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+} -+ -+static void disable_on_chip_terminators( -+ struct hw_dvo *pin) -+{ -+ const uint32_t addr = pin->addr.D1CRTC_MVP_CONTROL1; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ pin->store.mvp_terminator_state = (data & pin->mvp_termination_mask); -+ -+ data &= ~pin->mvp_termination_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+} -+ -+static void restore_on_chip_terminators( -+ struct hw_dvo *pin) -+{ -+ const uint32_t addr = pin->addr.D1CRTC_MVP_CONTROL1; -+ -+ uint32_t data = dal_read_reg(pin->base.ctx, addr); -+ -+ data &= ~pin->mvp_termination_mask; -+ -+ if (pin->store.mvp_terminator_state) -+ data |= pin->mvp_termination_mask; -+ -+ dal_write_reg(pin->base.ctx, addr, data); -+} -+ -+bool dal_hw_dvo_open( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode, -+ void *options) -+{ -+ struct hw_dvo *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ store_dvo_registers(pin); -+ -+ ptr->mode = mode; -+ -+ switch (mode) { -+ case GPIO_MODE_INPUT: -+ program_dvo_strength(pin); -+ disable_on_chip_terminators(pin); -+ program_dvo(pin, false); -+ -+ ptr->opened = true; -+ break; -+ case GPIO_MODE_OUTPUT: -+ program_dvo_strength(pin); -+ disable_on_chip_terminators(pin); -+ program_dvo(pin, true); -+ -+ ptr->opened = true; -+ break; -+ default: -+ /* unsupported mode */ -+ BREAK_TO_DEBUGGER(); -+ -+ ptr->opened = false; -+ } -+ -+ return ptr->opened; -+} -+ -+enum gpio_result dal_hw_dvo_get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value) -+{ -+ const struct hw_dvo *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ if (ptr->mode != GPIO_MODE_INPUT) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ *value = dal_read_reg(ptr->ctx, pin->addr.DC_GPIO_DVODATA_Y); -+ -+ *value &= pin->dvo_mask; -+ *value >>= pin->dvo_shift; -+ -+ return GPIO_RESULT_OK; -+} -+ -+enum gpio_result dal_hw_dvo_set_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t value) -+{ -+ const struct hw_dvo *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ uint32_t masked_value; -+ -+ if (ptr->mode != GPIO_MODE_OUTPUT) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+ -+ /* Ensure there is no overflow of the value written. -+ * Value cannot be more than 12 bits for a 12-bit channel. */ -+ -+ masked_value = value << pin->dvo_shift; -+ -+ if (masked_value != (masked_value & pin->dvo_mask)) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_INVALID_DATA; -+ } -+ -+ masked_value &= pin->dvo_mask; -+ -+ /* read the DataA register -+ * mask off the Bundle that we want to write to -+ * or the data into the register */ -+ { -+ const uint32_t addr = pin->addr.DC_GPIO_DVODATA_A; -+ -+ uint32_t data = dal_read_reg(ptr->ctx, addr); -+ -+ data &= ~pin->dvo_mask; -+ data |= masked_value; -+ -+ dal_write_reg(ptr->ctx, addr, data); -+ } -+ -+ return GPIO_RESULT_OK; -+} -+ -+void dal_hw_dvo_close( -+ struct hw_gpio_pin *ptr) -+{ -+ struct hw_dvo *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ restore_dvo_registers(pin); -+ restore_on_chip_terminators(pin); -+ -+ ptr->mode = GPIO_MODE_UNKNOWN; -+ -+ ptr->opened = false; -+} -+ -+bool dal_hw_dvo_construct( -+ struct hw_dvo *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ struct hw_gpio_pin *base = &pin->base; -+ -+ if (!dal_hw_gpio_pin_construct(base, id, en, ctx)) -+ return false; -+ -+ pin->addr.DC_GPIO_DVODATA_MASK = 0; -+ pin->addr.DC_GPIO_DVODATA_EN = 0; -+ pin->addr.DC_GPIO_DVODATA_A = 0; -+ pin->addr.DC_GPIO_DVODATA_Y = 0; -+ pin->addr.DVO_STRENGTH_CONTROL = 0; -+ pin->addr.D1CRTC_MVP_CONTROL1 = 0; -+ -+ pin->dvo_mask = 0; -+ pin->dvo_shift = 0; -+ pin->dvo_strength_mask = 0; -+ pin->mvp_termination_mask = 0; -+ -+ pin->dvo_strength = 0; -+ -+ pin->store.dvo_mask = 0; -+ pin->store.dvo_en = 0; -+ pin->store.dvo_data_a = 0; -+ pin->store.mvp_terminator_state = false; -+ -+ return true; -+} -+ -+void dal_hw_dvo_destruct( -+ struct hw_dvo *pin) -+{ -+ dal_hw_gpio_pin_destruct(&pin->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.h -new file mode 100644 -index 0000000..5a120c2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_dvo.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_HW_DVO_H__ -+#define __DAL_HW_DVO_H__ -+ -+#define BUNDLE_A_SHIFT 12L -+#define BUNDLE_B_SHIFT 0L -+ -+struct hw_dvo { -+ struct hw_gpio_pin base; -+ /* Register indices are represented by member variables, -+ * are to be filled in by derived classes. -+ * These members permit the use of common code -+ * for programming registers where the sequence is the same -+ * but the register sets are different */ -+ struct { -+ uint32_t DC_GPIO_DVODATA_MASK; -+ uint32_t DC_GPIO_DVODATA_EN; -+ uint32_t DC_GPIO_DVODATA_A; -+ uint32_t DC_GPIO_DVODATA_Y; -+ uint32_t DVO_STRENGTH_CONTROL; -+ uint32_t D1CRTC_MVP_CONTROL1; -+ } addr; -+ -+ /* Mask and shift differentiates between Bundle A and Bundle B */ -+ uint32_t dvo_mask; -+ uint32_t dvo_shift; -+ uint32_t dvo_strength_mask; -+ uint32_t mvp_termination_mask; -+ -+ uint32_t dvo_strength; -+ -+ struct { -+ uint32_t dvo_mask; -+ uint32_t dvo_en; -+ uint32_t dvo_data_a; -+ bool mvp_terminator_state; -+ } store; -+}; -+ -+bool dal_hw_dvo_construct( -+ struct hw_dvo *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+void dal_hw_dvo_destruct( -+ struct hw_dvo *pin); -+ -+bool dal_hw_dvo_open( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode, -+ void *options); -+ -+enum gpio_result dal_hw_dvo_get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value); -+ -+enum gpio_result dal_hw_dvo_set_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t value); -+ -+void dal_hw_dvo_close( -+ struct hw_gpio_pin *ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c -new file mode 100644 -index 0000000..d1b6b7e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c -@@ -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 -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_factory.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/hw_factory_dce110.h" -+#endif -+/* -+ * This unit -+ */ -+ -+bool dal_hw_factory_init( -+ struct hw_factory *factory, -+ enum dce_version dce_version) -+{ -+ switch (dce_version) { -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ dal_hw_factory_dce110_init(factory); -+ return true; -+#endif -+ default: -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+} -+ -+void dal_hw_factory_destroy( -+ struct dc_context *ctx, -+ struct hw_factory **factory) -+{ -+ if (!factory || !*factory) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ dc_service_free(ctx, *factory); -+ -+ *factory = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h -new file mode 100644 -index 0000000..f16678c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/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_factory { -+ uint32_t number_of_pins[GPIO_ID_COUNT]; -+ -+ const struct hw_factory_funcs { -+ struct hw_gpio_pin *(*create_dvo)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_ddc_data)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_ddc_clock)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_generic)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_hpd)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_gpio_pad)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_sync)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ struct hw_gpio_pin *(*create_gsl)( -+ struct dc_context *ctx, -+ enum gpio_id id, -+ uint32_t en); -+ } *funcs; -+}; -+ -+bool dal_hw_factory_init( -+ struct hw_factory *factory, -+ enum dce_version dce_version); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c -new file mode 100644 -index 0000000..2964d5d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c -@@ -0,0 +1,408 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "hw_gpio_pin.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_gpio.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+enum gpio_result dal_hw_gpio_get_reg_value( -+ struct dc_context *ctx, -+ const struct addr_mask *reg, -+ uint32_t *value) -+{ -+ *value = dal_read_reg(ctx, reg->addr); -+ -+ *value &= reg->mask; -+ -+ return GPIO_RESULT_OK; -+} -+ -+enum gpio_result dal_hw_gpio_set_reg_value( -+ struct dc_context *ctx, -+ const struct addr_mask *reg, -+ uint32_t value) -+{ -+ uint32_t prev_value; -+ -+ if ((value & reg->mask) != value) { -+ BREAK_TO_DEBUGGER(); -+ return GPIO_RESULT_INVALID_DATA; -+ } -+ -+ prev_value = dal_read_reg(ctx, reg->addr); -+ -+ prev_value &= ~reg->mask; -+ prev_value |= (value & reg->mask); -+ -+ dal_write_reg(ctx, reg->addr, prev_value); -+ -+ return GPIO_RESULT_OK; -+} -+ -+uint32_t dal_hw_gpio_get_shift_from_mask( -+ uint32_t mask) -+{ -+ uint32_t result = 0; -+ -+ if (!mask) -+ return 32; -+ -+ do { -+ if ((1 << result) & mask) -+ break; -+ -+ ++result; -+ } while (result < 32); -+ -+ return result; -+} -+ -+#define FROM_HW_GPIO_PIN(ptr) \ -+ container_of((ptr), struct hw_gpio, base) -+ -+static void store_registers( -+ struct hw_gpio *pin) -+{ -+ dal_hw_gpio_get_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ &pin->store.mask); -+ dal_hw_gpio_get_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_A, -+ &pin->store.a); -+ dal_hw_gpio_get_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_EN, -+ &pin->store.en); -+ -+ if (pin->mux_supported) -+ dal_hw_gpio_get_reg_value( -+ pin->base.ctx, -+ &pin->mux_reg.GPIO_MUX_CONTROL, -+ &pin->store.mux); -+} -+ -+static void restore_registers( -+ struct hw_gpio *pin) -+{ -+ dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ pin->store.mask); -+ dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_A, -+ pin->store.a); -+ dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_EN, -+ pin->store.en); -+ -+ if (pin->mux_supported) -+ dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->mux_reg.GPIO_MUX_CONTROL, -+ pin->store.mux); -+} -+ -+bool dal_hw_gpio_open( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode, -+ void *options) -+{ -+ struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ store_registers(pin); -+ -+ ptr->opened = (pin->funcs->config_mode(pin, mode) == GPIO_RESULT_OK); -+ -+ return ptr->opened; -+} -+ -+enum gpio_result dal_hw_gpio_get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value) -+{ -+ const struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ enum gpio_result result; -+ -+ switch (ptr->mode) { -+ case GPIO_MODE_INPUT: -+ case GPIO_MODE_OUTPUT: -+ case GPIO_MODE_HARDWARE: -+ case GPIO_MODE_FAST_OUTPUT: -+ result = dal_hw_gpio_get_reg_value( -+ ptr->ctx, -+ &pin->pin_reg.DC_GPIO_DATA_Y, -+ value); -+ /* Clients does not know that the value -+ * comes from register and is shifted. */ -+ if (result == GPIO_RESULT_OK) -+ *value >>= dal_hw_gpio_get_shift_from_mask( -+ pin->pin_reg.DC_GPIO_DATA_Y.mask); -+ break; -+ default: -+ result = GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+ -+ return result; -+} -+ -+enum gpio_result dal_hw_gpio_set_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t value) -+{ -+ struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ /* This is the public interface -+ * where the input comes from client, not shifted yet -+ * (because client does not know the shifts). */ -+ -+ switch (ptr->mode) { -+ case GPIO_MODE_OUTPUT: -+ return dal_hw_gpio_set_reg_value( -+ ptr->ctx, -+ &pin->pin_reg.DC_GPIO_DATA_A, -+ value << dal_hw_gpio_get_shift_from_mask( -+ pin->pin_reg.DC_GPIO_DATA_A.mask)); -+ case GPIO_MODE_FAST_OUTPUT: -+ /* We use (EN) to faster switch (used in DDC GPIO). -+ * So (A) is grounded, output is driven by (EN = 0) -+ * to pull the line down (output == 0) and (EN=1) -+ * then output is tri-state */ -+ return dal_hw_gpio_set_reg_value( -+ ptr->ctx, -+ &pin->pin_reg.DC_GPIO_DATA_EN, -+ pin->pin_reg.DC_GPIO_DATA_EN.mask & -+ ~(value << dal_hw_gpio_get_shift_from_mask( -+ pin->pin_reg.DC_GPIO_DATA_EN.mask))); -+ default: -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+} -+ -+enum gpio_result dal_hw_gpio_change_mode( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode) -+{ -+ struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ return pin->funcs->config_mode(pin, mode); -+} -+ -+void dal_hw_gpio_close( -+ struct hw_gpio_pin *ptr) -+{ -+ struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ restore_registers(pin); -+ -+ ptr->mode = GPIO_MODE_UNKNOWN; -+ ptr->opened = false; -+} -+ -+static enum gpio_result config_mode_input( -+ struct hw_gpio *pin) -+{ -+ enum gpio_result result; -+ -+ /* turn off output enable, act as input pin; -+ * program the pin as GPIO, mask out signal driven by HW */ -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_EN, -+ 0); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ pin->pin_reg.DC_GPIO_DATA_MASK.mask); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ return GPIO_RESULT_OK; -+} -+ -+static enum gpio_result config_mode_output( -+ struct hw_gpio *pin) -+{ -+ enum gpio_result result; -+ -+ /* turn on output enable, act as output pin; -+ * program the pin as GPIO, mask out signal driven by HW */ -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_EN, -+ pin->pin_reg.DC_GPIO_DATA_EN.mask); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ pin->pin_reg.DC_GPIO_DATA_MASK.mask); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ return GPIO_RESULT_OK; -+} -+ -+static enum gpio_result config_mode_fast_output( -+ struct hw_gpio *pin) -+{ -+ enum gpio_result result; -+ -+ /* grounding the A register then use the EN register bit -+ * will have faster effect on the rise time */ -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_A, 0); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ result = dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ pin->pin_reg.DC_GPIO_DATA_MASK.mask); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ return GPIO_RESULT_OK; -+} -+ -+static enum gpio_result config_mode_hardware( -+ struct hw_gpio *pin) -+{ -+ /* program the pin as tri-state, pin is driven by HW */ -+ -+ enum gpio_result result = -+ dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ 0); -+ -+ if (result != GPIO_RESULT_OK) -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ -+ return GPIO_RESULT_OK; -+} -+ -+enum gpio_result dal_hw_gpio_config_mode( -+ struct hw_gpio *pin, -+ enum gpio_mode mode) -+{ -+ pin->base.mode = mode; -+ -+ switch (mode) { -+ case GPIO_MODE_INPUT: -+ return config_mode_input(pin); -+ case GPIO_MODE_OUTPUT: -+ return config_mode_output(pin); -+ case GPIO_MODE_FAST_OUTPUT: -+ return config_mode_fast_output(pin); -+ case GPIO_MODE_HARDWARE: -+ return config_mode_hardware(pin); -+ default: -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+ } -+} -+ -+const struct hw_gpio_funcs func = { -+ .config_mode = dal_hw_gpio_config_mode, -+}; -+ -+bool dal_hw_gpio_construct( -+ struct hw_gpio *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ struct hw_gpio_pin *base = &pin->base; -+ -+ if (!dal_hw_gpio_pin_construct(base, id, en, ctx)) -+ return false; -+ -+ pin->funcs = &func; -+ -+ pin->pin_reg.DC_GPIO_DATA_MASK.addr = 0; -+ pin->pin_reg.DC_GPIO_DATA_MASK.mask = 0; -+ pin->pin_reg.DC_GPIO_DATA_A.addr = 0; -+ pin->pin_reg.DC_GPIO_DATA_A.mask = 0; -+ pin->pin_reg.DC_GPIO_DATA_EN.addr = 0; -+ pin->pin_reg.DC_GPIO_DATA_EN.mask = 0; -+ pin->pin_reg.DC_GPIO_DATA_Y.addr = 0; -+ pin->pin_reg.DC_GPIO_DATA_Y.mask = 0; -+ pin->mux_reg.GPIO_MUX_CONTROL.addr = 0; -+ pin->mux_reg.GPIO_MUX_CONTROL.mask = 0; -+ pin->mux_reg.GPIO_MUX_STEREO_SEL.addr = 0; -+ pin->mux_reg.GPIO_MUX_STEREO_SEL.mask = 0; -+ -+ pin->store.mask = 0; -+ pin->store.a = 0; -+ pin->store.en = 0; -+ pin->store.mux = 0; -+ -+ pin->mux_supported = false; -+ -+ return true; -+} -+ -+void dal_hw_gpio_destruct( -+ struct hw_gpio *pin) -+{ -+ dal_hw_gpio_pin_destruct(&pin->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h -new file mode 100644 -index 0000000..44eb86e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h -@@ -0,0 +1,129 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_GPIO_H__ -+#define __DAL_HW_GPIO_H__ -+ -+struct addr_mask { -+ uint32_t addr; -+ uint32_t mask; -+}; -+ -+enum gpio_result dal_hw_gpio_get_reg_value( -+ struct dc_context *ctx, -+ const struct addr_mask *reg, -+ uint32_t *value); -+ -+enum gpio_result dal_hw_gpio_set_reg_value( -+ struct dc_context *ctx, -+ const struct addr_mask *reg, -+ uint32_t value); -+ -+uint32_t dal_hw_gpio_get_shift_from_mask( -+ uint32_t mask); -+ -+struct hw_gpio; -+ -+struct hw_gpio_funcs { -+ enum gpio_result (*config_mode)( -+ struct hw_gpio *pin, -+ enum gpio_mode mode); -+}; -+ -+/* Register indices are represented by member variables -+ * and are to be filled in by constructors of derived classes. -+ * These members permit the use of common code -+ * for programming registers, where the sequence is the same -+ * but register sets are different. -+ * Some GPIOs have HW mux which allows to choose -+ * what is the source of the signal in HW mode */ -+ -+struct hw_gpio_pin_reg { -+ struct addr_mask DC_GPIO_DATA_MASK; -+ struct addr_mask DC_GPIO_DATA_A; -+ struct addr_mask DC_GPIO_DATA_EN; -+ struct addr_mask DC_GPIO_DATA_Y; -+}; -+ -+struct hw_gpio_mux_reg { -+ struct addr_mask GPIO_MUX_CONTROL; -+ struct addr_mask GPIO_MUX_STEREO_SEL; -+}; -+ -+struct hw_gpio { -+ struct hw_gpio_pin base; -+ const struct hw_gpio_funcs *funcs; -+ struct hw_gpio_pin_reg pin_reg; -+ struct hw_gpio_mux_reg mux_reg; -+ -+ /* variables to save register value */ -+ struct { -+ uint32_t mask; -+ uint32_t a; -+ uint32_t en; -+ uint32_t mux; -+ } store; -+ -+ /* GPIO MUX support */ -+ bool mux_supported; -+}; -+ -+#define HW_GPIO_FROM_BASE(hw_gpio_pin) \ -+ container_of((hw_gpio_pin), struct hw_gpio, base) -+ -+bool dal_hw_gpio_construct( -+ struct hw_gpio *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+bool dal_hw_gpio_open( -+ struct hw_gpio_pin *pin, -+ enum gpio_mode mode, -+ void *options); -+ -+enum gpio_result dal_hw_gpio_get_value( -+ const struct hw_gpio_pin *pin, -+ uint32_t *value); -+ -+enum gpio_result dal_hw_gpio_config_mode( -+ struct hw_gpio *pin, -+ enum gpio_mode mode); -+ -+void dal_hw_gpio_destruct( -+ struct hw_gpio *pin); -+ -+enum gpio_result dal_hw_gpio_set_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t value); -+ -+enum gpio_result dal_hw_gpio_change_mode( -+ struct hw_gpio_pin *ptr, -+ enum gpio_mode mode); -+ -+void dal_hw_gpio_close( -+ struct hw_gpio_pin *ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c -new file mode 100644 -index 0000000..057c439 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.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 "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "hw_gpio_pin.h" -+#include "hw_gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_gpio_pad.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+#define FROM_HW_GPIO(ptr) \ -+ container_of((ptr), struct hw_gpio_pad, base) -+ -+#define FROM_HW_GPIO_PIN(ptr) \ -+ FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base)) -+ -+enum gpio_result dal_hw_gpio_pad_get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value) -+{ -+ const struct hw_gpio_pad *pin = FROM_HW_GPIO_PIN(ptr); -+ -+ if (ptr->mode == GPIO_MODE_INTERRUPT) -+ /* in Interrupt mode, ask for interrupt status bit */ -+ return dal_hw_gpio_get_reg_value( -+ ptr->ctx, -+ &pin->gpiopad_int_status, -+ value); -+ else -+ /* for any mode other than Interrupt, -+ * gpio_pad operates as normal GPIO */ -+ return dal_hw_gpio_get_value(ptr, value); -+} -+ -+bool dal_hw_gpio_pad_construct( -+ struct hw_gpio_pad *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) -+ return false; -+ -+ pin->gpiopad_int_status.addr = 0; -+ pin->gpiopad_int_status.mask = 0; -+ -+ return true; -+} -+ -+void dal_hw_gpio_pad_destruct( -+ struct hw_gpio_pad *pin) -+{ -+ dal_hw_gpio_destruct(&pin->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h -new file mode 100644 -index 0000000..34b470a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_GPIO_PAD_H__ -+#define __DAL_HW_GPIO_PAD_H__ -+ -+struct hw_gpio_pad { -+ struct hw_gpio base; -+ struct addr_mask gpiopad_int_status; -+}; -+ -+bool dal_hw_gpio_pad_construct( -+ struct hw_gpio_pad *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+void dal_hw_gpio_pad_destruct( -+ struct hw_gpio_pad *pin); -+ -+enum gpio_result dal_hw_gpio_pad_get_value( -+ const struct hw_gpio_pin *ptr, -+ uint32_t *value); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c -new file mode 100644 -index 0000000..4ab1848 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c -@@ -0,0 +1,86 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_gpio_pin.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+enum gpio_result dal_hw_gpio_pin_set_config( -+ struct hw_gpio_pin *pin, -+ const struct gpio_config_data *config_data) -+{ -+ /* Attention! -+ * You must override this method in derived class */ -+ -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+} -+ -+enum gpio_result dal_hw_gpio_pin_change_mode( -+ struct hw_gpio_pin *pin, -+ enum gpio_mode mode) -+{ -+ /* Attention! -+ * You must override this method in derived class */ -+ -+ return GPIO_RESULT_NON_SPECIFIC_ERROR; -+} -+ -+bool dal_hw_gpio_pin_construct( -+ struct hw_gpio_pin *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ pin->ctx = ctx; -+ pin->id = id; -+ pin->en = en; -+ pin->mode = GPIO_MODE_UNKNOWN; -+ pin->opened = false; -+ -+ return true; -+} -+ -+void dal_hw_gpio_pin_destruct( -+ struct hw_gpio_pin *pin) -+{ -+ ASSERT(!pin->opened); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h -new file mode 100644 -index 0000000..d1f2f27 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h -@@ -0,0 +1,79 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_GPIO_PIN_H__ -+#define __DAL_HW_GPIO_PIN_H__ -+ -+struct hw_gpio_pin; -+ -+struct hw_gpio_pin_funcs { -+ void (*destroy)( -+ struct hw_gpio_pin **ptr); -+ bool (*open)( -+ struct hw_gpio_pin *pin, -+ enum gpio_mode mode, -+ void *options); -+ enum gpio_result (*get_value)( -+ const struct hw_gpio_pin *pin, -+ uint32_t *value); -+ enum gpio_result (*set_value)( -+ const struct hw_gpio_pin *pin, -+ uint32_t value); -+ enum gpio_result (*set_config)( -+ struct hw_gpio_pin *pin, -+ const struct gpio_config_data *config_data); -+ enum gpio_result (*change_mode)( -+ struct hw_gpio_pin *pin, -+ enum gpio_mode mode); -+ void (*close)( -+ struct hw_gpio_pin *pin); -+}; -+ -+struct hw_gpio_pin { -+ const struct hw_gpio_pin_funcs *funcs; -+ enum gpio_id id; -+ uint32_t en; -+ enum gpio_mode mode; -+ bool opened; -+ struct dc_context *ctx; -+}; -+ -+bool dal_hw_gpio_pin_construct( -+ struct hw_gpio_pin *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+void dal_hw_gpio_pin_destruct( -+ struct hw_gpio_pin *pin); -+ -+enum gpio_result dal_hw_gpio_pin_change_mode( -+ struct hw_gpio_pin *pin, -+ enum gpio_mode mode); -+ -+enum gpio_result dal_hw_gpio_pin_set_config( -+ struct hw_gpio_pin *pin, -+ const struct gpio_config_data *config_data); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c -new file mode 100644 -index 0000000..c09d74c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c -@@ -0,0 +1,88 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+#include "hw_gpio_pin.h" -+#include "hw_gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_hpd.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+static enum gpio_result config_mode( -+ struct hw_gpio *pin, -+ enum gpio_mode mode) -+{ -+ if (mode == GPIO_MODE_INTERRUPT) { -+ /* Interrupt mode supported only by HPD (IrqGpio) pins. */ -+ pin->base.mode = mode; -+ -+ return dal_hw_gpio_set_reg_value( -+ pin->base.ctx, -+ &pin->pin_reg.DC_GPIO_DATA_MASK, -+ 0); -+ } else -+ /* For any mode other than Interrupt, -+ * act as normal GPIO. */ -+ return dal_hw_gpio_config_mode(pin, mode); -+} -+ -+const struct hw_gpio_funcs hw_hpd_func = { -+ .config_mode = config_mode, -+}; -+ -+bool dal_hw_hpd_construct( -+ struct hw_hpd *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx) -+{ -+ if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) -+ return false; -+ pin->base.funcs = &hw_hpd_func; -+ return true; -+} -+ -+void dal_hw_hpd_destruct( -+ struct hw_hpd *pin) -+{ -+ dal_hw_gpio_destruct(&pin->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h -new file mode 100644 -index 0000000..3fb82df ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h -@@ -0,0 +1,45 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_HPD_H__ -+#define __DAL_HW_HPD_H__ -+ -+struct hw_hpd { -+ struct hw_gpio base; -+}; -+ -+#define HW_HPD_FROM_BASE(hw_gpio) \ -+ container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base) -+ -+bool dal_hw_hpd_construct( -+ struct hw_hpd *pin, -+ enum gpio_id id, -+ uint32_t en, -+ struct dc_context *ctx); -+ -+void dal_hw_hpd_destruct( -+ struct hw_hpd *pin); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c -new file mode 100644 -index 0000000..96e135f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c -@@ -0,0 +1,67 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_types.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "hw_translate.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/hw_translate_dce110.h" -+#endif -+ -+/* -+ * This unit -+ */ -+ -+bool dal_hw_translate_init( -+ struct hw_translate *translate, -+ enum dce_version dce_version) -+{ -+ switch (dce_version) { -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ dal_hw_translate_dce110_init(translate); -+ return true; -+#endif -+ default: -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h -new file mode 100644 -index 0000000..d5740ac ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h -@@ -0,0 +1,49 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_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); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.c b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c -new file mode 100644 -index 0000000..382b89f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c -@@ -0,0 +1,181 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/gpio_interface.h" -+#include "include/irq_interface.h" -+#include "include/gpio_service_interface.h" -+#include "hw_gpio_pin.h" -+#include "hw_translate.h" -+#include "hw_factory.h" -+#include "gpio_service.h" -+#include "gpio.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "irq.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+enum gpio_result dal_irq_open( -+ struct irq *irq) -+{ -+ return dal_gpio_open(irq->pin, GPIO_MODE_INTERRUPT); -+} -+ -+enum gpio_result dal_irq_get_value( -+ const struct irq *irq, -+ uint32_t *value) -+{ -+ return dal_gpio_get_value(irq->pin, value); -+} -+ -+enum dc_irq_source dal_irq_get_source( -+ const struct irq *irq) -+{ -+ enum gpio_id id = dal_gpio_get_id(irq->pin); -+ -+ switch (id) { -+ case GPIO_ID_HPD: -+ return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 + -+ dal_gpio_get_enum(irq->pin)); -+ case GPIO_ID_GPIO_PAD: -+ return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 + -+ dal_gpio_get_enum(irq->pin)); -+ default: -+ return DC_IRQ_SOURCE_INVALID; -+ } -+} -+ -+enum dc_irq_source dal_irq_get_rx_source( -+ const struct irq *irq) -+{ -+ enum gpio_id id = dal_gpio_get_id(irq->pin); -+ -+ switch (id) { -+ case GPIO_ID_HPD: -+ return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX + -+ dal_gpio_get_enum(irq->pin)); -+ default: -+ return DC_IRQ_SOURCE_INVALID; -+ } -+} -+ -+enum gpio_result dal_irq_setup_hpd_filter( -+ struct irq *irq, -+ struct gpio_hpd_config *config) -+{ -+ struct gpio_config_data config_data; -+ -+ if (!config) -+ return GPIO_RESULT_INVALID_DATA; -+ -+ config_data.type = GPIO_CONFIG_TYPE_HPD; -+ config_data.config.hpd = *config; -+ -+ return dal_gpio_set_config(irq->pin, &config_data); -+} -+ -+void dal_irq_close( -+ struct irq *irq) -+{ -+ dal_gpio_close(irq->pin); -+} -+ -+/* -+ * @brief -+ * Creation and destruction -+ */ -+ -+struct irq *dal_gpio_create_irq( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en) -+{ -+ struct irq *irq; -+ -+ switch (id) { -+ case GPIO_ID_HPD: -+ case GPIO_ID_GPIO_PAD: -+ break; -+ default: -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ irq = dc_service_alloc(service->ctx, sizeof(struct irq)); -+ -+ if (!irq) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ irq->pin = dal_gpio_service_create_gpio_ex( -+ service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); -+ irq->ctx = service->ctx; -+ -+ if (irq->pin) -+ return irq; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(service->ctx, irq); -+ -+ return NULL; -+} -+ -+static void destruct(struct irq *irq) -+{ -+ dal_irq_close(irq); -+ dal_gpio_service_destroy_gpio(&irq->pin); -+ -+} -+ -+void dal_gpio_destroy_irq( -+ struct irq **irq) -+{ -+ if (!irq || !*irq) { -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ -+ destruct(*irq); -+ dc_service_free((*irq)->ctx, *irq); -+ -+ *irq = NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.h b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h -new file mode 100644 -index 0000000..b69375c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h -@@ -0,0 +1,42 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_H__ -+#define __DAL_IRQ_H__ -+ -+struct irq { -+ struct gpio *pin; -+ struct dc_context *ctx; -+}; -+ -+struct irq *dal_gpio_create_irq( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en); -+ -+void dal_gpio_destroy_irq( -+ struct irq **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile -new file mode 100644 -index 0000000..d3d6faf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile -@@ -0,0 +1,26 @@ -+# -+# 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 = calc_pll_clock_source.o clock_source.o \ -+dc_clock_generator.o display_clock.o divider_range.o \ -+ext_clock_source.o pll_clock_source.o -+ -+AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) -+ -+AMD_DAL_FILES += $(AMD_DAL_GPU) -+ -+ -+############################################################################### -+# DCE 110 family -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+GPU_DCE110 = display_clock_dce110.o \ -+ pll_clock_source_dce110.o ext_clock_source_dce110.o \ -+ vce_clock_source_dce110.o dc_clock_gating_dce110.o -+ -+AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) -+ -+AMD_DAL_FILES += $(AMD_DAL_GPU_DCE110) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c -new file mode 100644 -index 0000000..7c94733 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c -@@ -0,0 +1,407 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "calc_pll_clock_source.h" -+#include "include/bios_parser_interface.h" -+#include "include/logger_interface.h" -+ -+/** -+* 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; -+} -+ -+uint32_t dal_clock_source_calculate_pixel_clock_pll_dividers( -+ struct calc_pll_clock_source *calc_pll_cs, -+ struct pll_settings *pll_settings) -+{ -+ uint32_t err_tolerance; -+ uint32_t min_post_divider; -+ uint32_t max_post_divider; -+ uint32_t min_ref_divider; -+ uint32_t max_ref_divider; -+ -+ if (pll_settings->adjusted_pix_clk == 0) { -+ dal_logger_write(calc_pll_cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s Bad requested pixel clock", __func__); -+ return MAX_PLL_CALC_ERROR; -+ } -+ -+/* 1) Find Post divider ranges */ -+ if (pll_settings->pix_clk_post_divider) { -+ min_post_divider = pll_settings->pix_clk_post_divider; -+ max_post_divider = pll_settings->pix_clk_post_divider; -+ } else { -+ min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; -+ if (min_post_divider * pll_settings->adjusted_pix_clk < -+ calc_pll_cs->min_vco_khz) { -+ min_post_divider = calc_pll_cs->min_vco_khz / -+ pll_settings->adjusted_pix_clk; -+ if ((min_post_divider * -+ pll_settings->adjusted_pix_clk) < -+ calc_pll_cs->min_vco_khz) -+ min_post_divider++; -+ } -+ -+ max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; -+ if (max_post_divider * pll_settings->adjusted_pix_clk -+ > calc_pll_cs->max_vco_khz) -+ max_post_divider = calc_pll_cs->max_vco_khz / -+ pll_settings->adjusted_pix_clk; -+ } -+ -+/* 2) Find Reference divider ranges -+ * When SS is enabled, or for Display Port even without SS, -+ * pll_settings->referenceDivider is not zero. -+ * So calculate PPLL FB and fractional FB divider -+ * using the passed reference divider*/ -+ -+ if (pll_settings->reference_divider) { -+ min_ref_divider = pll_settings->reference_divider; -+ max_ref_divider = pll_settings->reference_divider; -+ } else { -+ min_ref_divider = ((calc_pll_cs->ref_freq_khz -+ / calc_pll_cs->max_pll_input_freq_khz) -+ > calc_pll_cs->min_pll_ref_divider) -+ ? calc_pll_cs->ref_freq_khz -+ / calc_pll_cs->max_pll_input_freq_khz -+ : calc_pll_cs->min_pll_ref_divider; -+ -+ max_ref_divider = ((calc_pll_cs->ref_freq_khz -+ / calc_pll_cs->min_pll_input_freq_khz) -+ < calc_pll_cs->max_pll_ref_divider) -+ ? calc_pll_cs->ref_freq_khz / -+ calc_pll_cs->min_pll_input_freq_khz -+ : calc_pll_cs->max_pll_ref_divider; -+ } -+ -+/* If some parameters are invalid we could have scenario when "min">"max" -+ * which produced endless loop later. -+ * We should investigate why we get the wrong parameters. -+ * But to follow the similar logic when "adjustedPixelClock" is set to be 0 -+ * it is better to return here than cause system hang/watchdog timeout later. -+ * ## SVS Wed 15 Jul 2009 */ -+ -+ if (min_post_divider > max_post_divider) { -+ dal_logger_write(calc_pll_cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s Post divider range is invalid", __func__); -+ return MAX_PLL_CALC_ERROR; -+ } -+ -+ if (min_ref_divider > max_ref_divider) { -+ dal_logger_write(calc_pll_cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s Reference divider range is invalid", __func__); -+ return MAX_PLL_CALC_ERROR; -+ } -+ -+/* 3) Try to find PLL dividers given ranges -+ * starting with minimal error tolerance. -+ * Increase error tolerance until PLL dividers found*/ -+ err_tolerance = MAX_PLL_CALC_ERROR; -+ -+ while (!calc_pll_dividers_in_range( -+ calc_pll_cs, -+ pll_settings, -+ min_ref_divider, -+ max_ref_divider, -+ min_post_divider, -+ max_post_divider, -+ err_tolerance)) -+ err_tolerance += (err_tolerance > 10) -+ ? (err_tolerance / 10) -+ : 1; -+ -+ return err_tolerance; -+} -+ -+static bool calc_pll_clock_source_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 (dal_bios_parser_get_firmware_info( -+ init_data->bp, -+ &fw_info) != BP_RESULT_OK) -+ return false; -+ -+ calc_pll_cs->ctx = init_data->ctx; -+ calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency; -+ calc_pll_cs->min_vco_khz = -+ fw_info.pll_info.min_output_pxl_clk_pll_frequency; -+ calc_pll_cs->max_vco_khz = -+ fw_info.pll_info.max_output_pxl_clk_pll_frequency; -+ -+ if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0) -+ calc_pll_cs->max_pll_input_freq_khz = -+ init_data->max_override_input_pxl_clk_pll_freq_khz; -+ else -+ calc_pll_cs->max_pll_input_freq_khz = -+ fw_info.pll_info.max_input_pxl_clk_pll_frequency; -+ -+ if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0) -+ calc_pll_cs->min_pll_input_freq_khz = -+ init_data->min_override_input_pxl_clk_pll_freq_khz; -+ else -+ calc_pll_cs->min_pll_input_freq_khz = -+ fw_info.pll_info.min_input_pxl_clk_pll_frequency; -+ -+ calc_pll_cs->min_pix_clock_pll_post_divider = -+ init_data->min_pix_clk_pll_post_divider; -+ calc_pll_cs->max_pix_clock_pll_post_divider = -+ init_data->max_pix_clk_pll_post_divider; -+ calc_pll_cs->min_pll_ref_divider = -+ init_data->min_pll_ref_divider; -+ calc_pll_cs->max_pll_ref_divider = -+ init_data->max_pll_ref_divider; -+ -+ if (init_data->num_fract_fb_divider_decimal_point == 0 || -+ init_data->num_fract_fb_divider_decimal_point_precision > -+ init_data->num_fract_fb_divider_decimal_point) { -+ dal_logger_write(calc_pll_cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "The dec point num or precision is incorrect!"); -+ return false; -+ } -+ if (init_data->num_fract_fb_divider_decimal_point_precision == 0) { -+ dal_logger_write(calc_pll_cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "Incorrect fract feedback divider precision num!"); -+ return false; -+ } -+ -+ calc_pll_cs->fract_fb_divider_decimal_points_num = -+ init_data->num_fract_fb_divider_decimal_point; -+ calc_pll_cs->fract_fb_divider_precision = -+ init_data->num_fract_fb_divider_decimal_point_precision; -+ calc_pll_cs->fract_fb_divider_factor = 1; -+ for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i) -+ calc_pll_cs->fract_fb_divider_factor *= 10; -+ -+ calc_pll_cs->fract_fb_divider_precision_factor = 1; -+ for ( -+ i = 0; -+ i < (calc_pll_cs->fract_fb_divider_decimal_points_num - -+ calc_pll_cs->fract_fb_divider_precision); -+ ++i) -+ calc_pll_cs->fract_fb_divider_precision_factor *= 10; -+ -+ return true; -+} -+ -+bool dal_calc_pll_clock_source_max_vco_init( -+ struct calc_pll_clock_source *calc_pll_cs, -+ struct calc_pll_clock_source_init_data *init_data) -+{ -+ return calc_pll_clock_source_max_vco_construct( -+ calc_pll_cs, init_data); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h -new file mode 100644 -index 0000000..be44d06 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h -@@ -0,0 +1,79 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_CALC_PLL_CLOCK_SOURCE_H__ -+#define __DAL_CALC_PLL_CLOCK_SOURCE_H__ -+ -+#include "include/clock_source_types.h" -+ -+struct calc_pll_clock_source_init_data { -+ struct bios_parser *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; -+ -+}; -+#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 -+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; -+}; -+ -+ -+bool dal_calc_pll_clock_source_max_vco_init( -+ struct calc_pll_clock_source *calc_pll_cs, -+ struct calc_pll_clock_source_init_data *init_data); -+ -+uint32_t dal_clock_source_calculate_pixel_clock_pll_dividers( -+ struct calc_pll_clock_source *calc_pll_cs, -+ struct pll_settings *pll_settings); -+ -+ -+#endif /*__DAL_CALC_PLL_CLOCK_SOURCE_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.c -new file mode 100644 -index 0000000..8e700ea ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.c -@@ -0,0 +1,649 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/adapter_service_interface.h" -+#include "include/bios_parser_interface.h" -+#include "include/grph_object_id.h" -+#include "include/clock_source_interface.h" -+#include "include/logger_interface.h" -+ -+#include "clock_source.h" -+#include "pll_clock_source.h" -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/ext_clock_source_dce110.h" -+#include "dce110/pll_clock_source_dce110.h" -+#include "dce110/vce_clock_source_dce110.h" -+#endif -+ -+ -+struct clock_source *dal_clock_source_create( -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ enum dce_version dce_ver = -+ dal_adapter_service_get_dce_version(clk_src_init_data->as); -+ enum clock_source_id clk_src_id = -+ dal_graphics_object_id_get_clock_source_id( -+ clk_src_init_data->clk_src_id); -+ switch (dce_ver) { -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ break; -+ case DCE_VERSION_11_0: -+ { -+ switch (clk_src_id) { -+ case CLOCK_SOURCE_ID_PLL0: -+ /* fall through */ -+ case CLOCK_SOURCE_ID_PLL1: -+ /* fall through */ -+ case CLOCK_SOURCE_ID_PLL2: -+ return dal_pll_clock_source_dce110_create( -+ clk_src_init_data); -+ case CLOCK_SOURCE_ID_EXTERNAL: -+ return dal_ext_clock_source_dce110_create( -+ clk_src_init_data); -+ case CLOCK_SOURCE_ID_VCE: -+ return dal_vce_clock_source_dce110_create( -+ clk_src_init_data); -+ default: -+ return NULL; -+ } -+ } -+ break; -+#endif -+ default: -+ dal_logger_write(clk_src_init_data->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "Clock Source (id %d): not supported DCE version %d", -+ clk_src_id, -+ dce_ver); -+ ASSERT_CRITICAL(false); -+ break; -+ } -+ return NULL; -+} -+ -+const struct spread_spectrum_data *dal_clock_source_get_ss_data_entry( -+ struct clock_source *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_LVDS: -+ ss_parm = clk_src->ep_ss_params; -+ entrys_num = clk_src->ep_ss_params_cnt; -+ break; -+ -+ case SIGNAL_TYPE_DISPLAY_PORT: -+ case SIGNAL_TYPE_DISPLAY_PORT_MST: -+ case SIGNAL_TYPE_EDP: -+ ss_parm = clk_src->dp_ss_params; -+ entrys_num = clk_src->dp_ss_params_cnt; -+ break; -+ -+ default: -+ ss_parm = NULL; -+ entrys_num = 0; -+ break; -+ } -+ -+ if (ss_parm == NULL) -+ return ret; -+ -+ for (i = 0; i < entrys_num; ++i, ++ss_parm) { -+ if (ss_parm->freq_range_khz >= pix_clk_khz) { -+ ret = ss_parm; -+ break; -+ } -+ } -+ -+ return ret; -+} -+ -+bool dal_clock_source_base_adjust_dto_pix_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_pix_clk_hz) -+{ -+ return false; -+} -+ -+/* Adjust clock to match given pixel rate (SS/DeepColor compensated)*/ -+bool dal_clock_source_base_adjust_pll_pixel_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requestedPixelClockInHz) -+{ -+ return false; -+} -+ -+static uint32_t retrieve_raw_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params) -+{ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ return clk_src->funcs->retrieve_dto_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ else -+ return clk_src->funcs->retrieve_pll_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+} -+ -+ -+ -+bool dal_clock_source_adjust_pxl_clk_by_pxl_amount( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ int32_t pix_num) -+{ -+ -+ uint32_t cur_pix_rate_hz; -+ uint32_t reqested_pix_rate_hz; -+ bool success = false; -+ -+ if (pix_clk_params == NULL) -+ return false; -+ -+ cur_pix_rate_hz = retrieve_raw_pix_rate_hz(clk_src, pix_clk_params); -+ reqested_pix_rate_hz = cur_pix_rate_hz + pix_num; -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[start]: Current(Raw): %u,%03u,%03uHz, Requested(Raw): %u,%03u,%03uHz\n", -+ __func__, -+ (cur_pix_rate_hz / 1000000), -+ (cur_pix_rate_hz / 1000) % 1000, -+ (cur_pix_rate_hz % 1000), -+ (reqested_pix_rate_hz / 1000000), -+ (reqested_pix_rate_hz / 1000) % 1000, -+ (reqested_pix_rate_hz % 1000)); -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ success = clk_src->funcs->adjust_dto_pixel_rate(clk_src, -+ pix_clk_params, -+ reqested_pix_rate_hz); -+ else -+ success = clk_src->funcs->adjust_pll_pixel_rate( -+ clk_src, -+ pix_clk_params, -+ reqested_pix_rate_hz); -+ -+ cur_pix_rate_hz = retrieve_raw_pix_rate_hz(clk_src, pix_clk_params); -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[end]: Current(Raw): %u,%03u,%03uHz, Requested(Raw): %u,%03u,%03uHz\n\n", -+ __func__, -+ (cur_pix_rate_hz / 1000000), -+ (cur_pix_rate_hz / 1000) % 1000, -+ (cur_pix_rate_hz % 1000), -+ (reqested_pix_rate_hz / 1000000), -+ (reqested_pix_rate_hz / 1000) % 1000, -+ (reqested_pix_rate_hz % 1000)); -+ -+ return success; -+} -+ -+/***************************/ -+/* private methods section */ -+/***************************/ -+ -+void dal_clock_source_get_ss_info_from_atombios( -+ struct clock_source *clk_src, -+ enum as_signal_type as_signal, -+ struct spread_spectrum_data *spread_spectrum_data[], -+ uint32_t *ss_entries_num) -+{ -+ enum bp_result bp_result = BP_RESULT_FAILURE; -+ struct spread_spectrum_info *ss_info; -+ struct spread_spectrum_data *ss_data; -+ struct spread_spectrum_info *ss_info_cur; -+ struct spread_spectrum_data *ss_data_cur; -+ uint32_t i; -+ -+ if (ss_entries_num == NULL) { -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "Invalid entry !!!\n"); -+ return; -+ } -+ if (spread_spectrum_data == NULL) { -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "Invalid array pointer!!!\n"); -+ return; -+ } -+ -+ spread_spectrum_data[0] = NULL; -+ *ss_entries_num = 0; -+ -+ *ss_entries_num = dal_bios_parser_get_ss_entry_number( -+ clk_src->bios_parser, -+ as_signal); -+ if (*ss_entries_num == 0) -+ return; -+ -+ ss_info = dc_service_alloc(clk_src->ctx, sizeof(struct spread_spectrum_info) -+ * (*ss_entries_num)); -+ ss_info_cur = ss_info; -+ if (ss_info == NULL) -+ return; -+ -+ ss_data = dc_service_alloc(clk_src->ctx, sizeof(struct spread_spectrum_data) * -+ (*ss_entries_num)); -+ if (ss_data == NULL) -+ goto out_free_info; -+ -+ for (i = 0, ss_info_cur = ss_info; -+ i < (*ss_entries_num); -+ ++i, ++ss_info_cur) { -+ bp_result = dal_bios_parser_get_spread_spectrum_info( -+ clk_src->bios_parser, -+ as_signal, -+ i, -+ ss_info_cur); -+ if (bp_result != BP_RESULT_OK) -+ goto out_free_data; -+ } -+ -+ for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data; -+ i < (*ss_entries_num); -+ ++i, ++ss_info_cur, ++ss_data_cur) { -+ -+ if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) { -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "Invalid ATOMBIOS SS Table!!!\n"); -+ goto out_free_data; -+ } -+ -+ /* for HDMI check SS percentage, -+ * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/ -+ if (as_signal == AS_SIGNAL_TYPE_HDMI -+ && ss_info_cur->spread_spectrum_percentage > 6){ -+ /* invalid input, do nothing */ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "Invalid SS percentage "); -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "for HDMI in ATOMBIOS info Table!!!\n"); -+ continue; -+ } -+ if (ss_info_cur->spread_percentage_divider == 1000) { -+ /* Keep previous precision from ATOMBIOS for these -+ * in case new precision set by ATOMBIOS for these -+ * (otherwise all code in DCE specific classes -+ * for all previous ASICs would need -+ * to be updated for SS calculations, -+ * Audio SS compensation and DP DTO SS compensation -+ * which assumes fixed SS percentage Divider = 100)*/ -+ ss_info_cur->spread_spectrum_percentage /= 10; -+ ss_info_cur->spread_percentage_divider = 100; -+ } -+ -+ ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range; -+ ss_data_cur->percentage = -+ ss_info_cur->spread_spectrum_percentage; -+ ss_data_cur->percentage_divider = -+ ss_info_cur->spread_percentage_divider; -+ ss_data_cur->modulation_freq_hz = -+ ss_info_cur->spread_spectrum_range; -+ -+ if (ss_info_cur->type.CENTER_MODE) -+ ss_data_cur->flags.CENTER_SPREAD = 1; -+ -+ if (ss_info_cur->type.EXTERNAL) -+ ss_data_cur->flags.EXTERNAL_SS = 1; -+ -+ } -+ -+ *spread_spectrum_data = ss_data; -+ dc_service_free(clk_src->ctx, ss_info); -+ return; -+ -+out_free_data: -+ dc_service_free(clk_src->ctx, ss_data); -+ *ss_entries_num = 0; -+out_free_info: -+ dc_service_free(clk_src->ctx, ss_info); -+} -+ -+uint32_t dal_clock_source_base_retrieve_dto_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params) -+{ -+ return 0; -+} -+ -+ -+uint32_t dal_clock_source_base_retrieve_pll_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params) -+{ -+ return 0; -+} -+ -+/*****************************/ -+/* interface methods section */ -+/*****************************/ -+ -+enum clock_source_id dal_clock_source_get_id( -+ const struct clock_source *clk_src) -+{ -+ return clk_src->clk_src_id; -+} -+ -+bool dal_clock_source_is_clk_src_with_fixed_freq( -+ const struct clock_source *clk_src) -+{ -+ return clk_src->is_clock_source_with_fixed_freq; -+} -+ -+const struct graphics_object_id dal_clock_source_get_graphics_object_id( -+ const struct clock_source *clk_src) -+{ -+ return clk_src->id; -+} -+ -+enum clock_sharing_level dal_clock_souce_get_clk_sharing_lvl( -+ const struct clock_source *clk_src) -+{ -+ return clk_src->clk_sharing_lvl; -+} -+ -+uint32_t dal_clock_source_get_pix_clk_dividers( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ return clk_src->funcs-> -+ get_pix_clk_dividers(clk_src, pix_clk_params, pll_settings); -+} -+ -+bool dal_clock_source_program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ return clk_src->funcs-> -+ program_pix_clk(clk_src, pix_clk_params, pll_settings); -+} -+ -+/* TODO save/restore FP was here */ -+bool dal_clock_source_adjust_pxl_clk_by_ref_pixel_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t pix_rate_hz) -+{ -+ uint32_t current_pix_rate_hz = 0; -+ uint32_t raw_cur_pix_rate_hz = 0; -+ uint32_t raw_pix_rate_hz = pix_rate_hz; -+ bool success = false; -+ -+ if (pix_clk_params == NULL || pix_rate_hz == 0) -+ return false; -+ -+ current_pix_rate_hz = retrieve_raw_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ raw_cur_pix_rate_hz = current_pix_rate_hz; -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[start]: Current: %u,%03u,%03uHz, Requested: %u,%03u,%03uHz\n", -+ __func__, -+ (current_pix_rate_hz / 1000000), -+ (current_pix_rate_hz / 1000) % 1000, -+ (current_pix_rate_hz % 1000), -+ (pix_rate_hz / 1000000), -+ (pix_rate_hz / 1000) % 1000, -+ (pix_rate_hz % 1000)); -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ success = clk_src->funcs->adjust_dto_pixel_rate( -+ clk_src, -+ pix_clk_params, -+ raw_pix_rate_hz); -+ else -+ success = clk_src->funcs->adjust_pll_pixel_rate( -+ clk_src, -+ pix_clk_params, -+ raw_pix_rate_hz); -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ raw_cur_pix_rate_hz = clk_src->funcs-> -+ retrieve_dto_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ else -+ raw_cur_pix_rate_hz = clk_src->funcs-> -+ retrieve_pll_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ -+ current_pix_rate_hz = raw_cur_pix_rate_hz; -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[end]: Current: %u,%03u,%03uHz, Requested: %u,%03u,%03uHz\n", -+ __func__, -+ (current_pix_rate_hz / 1000000), -+ (current_pix_rate_hz / 1000) % 1000, -+ (current_pix_rate_hz % 1000), -+ (pix_rate_hz / 1000000), -+ (pix_rate_hz / 1000) % 1000, -+ (pix_rate_hz % 1000)); -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[end]: Current(Raw): %u,%03u,%03uHz, Requested(Raw): %u,%03u,%03uHz\n\n", -+ __func__, -+ (raw_cur_pix_rate_hz / 1000000), -+ (raw_cur_pix_rate_hz / 1000) % 1000, -+ (raw_cur_pix_rate_hz % 1000), -+ (raw_pix_rate_hz / 1000000), -+ (raw_pix_rate_hz / 1000) % 1000, -+ (raw_pix_rate_hz % 1000)); -+ -+ return success; -+} -+ -+/* TODO store/restore FP was here*/ -+bool dal_clock_source_adjust_pxl_clk_by_pix_amount( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ int32_t pix_num) -+{ -+ bool success = false; -+ uint32_t requested_pix_rate_hz; -+ uint32_t cur_pix_rate_hz = retrieve_raw_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ requested_pix_rate_hz = cur_pix_rate_hz + pix_num; -+ -+ if (pix_clk_params == NULL) -+ return false; -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[start]: Current(Raw): %u,%03u,%03uHz, Requested(Raw): %u,%03u,%03uHz\n", -+ __func__, -+ (cur_pix_rate_hz / 1000000), -+ (cur_pix_rate_hz / 1000) % 1000, -+ (cur_pix_rate_hz % 1000), -+ (requested_pix_rate_hz / 1000000), -+ (requested_pix_rate_hz / 1000) % 1000, -+ (requested_pix_rate_hz % 1000)); -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ success = clk_src->funcs->adjust_dto_pixel_rate( -+ clk_src, -+ pix_clk_params, -+ requested_pix_rate_hz); -+ else -+ success = clk_src->funcs->adjust_pll_pixel_rate( -+ clk_src, -+ pix_clk_params, -+ requested_pix_rate_hz); -+ -+ cur_pix_rate_hz = retrieve_raw_pix_rate_hz(clk_src, pix_clk_params); -+ -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_SYNC, -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, -+ "%s[end]: Current(Raw): %u,%03u,%03uHz,Requested(Raw): %u,%03u,%03uHz\n\n", -+ __func__, -+ (cur_pix_rate_hz / 1000000), -+ (cur_pix_rate_hz / 1000) % 1000, -+ (cur_pix_rate_hz % 1000), -+ (requested_pix_rate_hz / 1000000), -+ (requested_pix_rate_hz / 1000) % 1000, -+ (requested_pix_rate_hz % 1000)); -+ -+ return success; -+} -+ -+/* TODO save/restore FP was here*/ -+uint32_t dal_clock_source_retrieve_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params) -+{ -+ uint32_t pixel_rate_hz = 0; -+ -+ if (pix_clk_params == NULL) -+ return pixel_rate_hz; -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ pixel_rate_hz = clk_src->funcs->retrieve_dto_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ else -+ pixel_rate_hz = clk_src->funcs->retrieve_pll_pix_rate_hz( -+ clk_src, -+ pix_clk_params); -+ -+ -+ return pixel_rate_hz; -+} -+ -+bool dal_clock_source_construct( -+ struct clock_source *clk_src, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ if (clk_src_init_data == NULL || clk_src_init_data->as == NULL) -+ return false; -+ clk_src->ctx = clk_src_init_data->ctx; -+ clk_src->id = clk_src_init_data->clk_src_id; -+ clk_src->adapter_service = clk_src_init_data->as; -+ clk_src->bios_parser = dal_adapter_service_get_bios_parser( -+ clk_src_init_data->as); -+ clk_src->turn_off_ds = false; -+ clk_src->clk_src_id = dal_graphics_object_id_get_clock_source_id( -+ clk_src_init_data->clk_src_id); -+ clk_src->is_gen_lock_capable = true; -+/*NOTE is_gen_lock_capable is false only for ext clock source dce80 */ -+ -+ clk_src->ep_ss_params = NULL; -+ clk_src->dp_ss_params = NULL; -+ clk_src->hdmi_ss_params = NULL; -+ clk_src->hdmi_ss_params = NULL; -+ clk_src->ep_ss_params_cnt = 0; -+ clk_src->dp_ss_params_cnt = 0; -+ clk_src->hdmi_ss_params_cnt = 0; -+ clk_src->dvi_ss_params_cnt = 0; -+ clk_src->output_signals = SIGNAL_TYPE_ALL; -+ clk_src->input_signals = SIGNAL_TYPE_ALL; -+ -+ return true; -+} -+ -+void dal_clock_source_destroy(struct clock_source **clk_src) -+{ -+ if (!clk_src || !(*clk_src)) -+ return; -+ -+ (*clk_src)->funcs->destroy(clk_src); -+ -+ *clk_src = NULL; -+} -+ -+bool dal_clock_source_is_input_signal_supported( -+ struct clock_source *clk_src, -+ enum signal_type signal_type) -+{ -+ /* TODO do we need this in clock_source ?? */ -+ return (clk_src->input_signals & signal_type) != 0; -+} -+ -+bool dal_clock_source_is_output_signal_supported( -+ const struct clock_source *clk_src, -+ enum signal_type signal_type) -+{ -+ return (clk_src->output_signals & signal_type) != 0; -+} -+ -+bool dal_clock_source_is_gen_lock_capable(struct clock_source *clk_src) -+{ -+ return clk_src->is_gen_lock_capable; -+} -+ -+bool dal_clock_source_power_down_pll(struct clock_source *clk_src, -+ enum controller_id controller_id) -+{ -+ return clk_src->funcs->power_down_pll(clk_src, controller_id); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h -new file mode 100644 -index 0000000..0a83874 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h -@@ -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 -+ * -+ */ -+ -+#ifndef __DAL_CLOCK_SOURCE_H__ -+#define __DAL_CLOCK_SOURCE_H__ -+ -+#include "include/adapter_service_types.h" -+#include "include/bios_parser_types.h" -+#include "include/clock_source_interface.h" -+#include "include/clock_source_types.h" -+ -+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 clock_source_impl { -+ bool (*switch_dp_clock_source)( -+ struct clock_source *clk_src, -+ enum controller_id, -+ enum clock_source_id); -+ bool (*adjust_pll_pixel_rate)( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_pix_clk_hz); -+ bool (*adjust_dto_pixel_rate)( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_clk_freq_hz); -+ uint32_t (*retrieve_dto_pix_rate_hz)( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params); -+ uint32_t (*retrieve_pll_pix_rate_hz)( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params); -+ -+ uint32_t (*get_pix_clk_dividers)(struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+ bool (*program_pix_clk)(struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+ bool (*power_down_pll)(struct clock_source *clk_src, -+ enum controller_id); -+ void (*destroy)(struct clock_source **clk_src); -+}; -+ -+void dal_clock_source_get_ss_info_from_atombios( -+ struct clock_source *clk_src, -+ enum as_signal_type as_signal, -+ struct spread_spectrum_data *ss_data[], -+ uint32_t *ss_entries_num); -+uint32_t dal_clock_source_base_retrieve_dto_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params); -+const struct spread_spectrum_data *dal_clock_source_get_ss_data_entry( -+ struct clock_source *clk_src, -+ enum signal_type signal, -+ uint32_t pix_clk_khz); -+/* for PLL and EXT clock sources */ -+struct registers { -+ uint32_t dp_dtox_phase; -+ uint32_t dp_dtox_modulo; -+ uint32_t crtcx_pixel_rate_cntl; -+}; -+ -+struct clock_source { -+ const struct clock_source_impl *funcs; -+ struct graphics_object_id id; -+ enum clock_source_id clk_src_id; -+ struct adapter_service *adapter_service; -+ struct bios_parser *bios_parser; -+ -+ struct spread_spectrum_data *ep_ss_params; -+ uint32_t ep_ss_params_cnt; -+ 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 output_signals; -+ uint32_t input_signals; -+ -+ bool turn_off_ds; -+ bool is_gen_lock_capable; /*replacement for virtual method*/ -+ bool is_clock_source_with_fixed_freq; /*replacement for virtual method*/ -+ enum clock_sharing_level clk_sharing_lvl; -+ struct dc_context *ctx; -+}; -+ -+bool dal_clock_source_construct( -+ struct clock_source *clk_src, -+ struct clock_source_init_data *clk_src_init_data); -+bool dal_clock_source_base_adjust_pll_pixel_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_pix_clk_hz); -+bool dal_clock_source_base_adjust_dto_pix_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_pix_clk_hz); -+uint32_t dal_clock_source_base_retrieve_pll_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c -new file mode 100644 -index 0000000..f124dba ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c -@@ -0,0 +1,92 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dc_clock_generator.h" -+ -+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc) -+{ -+ if (dc == NULL || *dc == NULL) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ (*dc)->funcs->destroy(dc); -+ -+ *dc = NULL; -+} -+ -+void dal_dc_clock_generator_set_display_pipe_mapping( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_mapping_params *params) -+{ -+ dc_clk_gen->funcs->set_display_pipe_mapping(dc_clk_gen, params); -+} -+ -+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_dp_ref_clk_ds_params *params) -+{ -+ return dc_clk_gen->funcs->get_dp_ref_clk_ds_params(dc_clk_gen, params); -+} -+ -+bool dal_dc_clock_generator_enable_gtc_counter( -+ struct dc_clock_generator *dc_clk_gen, -+ uint32_t dprefclk) -+{ -+ return dc_clk_gen->funcs->enable_gtc_counter(dc_clk_gen, dprefclk); -+} -+ -+void dal_dc_clock_generator_disable_gtc_counter( -+ struct dc_clock_generator *dc_clk_gen) -+{ -+ dc_clk_gen->funcs->disable_gtc_counter(dc_clk_gen); -+} -+ -+void dal_dc_clock_generator_set_gtc_group_offset( -+ struct dc_clock_generator *dc_clk_gen, -+ enum gtc_group group_num, -+ uint32_t offset) -+{ -+ dc_clk_gen->funcs->set_gtc_group_offset(dc_clk_gen, group_num, offset); -+} -+ -+void dal_dc_clock_generator_base_set_display_pipe_mapping( -+ struct dc_clock_generator *base, -+ struct dccg_mapping_params *params) -+{ -+ -+} -+ -+bool dal_dc_clock_generator_construct_base( -+ struct dc_clock_generator *base, -+ struct dc_context *ctx -+) -+{ -+ base->ctx = ctx; -+ return true; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h -new file mode 100644 -index 0000000..d1bf1af ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h -@@ -0,0 +1,63 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DC_CLOCK_GENERATOR_H__ -+#define __DAL_DC_CLOCK_GENERATOR_H__ -+ -+#include "include/dc_clock_generator_interface.h" -+ -+struct dc_clock_generator_funcs { -+ void (*destroy)(struct dc_clock_generator **to_destroy); -+ -+ void (*set_display_pipe_mapping)( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_mapping_params *params); -+ -+ bool (*get_dp_ref_clk_ds_params)( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_dp_ref_clk_ds_params *params); -+ bool (*enable_gtc_counter)( -+ struct dc_clock_generator *dc_clk_gen, -+ uint32_t dprefclk); -+ void (*disable_gtc_counter)( -+ struct dc_clock_generator *dc_clk_gen); -+ void (*set_gtc_group_offset)( -+ struct dc_clock_generator *dc_clk_gen, -+ enum gtc_group group_num, -+ uint32_t offset); -+}; -+struct dc_clock_generator { -+ const struct dc_clock_generator_funcs *funcs; -+ struct dc_context *ctx; -+}; -+bool dal_dc_clock_generator_construct_base( -+ struct dc_clock_generator *base, -+ struct dc_context *ctx -+); -+void dal_dc_clock_generator_base_set_display_pipe_mapping( -+ struct dc_clock_generator *base, -+ struct dccg_mapping_params *params); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c -new file mode 100644 -index 0000000..e2d4228 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c -@@ -0,0 +1,90 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "include/logger_interface.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+#include "dc_clock_gating_dce110.h" -+ -+/****************************************************************************** -+ * Macro definitions -+ *****************************************************************************/ -+ -+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, \ -+ "%s:%s()\n", __FILE__, __func__) -+ -+/****************************************************************************** -+ * static functions -+ *****************************************************************************/ -+static void force_hw_base_light_sleep(struct dc_context *ctx) -+{ -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ -+ -+ addr = mmDC_MEM_GLOBAL_PWR_REQ_CNTL; -+ /* Read the mmDC_MEM_GLOBAL_PWR_REQ_CNTL to get the currently -+ * programmed DC_MEM_GLOBAL_PWR_REQ_DIS*/ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_MEM_GLOBAL_PWR_REQ_CNTL, -+ DC_MEM_GLOBAL_PWR_REQ_DIS); -+ -+ dal_write_reg(ctx, addr, value); -+ -+} -+ -+static void enable_hw_base_light_sleep(struct dc_context *ctx) -+{ -+ NOT_IMPLEMENTED(); -+} -+ -+static void disable_sw_manual_control_light_sleep( -+ struct dc_context *ctx) -+{ -+ NOT_IMPLEMENTED(); -+} -+ -+/****************************************************************************** -+ * public functions -+ *****************************************************************************/ -+ -+void dal_dc_clock_gating_dce110_power_up( -+ struct dc_context *ctx, -+ bool enable) -+{ -+ if (enable) { -+ enable_hw_base_light_sleep(ctx); -+ disable_sw_manual_control_light_sleep(ctx); -+ } else { -+ force_hw_base_light_sleep(ctx); -+ } -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h -new file mode 100644 -index 0000000..1bfd75a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DC_CLOCK_GATING_DCE110_H__ -+#define __DAL_DC_CLOCK_GATING_DCE110_H__ -+ -+void dal_dc_clock_gating_dce110_power_up( -+ struct dc_context *ctx, -+ bool enable); -+ -+#endif /* __DAL_DC_CLOCK_GATING_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c -new file mode 100644 -index 0000000..e582ba0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c -@@ -0,0 +1,958 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "include/adapter_service_interface.h" -+#include "include/bios_parser_interface.h" -+#include "include/fixed32_32.h" -+#include "include/logger_interface.h" -+ -+#include "../divider_range.h" -+ -+#include "display_clock_dce110.h" -+ -+#define FROM_DISPLAY_CLOCK(base) \ -+ container_of(base, struct display_clock_dce110, disp_clk_base) -+ -+static struct state_dependent_clocks max_clks_by_state[] = { -+/*( dvo not exist in KV)*/ -+/*ClocksStateInvalid - should not be used*/ -+{ .display_clk_khz = 0, .pixel_clk_khz = 0, .dvo_clk_khz = 0 }, -+/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000, .dvo_clk_khz = 0 }, -+/*ClocksStateLow*/ -+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000, .dvo_clk_khz = 0 }, -+/*ClocksStateNominal*/ -+{ .display_clk_khz = 467000, .pixel_clk_khz = 400000, .dvo_clk_khz = 0 }, -+/*ClocksStatePerformance*/ -+{ .display_clk_khz = 643000, .pixel_clk_khz = 400000, .dvo_clk_khz = 0 } }; -+ -+ -+/* Starting point for each divider range.*/ -+enum divider_range_start { -+ DIVIDER_RANGE_01_START = 200, /* 2.00*/ -+ DIVIDER_RANGE_02_START = 1600, /* 16.00*/ -+ DIVIDER_RANGE_03_START = 3200, /* 32.00*/ -+ DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -+}; -+ -+/* Array identifiers and count for the divider ranges.*/ -+enum divider_range_count { -+ DIVIDER_RANGE_01 = 0, -+ DIVIDER_RANGE_02, -+ DIVIDER_RANGE_03, -+ DIVIDER_RANGE_MAX /* == 3*/ -+}; -+ -+/* Ranges for divider identifiers (Divider ID or DID) -+ mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -+enum divider_id_register_setting { -+ DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, -+ DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, -+ DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, -+ DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -+}; -+ -+/* Step size between each divider within a range. -+ Incrementing the DENTIST_DISPCLK_WDIVIDER by one -+ will increment the divider by this much.*/ -+enum divider_range_step_size { -+ DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ -+ DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ -+ DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -+}; -+ -+static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; -+ -+#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000 -+/***************************************************************************** -+ * static functions -+ *****************************************************************************/ -+ -+/* -+ * store_max_clocks_state -+ * -+ * @brief -+ * Cache the clock state -+ * -+ * @param -+ * struct display_clock *base - [out] cach the state in this structure -+ * enum clocks_state max_clocks_state - [in] state to be stored -+ */ -+static void store_max_clocks_state( -+ struct display_clock *base, -+ enum clocks_state max_clocks_state) -+{ -+ struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); -+ -+ switch (max_clocks_state) { -+ case CLOCKS_STATE_LOW: -+ case CLOCKS_STATE_NOMINAL: -+ case CLOCKS_STATE_PERFORMANCE: -+ case CLOCKS_STATE_ULTRA_LOW: -+ dc->max_clks_state = max_clocks_state; -+ break; -+ -+ case CLOCKS_STATE_INVALID: -+ default: -+ /*Invalid Clocks State!*/ -+ ASSERT_CRITICAL(false); -+ break; -+ } -+} -+ -+static enum clocks_state get_min_clocks_state(struct display_clock *base) -+{ -+ return base->cur_min_clks_state; -+} -+ -+static bool set_min_clocks_state( -+ struct display_clock *base, -+ enum clocks_state clocks_state) -+{ -+ struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); -+ -+ if (clocks_state > dc->max_clks_state) { -+ /*Requested state exceeds max supported state.*/ -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Requested state exceeds max supported state"); -+ return false; -+ } else if (clocks_state == base->cur_min_clks_state) { -+ /*if we're trying to set the same state, we can just return -+ * since nothing needs to be done*/ -+ return true; -+ } -+ -+ base->cur_min_clks_state = clocks_state; -+ -+ return true; -+} -+ -+static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -+{ -+ uint32_t dispclk_cntl_value; -+ uint32_t dp_ref_clk_cntl_value; -+ uint32_t dp_ref_clk_cntl_src_sel_value; -+ uint32_t dp_ref_clk_khz = 600000; -+ uint32_t target_div = INVALID_DIVIDER; -+ struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); -+ -+ /* ASSERT DP Reference Clock source is from DFS*/ -+ dp_ref_clk_cntl_value = dal_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 = dal_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); -+ -+ dc_service_free((*base)->ctx, dc110); -+ -+ *base = NULL; -+} -+ -+static uint32_t get_validation_clock(struct display_clock *dc) -+{ -+ uint32_t clk = 0; -+ struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); -+ -+ switch (disp_clk->max_clks_state) { -+ case CLOCKS_STATE_ULTRA_LOW: -+ /*Currently not supported, it has 0 in table entry*/ -+ case CLOCKS_STATE_LOW: -+ clk = max_clks_by_state[CLOCKS_STATE_LOW]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_NOMINAL: -+ clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_PERFORMANCE: -+ clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. -+ display_clk_khz; -+ break; -+ -+ case CLOCKS_STATE_INVALID: -+ default: -+ /*Invalid Clocks State*/ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Invalid clock state"); -+ /* just return the display engine clock for -+ * lowest supported state*/ -+ clk = max_clks_by_state[CLOCKS_STATE_LOW]. -+ display_clk_khz; -+ break; -+ } -+ return clk; -+} -+ -+static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -+{ -+ /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ -+ struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); -+ -+ if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) -+ return deep_color_factor; -+ -+ switch (params->deep_color_depth) { -+ case COLOR_DEPTH_101010: -+ /*deep color ratio for 30bpp is 30/24 = 1.25*/ -+ deep_color_factor = dal_fixed32_32_from_fraction(30, 24); -+ break; -+ -+ case COLOR_DEPTH_121212: -+ /* deep color ratio for 36bpp is 36/24 = 1.5*/ -+ deep_color_factor = dal_fixed32_32_from_fraction(36, 24); -+ break; -+ -+ case COLOR_DEPTH_161616: -+ /* deep color ratio for 48bpp is 48/24 = 2.0 */ -+ deep_color_factor = dal_fixed32_32_from_fraction(48, 24); -+ break; -+ default: -+ break; -+ } -+ return deep_color_factor; -+} -+ -+static struct fixed32_32 get_scaler_efficiency( -+ struct dc_context *ctx, -+ struct min_clock_params *params) -+{ -+ struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); -+ -+ if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { -+ scaler_efficiency = -+ dal_fixed32_32_add( -+ dal_fixed32_32_from_fraction(35555, 10000), -+ dal_fixed32_32_from_fraction( -+ 55556, -+ 100000 * 10000)); -+ } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { -+ scaler_efficiency = -+ dal_fixed32_32_add( -+ dal_fixed32_32_from_fraction(34285, 10000), -+ dal_fixed32_32_from_fraction( -+ 71429, -+ 100000 * 10000)); -+ } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) -+ scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); -+ -+ return scaler_efficiency; -+} -+ -+static struct fixed32_32 get_lb_lines_in_per_line_out( -+ struct min_clock_params *params, -+ struct fixed32_32 v_scale_ratio) -+{ -+ struct fixed32_32 two = dal_fixed32_32_from_int(2); -+ struct fixed32_32 four = dal_fixed32_32_from_int(4); -+ struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); -+ struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); -+ -+ if (params->line_buffer_prefetch_enabled) -+ return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); -+ else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) -+ return dal_fixed32_32_one; -+ else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) -+ return f4_to_3; -+ else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) -+ return f6_to_4; -+ else if (dal_fixed32_32_le(v_scale_ratio, two)) -+ return two; -+ else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) -+ return four; -+ else -+ return dal_fixed32_32_zero; -+} -+ -+static uint32_t get_actual_required_display_clk( -+ struct display_clock_dce110 *disp_clk, -+ uint32_t target_clk_khz) -+{ -+ uint32_t disp_clk_khz = target_clk_khz; -+ uint32_t div = INVALID_DIVIDER; -+ uint32_t did = INVALID_DID; -+ uint32_t scaled_vco = -+ disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; -+ -+ ASSERT_CRITICAL(!!disp_clk_khz); -+ -+ if (disp_clk_khz) -+ div = scaled_vco / disp_clk_khz; -+ -+ did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); -+ -+ if (did != INVALID_DID) { -+ div = dal_divider_range_get_divider( -+ divider_ranges, DIVIDER_RANGE_MAX, did); -+ -+ if ((div != INVALID_DIVIDER) && -+ (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) -+ if (disp_clk_khz > (scaled_vco / div)) -+ div = dal_divider_range_get_divider( -+ divider_ranges, DIVIDER_RANGE_MAX, -+ did - 1); -+ -+ if (div != INVALID_DIVIDER) -+ disp_clk_khz = scaled_vco / div; -+ -+ } -+ /* We need to add 10KHz to this value because the accuracy in VBIOS is -+ in 10KHz units. So we need to always round the last digit up in order -+ to reach the next div level.*/ -+ return disp_clk_khz + 10; -+} -+ -+static uint32_t calc_single_display_min_clks( -+ struct display_clock *base, -+ struct min_clock_params *params, -+ bool set_clk) -+{ -+ struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; -+ struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; -+ uint32_t pix_clk_khz = 0; -+ uint32_t lb_source_width = 0; -+ struct fixed32_32 deep_color_factor; -+ struct fixed32_32 scaler_efficiency; -+ struct fixed32_32 v_filter_init; -+ uint32_t v_filter_init_trunc; -+ uint32_t num_lines_at_frame_start = 3; -+ struct fixed32_32 v_filter_init_ceil; -+ struct fixed32_32 lines_per_lines_out_at_frame_start; -+ struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ -+ uint32_t src_wdth_rnd_to_chunks; -+ struct fixed32_32 scaling_coeff; -+ struct fixed32_32 h_blank_granularity_factor = -+ dal_fixed32_32_one; -+ struct fixed32_32 fx_disp_clk_mhz; -+ struct fixed32_32 line_time; -+ struct fixed32_32 disp_pipe_pix_throughput; -+ struct fixed32_32 fx_alt_disp_clk_mhz; -+ uint32_t disp_clk_khz; -+ uint32_t alt_disp_clk_khz; -+ struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base); -+ uint32_t max_clk_khz = get_validation_clock(base); -+ bool panning_allowed = false; /* TODO: receive this value from AS */ -+ -+ if (params == NULL) { -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Invalid input parameter in %s", -+ __func__); -+ return 0; -+ } -+ -+ deep_color_factor = get_deep_color_factor(params); -+ scaler_efficiency = get_scaler_efficiency(base->ctx, params); -+ pix_clk_khz = params->requested_pixel_clock; -+ lb_source_width = params->source_view.width; -+ -+ if (0 != params->dest_view.height && 0 != params->dest_view.width) { -+ -+ h_scale_ratio = dal_fixed32_32_from_fraction( -+ params->source_view.width, -+ params->dest_view.width); -+ v_scale_ratio = dal_fixed32_32_from_fraction( -+ params->source_view.height, -+ params->dest_view.height); -+ } else { -+ dal_logger_write(base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Destination height or width is 0!\n"); -+ } -+ -+ v_filter_init = -+ dal_fixed32_32_add( -+ v_scale_ratio, -+ dal_fixed32_32_add_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int( -+ v_scale_ratio, -+ params->timing_info.INTERLACED), -+ 2), -+ params->scaling_info.v_taps + 1)); -+ v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); -+ -+ v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); -+ -+ v_filter_init_ceil = dal_fixed32_32_from_fraction( -+ v_filter_init_trunc, 2); -+ v_filter_init_ceil = dal_fixed32_32_from_int( -+ dal_fixed32_32_ceil(v_filter_init_ceil)); -+ v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); -+ -+ lines_per_lines_out_at_frame_start = -+ dal_fixed32_32_div_int(v_filter_init_ceil, -+ num_lines_at_frame_start); -+ lb_lines_in_per_line_out = -+ get_lb_lines_in_per_line_out(params, v_scale_ratio); -+ -+ if (panning_allowed) -+ src_wdth_rnd_to_chunks = -+ ((lb_source_width - 1) / 128) * 128 + 256; -+ else -+ src_wdth_rnd_to_chunks = -+ ((lb_source_width + 127) / 128) * 128; -+ -+ scaling_coeff = -+ dal_fixed32_32_div( -+ dal_fixed32_32_from_int(params->scaling_info.v_taps), -+ scaler_efficiency); -+ -+ if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) -+ scaling_coeff = dal_fixed32_32_max( -+ dal_fixed32_32_from_int( -+ dal_fixed32_32_ceil( -+ dal_fixed32_32_from_fraction( -+ params->scaling_info.h_taps, -+ 4))), -+ dal_fixed32_32_max( -+ dal_fixed32_32_mul( -+ scaling_coeff, -+ h_scale_ratio), -+ dal_fixed32_32_one)); -+ -+ if (!params->line_buffer_prefetch_enabled && -+ dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && -+ dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { -+ uint32_t line_total_pixel = -+ params->timing_info.h_total + lb_source_width - 256; -+ h_blank_granularity_factor = dal_fixed32_32_div( -+ dal_fixed32_32_from_int(params->timing_info.h_total), -+ dal_fixed32_32_div( -+ dal_fixed32_32_from_fraction( -+ line_total_pixel, 2), -+ h_scale_ratio)); -+ } -+ -+ /* Calculate display clock with ramping. Ramping factor is 1.1*/ -+ fx_disp_clk_mhz = -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int(scaling_coeff, 11), -+ 10); -+ line_time = dal_fixed32_32_from_fraction( -+ params->timing_info.h_total * 1000, pix_clk_khz); -+ -+ disp_pipe_pix_throughput = dal_fixed32_32_mul( -+ lb_lines_in_per_line_out, h_blank_granularity_factor); -+ disp_pipe_pix_throughput = dal_fixed32_32_max( -+ disp_pipe_pix_throughput, -+ lines_per_lines_out_at_frame_start); -+ disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( -+ disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), -+ line_time); -+ -+ if (0 != params->timing_info.h_total) { -+ fx_disp_clk_mhz = -+ dal_fixed32_32_max( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_mul_int( -+ scaling_coeff, pix_clk_khz), -+ 1000), -+ disp_pipe_pix_throughput); -+ fx_disp_clk_mhz = -+ dal_fixed32_32_mul( -+ fx_disp_clk_mhz, -+ dal_fixed32_32_from_fraction(11, 10)); -+ } -+ -+ fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, -+ dal_fixed32_32_mul(deep_color_factor, -+ dal_fixed32_32_from_fraction(11, 10))); -+ -+ /* Calculate display clock without ramping */ -+ fx_alt_disp_clk_mhz = scaling_coeff; -+ -+ if (0 != params->timing_info.h_total) { -+ fx_alt_disp_clk_mhz = dal_fixed32_32_max( -+ dal_fixed32_32_div_int(dal_fixed32_32_mul_int( -+ scaling_coeff, pix_clk_khz), -+ 1000), -+ dal_fixed32_32_div_int(dal_fixed32_32_mul_int( -+ disp_pipe_pix_throughput, 105), -+ 100)); -+ } -+ -+ if (set_clk && disp_clk_110->ss_on_gpu_pll && -+ disp_clk_110->gpu_pll_ss_divider) -+ fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, -+ dal_fixed32_32_add_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_div_int( -+ dal_fixed32_32_from_fraction( -+ disp_clk_110->gpu_pll_ss_percentage, -+ disp_clk_110->gpu_pll_ss_divider), 100), -+ 2), -+ 1)); -+ -+ /* convert to integer */ -+ disp_clk_khz = dal_fixed32_32_round( -+ dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); -+ alt_disp_clk_khz = dal_fixed32_32_round( -+ dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); -+ -+ if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) -+ disp_clk_khz = alt_disp_clk_khz; -+ -+ if (set_clk) { /* only compensate clock if we are going to set it.*/ -+ disp_clk_khz = get_actual_required_display_clk( -+ disp_clk_110, disp_clk_khz); -+ } -+ -+ disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; -+ -+ return disp_clk_khz; -+} -+ -+static uint32_t calculate_min_clock( -+ struct display_clock *base, -+ uint32_t path_num, -+ struct min_clock_params *params) -+{ -+ uint32_t i; -+ uint32_t validation_clk_khz = -+ get_validation_clock(base); -+ uint32_t min_clk_khz = validation_clk_khz; -+ uint32_t max_clk_khz = 0; -+ struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); -+ -+ if (dc->use_max_disp_clk) -+ return min_clk_khz; -+ -+ if (params != NULL) { -+ uint32_t disp_clk_khz = 0; -+ -+ for (i = 0; i < path_num; ++i) { -+ -+ disp_clk_khz = calc_single_display_min_clks( -+ base, params, true); -+ -+ /* update the max required clock found*/ -+ if (disp_clk_khz > max_clk_khz) -+ max_clk_khz = disp_clk_khz; -+ -+ params++; -+ } -+ } -+ -+ min_clk_khz = max_clk_khz; -+ -+ if (min_clk_khz > validation_clk_khz) -+ min_clk_khz = validation_clk_khz; -+ else if (min_clk_khz < base->min_display_clk_threshold_khz) -+ min_clk_khz = base->min_display_clk_threshold_khz; -+ -+ if (dc->use_max_disp_clk) -+ min_clk_khz = get_validation_clock(base); -+ -+ return min_clk_khz; -+} -+ -+static bool display_clock_integrated_info_construct( -+ struct display_clock_dce110 *disp_clk, -+ struct adapter_service *as) -+{ -+ struct integrated_info info; -+ uint32_t i; -+ -+ struct display_clock *base = &disp_clk->disp_clk_base; -+ -+ if (!dal_adapter_service_get_integrated_info(as, &info)) -+ return false; -+ -+ 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; -+ -+ 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) { -+ max_clks_by_state[clk_state].display_clk_khz = -+ info.disp_clk_voltage[i].max_supported_clk; -+ } -+ } -+ disp_clk->dfs_bypass_enabled = -+ dal_adapter_service_is_dfs_bypass_enabled(as); -+ disp_clk->use_max_disp_clk = -+ dal_adapter_service_is_feature_supported( -+ FEATURE_USE_MAX_DISPLAY_CLK); -+ -+ return true; -+} -+ -+static uint32_t get_clock(struct display_clock *dc) -+{ -+ uint32_t disp_clock = get_validation_clock(dc); -+ uint32_t target_div = INVALID_DIVIDER; -+ uint32_t addr = mmDENTIST_DISPCLK_CNTL; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); -+ -+ if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) -+ return disp_clk->dfs_bypass_disp_clk; -+ -+ /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed -+ DID DENTIST_DISPCLK_WDIVIDER.*/ -+ value = dal_read_reg(dc->ctx, addr); -+ field = get_reg_field_value( -+ value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); -+ -+ /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ -+ target_div = dal_divider_range_get_divider( -+ divider_ranges, -+ DIVIDER_RANGE_MAX, -+ field); -+ -+ if (target_div != INVALID_DIVIDER) -+ /* Calculate the current DFS clock in KHz. -+ Should be okay up to 42.9 THz before overflowing.*/ -+ disp_clock = (DIVIDER_RANGE_SCALE_FACTOR -+ * disp_clk->dentist_vco_freq_khz) / target_div; -+ return disp_clock; -+} -+ -+static enum clocks_state get_required_clocks_state( -+ struct display_clock *dc, -+ struct state_dependent_clocks *req_clocks) -+{ -+ int32_t i; -+ struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); -+ enum clocks_state low_req_clk = disp_clk->max_clks_state; -+ -+ if (!req_clocks) { -+ /* NULL pointer*/ -+ dal_logger_write(dc->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameter", -+ __func__); -+ return CLOCKS_STATE_INVALID; -+ } -+ -+ /* Iterate from highest supported to lowest valid state, and update -+ * lowest RequiredState with the lowest state that satisfies -+ * all required clocks -+ */ -+ for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { -+ if ((req_clocks->display_clk_khz <= -+ max_clks_by_state[i].display_clk_khz) && -+ (req_clocks->pixel_clk_khz <= -+ max_clks_by_state[i].pixel_clk_khz)) -+ low_req_clk = i; -+ } -+ return low_req_clk; -+} -+ -+static void set_clock( -+ struct display_clock *base, -+ uint32_t requested_clk_khz) -+{ -+ struct bp_pixel_clock_parameters pxl_clk_params; -+ struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); -+ struct bios_parser *bp = dal_adapter_service_get_bios_parser(base->as); -+ -+ /* Prepare to program display clock*/ -+ dc_service_memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); -+ -+ pxl_clk_params.target_pixel_clock = requested_clk_khz; -+ pxl_clk_params.pll_id = base->id; -+ -+ dal_bios_parser_program_display_engine_pll(bp, &pxl_clk_params); -+ -+ if (dc->dfs_bypass_enabled) { -+ -+ /* Cache the fixed display clock*/ -+ dc->dfs_bypass_disp_clk = -+ pxl_clk_params.dfs_bypass_display_clock; -+ } -+ -+ /* from power down, we need mark the clock state as ClocksStateNominal -+ * from HWReset, so when resume we will call pplib voltage regulator.*/ -+ if (requested_clk_khz == 0) -+ base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; -+} -+ -+static void set_clock_state( -+ struct display_clock *dc, -+ struct display_clock_state clk_state) -+{ -+ struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); -+ -+ disp_clk->clock_state = clk_state; -+} -+ -+static struct display_clock_state get_clock_state( -+ struct display_clock *dc) -+{ -+ struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); -+ -+ return disp_clk->clock_state; -+} -+ -+static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -+{ -+ return DCE110_DFS_BYPASS_THRESHOLD_KHZ; -+} -+ -+static const struct display_clock_funcs funcs = { -+ .destroy = destroy, -+ .calculate_min_clock = calculate_min_clock, -+ .get_clock = get_clock, -+ .get_clock_state = get_clock_state, -+ .get_dfs_bypass_threshold = get_dfs_bypass_threshold, -+ .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, -+ .get_min_clocks_state = get_min_clocks_state, -+ .get_required_clocks_state = get_required_clocks_state, -+ .get_validation_clock = get_validation_clock, -+ .set_clock = set_clock, -+ .set_clock_state = set_clock_state, -+ .set_dp_ref_clock_source = NULL, -+ .set_min_clocks_state = set_min_clocks_state, -+ .store_max_clocks_state = store_max_clocks_state, -+ .validate = NULL, -+}; -+ -+static bool dal_display_clock_dce110_construct( -+ struct display_clock_dce110 *dc110, -+ struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct display_clock *dc_base = &dc110->disp_clk_base; -+ -+ if (NULL == as) -+ return false; -+ -+ if (!dal_display_clock_construct_base(dc_base, ctx, as)) -+ return false; -+ -+ dc_base->funcs = &funcs; -+ -+ dc110->dfs_bypass_disp_clk = 0; -+ -+ if (!display_clock_integrated_info_construct(dc110, as)) -+ dal_logger_write(dc_base->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "Cannot obtain VBIOS integrated info\n"); -+ -+ dc110->gpu_pll_ss_percentage = 0; -+ dc110->gpu_pll_ss_divider = 1000; -+ dc110->ss_on_gpu_pll = false; -+ -+ dc_base->id = CLOCK_SOURCE_ID_DFS; -+/* Initially set max clocks state to nominal. This should be updated by -+ * via a pplib call to DAL IRI eventually calling a -+ * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in -+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ -+ dc110->max_clks_state = CLOCKS_STATE_NOMINAL; -+ -+ dal_divider_range_construct( -+ ÷r_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( -+ ÷r_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( -+ ÷r_ranges[DIVIDER_RANGE_03], -+ DIVIDER_RANGE_03_START, -+ DIVIDER_RANGE_03_STEP_SIZE, -+ DIVIDER_RANGE_03_BASE_DIVIDER_ID, -+ DIVIDER_RANGE_MAX_DIVIDER_ID); -+ -+ { -+ uint32_t ss_info_num = -+ dal_adapter_service_get_ss_info_num( -+ as, -+ AS_SIGNAL_TYPE_GPU_PLL); -+ -+ if (ss_info_num) { -+ struct spread_spectrum_info info; -+ bool result; -+ -+ dc_service_memset(&info, 0, sizeof(info)); -+ -+ result = -+ dal_adapter_service_get_ss_info( -+ as, -+ AS_SIGNAL_TYPE_GPU_PLL, -+ 0, -+ &info); -+ -+ /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS -+ * even if SS not enabled and in that case -+ * SSInfo.spreadSpectrumPercentage !=0 would be sign -+ * that SS is enabled -+ */ -+ if (result && info.spread_spectrum_percentage != 0) { -+ dc110->ss_on_gpu_pll = true; -+ dc110->gpu_pll_ss_divider = -+ info.spread_percentage_divider; -+ -+ if (info.type.CENTER_MODE == 0) { -+ /* Currently for DP Reference clock we -+ * need only SS percentage for -+ * downspread */ -+ dc110->gpu_pll_ss_percentage = -+ info.spread_spectrum_percentage; -+ } -+ } -+ -+ } -+ } -+ -+ return true; -+} -+ -+/***************************************************************************** -+ * public functions -+ *****************************************************************************/ -+ -+struct display_clock *dal_display_clock_dce110_create( -+ struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ struct display_clock_dce110 *dc110; -+ -+ dc110 = dc_service_alloc(ctx, sizeof(struct display_clock_dce110)); -+ -+ if (dc110 == NULL) -+ return NULL; -+ -+ if (dal_display_clock_dce110_construct(dc110, ctx, as)) -+ return &dc110->disp_clk_base; -+ -+ dc_service_free(ctx, dc110); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h -new file mode 100644 -index 0000000..0cdc7b5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h -@@ -0,0 +1,53 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ -+#define __DAL_DISPLAY_CLOCK_DCE110_H__ -+ -+#include "gpu/display_clock.h" -+ -+struct display_clock_dce110 { -+ struct display_clock disp_clk_base; -+ /* Max display block clocks state*/ -+ enum clocks_state max_clks_state; -+ bool use_max_disp_clk; -+ uint32_t dentist_vco_freq_khz; -+ /* Cache the status of DFS-bypass feature*/ -+ bool dfs_bypass_enabled; -+ /* GPU PLL SS percentage (if down-spread enabled) */ -+ uint32_t gpu_pll_ss_percentage; -+ /* GPU PLL SS percentage Divider (100 or 1000) */ -+ uint32_t gpu_pll_ss_divider; -+ /* Flag for Enabled SS on GPU PLL */ -+ bool ss_on_gpu_pll; -+ /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. -+ * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ -+ uint32_t dfs_bypass_disp_clk; -+ struct display_clock_state clock_state; -+}; -+ -+#define DCLCK110_FROM_BASE(dc_base) \ -+ container_of(dc_base, struct display_clock_dce110, disp_clk_base) -+ -+#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c -new file mode 100644 -index 0000000..7fd5984 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c -@@ -0,0 +1,383 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "include/logger_interface.h" -+#include "include/adapter_service_interface.h" -+#include "include/fixed32_32.h" -+ -+#include "ext_clock_source_dce110.h" -+ -+/** -+ * In this file ECS stands for External Clock Source. -+ */ -+ -+#define ECS110_FROM_BASE(clk_src_ptr)\ -+ container_of(\ -+ container_of((clk_src_ptr), struct ext_clock_source, base), \ -+ struct ext_clock_source_dce110, base) -+ -+#define ECS_WARNING(...) \ -+ dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \ -+ LOG_MINOR_COMPONENT_GPU, __VA_ARGS__) -+ -+#define ECS_ERROR(...) \ -+ dal_logger_write(ctx->logger, LOG_MAJOR_ERROR, \ -+ LOG_MINOR_COMPONENT_GPU, __VA_ARGS__) -+ -+/****************************************************************************** -+ * implementation functions -+ *****************************************************************************/ -+ -+static uint32_t controller_id_to_index( -+ struct clock_source *clk_src, -+ enum controller_id controller_id) -+{ -+ struct dc_context *ctx = clk_src->ctx; -+ uint32_t index = 0; -+ -+ switch (controller_id) { -+ case CONTROLLER_ID_D0: -+ index = 0; -+ break; -+ case CONTROLLER_ID_D1: -+ index = 1; -+ break; -+ case CONTROLLER_ID_D2: -+ index = 2; -+ break; -+ default: -+ ECS_ERROR("%s: invalid input controller_id = %d!\n", -+ __func__, controller_id); -+ break; -+ } -+ -+ return index; -+} -+ -+/* Adjust pixel rate by DTO programming (used for DisplayPort) */ -+static bool adjust_dto_pixel_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t requested_pix_clk_hz) -+{ -+ struct ext_clock_source_dce110 *ecs110 = -+ ECS110_FROM_BASE(clk_src); -+ struct dc_context *ctx = clk_src->ctx; -+ uint32_t index; -+ uint32_t dto_phase_reg; -+ uint32_t dto_modulo_reg; -+ uint32_t dto_phase_rnd; -+ uint32_t addr; -+ uint32_t value; -+ struct fixed32_32 dto_phase; -+ -+ if (NULL == pix_clk_params) { -+ ECS_WARNING("%s: invalid input!\n", __func__); -+ return false; -+ } -+ -+ index = controller_id_to_index(clk_src, pix_clk_params->controller_id); -+ -+ addr = ecs110->registers[index].dp_dtox_phase; -+ dto_phase_reg = dal_read_reg(ctx, addr); -+ -+ addr = ecs110->registers[index].dp_dtox_modulo; -+ dto_modulo_reg = dal_read_reg(ctx, addr); -+ -+ if (!dto_modulo_reg) { -+ ECS_WARNING("%s: current modulo is zero!\n", __func__); -+ return false; -+ } -+ -+ dto_phase = dal_fixed32_32_from_int(requested_pix_clk_hz); -+ -+ dto_phase = dal_fixed32_32_mul_int(dto_phase, dto_modulo_reg); -+ -+ dto_phase = dal_fixed32_32_div_int(dto_phase, -+ pix_clk_params->dp_ref_clk * 1000); -+ -+ dto_phase_rnd = dal_fixed32_32_round(dto_phase); -+ -+ /* Program DTO Phase */ -+ if (dto_phase_reg != dto_phase_rnd) { -+ /* If HW De-Spreading enabled on DP REF clock and if there will -+ * be case when Pixel rate > average DP Ref Clock, then need to -+ * disable de-spread for DP DTO (ATOMBIOS will program MODULO -+ * for average DP REF clock so no further SW adjustment -+ * needed) */ -+ if (pix_clk_params->de_spread_params.hw_dso_n_dp_ref_clk) { -+ -+ addr = ecs110->registers[index].crtcx_pixel_rate_cntl; -+ value = dal_read_reg(ctx, addr); -+ -+ if (requested_pix_clk_hz / 1000 > -+ pix_clk_params-> -+ de_spread_params.avg_dp_ref_clk_khz) { -+ -+ set_reg_field_value(value, 1, -+ CRTC0_PIXEL_RATE_CNTL, -+ DP_DTO0_DS_DISABLE); -+ } else { -+ set_reg_field_value(value, 0, -+ CRTC0_PIXEL_RATE_CNTL, -+ DP_DTO0_DS_DISABLE); -+ } -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ value = 0; -+ addr = ecs110->registers[index].dp_dtox_phase; -+ -+ set_reg_field_value(value, dto_phase_rnd, -+ DP_DTO0_PHASE, -+ DP_DTO0_PHASE); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ return true; -+} -+ -+/** -+ * Retrieve Pixel Rate (in Hz) from HW registers already programmed. -+ */ -+uint32_t retrieve_dp_pixel_rate_from_display_pll( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *params) -+{ -+ struct dc_context *ctx = clk_src->ctx; -+ -+ /* TODO: update when DAL2 implements this function. */ -+ DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, "%s\n", __func__); -+ return 0; -+} -+ -+static uint32_t retrieve_dto_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *params) -+{ -+ struct ext_clock_source_dce110 *ecs110 = -+ ECS110_FROM_BASE(clk_src); -+ struct dc_context *ctx = clk_src->ctx; -+ uint32_t index; -+ uint32_t dto_phase_reg; -+ uint32_t dto_modulo_reg; -+ uint32_t addr; -+ uint32_t value; -+ uint32_t pix_rate_hz; -+ struct fixed32_32 p_clk; -+ -+ if (params == NULL) -+ return 0; -+ -+ if (NULL == params) { -+ ECS_WARNING("%s: invalid input!\n", __func__); -+ return false; -+ } -+ -+ index = controller_id_to_index(clk_src, params->controller_id); -+ -+ addr = ecs110->registers[index].crtcx_pixel_rate_cntl; -+ value = dal_read_reg(ctx, addr); -+ -+ if (get_reg_field_value(value, CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE) -+ == 1) { -+ -+ addr = ecs110->registers[index].dp_dtox_phase; -+ dto_phase_reg = dal_read_reg(ctx, addr); -+ -+ addr = ecs110->registers[index].dp_dtox_modulo; -+ dto_modulo_reg = dal_read_reg(ctx, addr); -+ -+ if (!dto_modulo_reg) { -+ ECS_WARNING("%s: current modulo is zero!\n", __func__); -+ return 0; -+ } -+ -+ /* Calculate pixel clock from DTO Phase & Modulo*/ -+ p_clk = dal_fixed32_32_from_int(params->dp_ref_clk * 1000); -+ -+ p_clk = dal_fixed32_32_mul_int(p_clk, dto_phase_reg); -+ -+ p_clk = dal_fixed32_32_div_int(p_clk, dto_modulo_reg); -+ -+ pix_rate_hz = dal_fixed32_32_round(p_clk); -+ } else { -+ pix_rate_hz = retrieve_dp_pixel_rate_from_display_pll(clk_src, -+ params); -+ } -+ -+ return pix_rate_hz; -+} -+ -+/****************************************************************************** -+ * create/destroy functions -+ *****************************************************************************/ -+ -+static void destruct(struct ext_clock_source_dce110 *ecs110) -+{ -+ struct ext_clock_source *ext_cs = &ecs110->base; -+ struct clock_source *base = &ext_cs->base; -+ -+ if (NULL != base->dp_ss_params) { -+ dc_service_free(base->ctx, base->dp_ss_params); -+ base->dp_ss_params = NULL; -+ } -+ -+ dc_service_free(base->ctx, ecs110->registers); -+ ecs110->registers = NULL; -+} -+ -+ -+static void destroy(struct clock_source **clk_src) -+{ -+ struct ext_clock_source_dce110 *ecs110; -+ -+ ecs110 = ECS110_FROM_BASE(*clk_src); -+ -+ destruct(ecs110); -+ -+ dc_service_free((*clk_src)->ctx, ecs110); -+ -+ *clk_src = NULL; -+} -+ -+static const struct clock_source_impl funcs = { -+ .program_pix_clk = dal_ext_clock_source_program_pix_clk, -+ .adjust_pll_pixel_rate = dal_clock_source_base_adjust_pll_pixel_rate, -+ .adjust_dto_pixel_rate = adjust_dto_pixel_rate, -+ .retrieve_pll_pix_rate_hz = -+ dal_clock_source_base_retrieve_pll_pix_rate_hz, -+ .get_pix_clk_dividers = dal_ext_clock_source_get_pix_clk_dividers, -+ .destroy = destroy, -+ .retrieve_dto_pix_rate_hz = retrieve_dto_pix_rate_hz, -+ .power_down_pll = dal_ext_clock_source_power_down_pll -+}; -+ -+static bool construct( -+ struct ext_clock_source_dce110 *ecs110, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct dc_context *ctx = clk_src_init_data->ctx; -+ struct ext_clock_source *ext_cs = &ecs110->base; -+ struct clock_source *base = &ext_cs->base; -+ uint32_t controllers_num; -+ struct registers *registers; -+ -+ /* None of the base construct() functions allocates memory. -+ * That means, in case of error, we don't have to free memory -+ * allocated by base. */ -+ if (!dal_ext_clock_source_construct(ext_cs, clk_src_init_data)) -+ return false; -+ -+ base->funcs = &funcs; -+ -+ base->is_gen_lock_capable = false; -+ base->dp_ss_params = NULL; -+ base->dp_ss_params_cnt = 0; -+ -+ ecs110->registers = NULL; -+ -+ if (base->clk_src_id != CLOCK_SOURCE_ID_EXTERNAL) { -+ ECS_ERROR("ECS110:Invalid ClockSourceId = %d!\n", -+ base->clk_src_id); -+ return false; -+ } -+ -+ controllers_num = dal_adapter_service_get_controllers_num( -+ base->adapter_service); -+ -+ if (controllers_num <= 0 || controllers_num > 3) { -+ ECS_ERROR("ECS110:Invalid number of controllers = %d!\n", -+ controllers_num); -+ return false; -+ } -+ -+ ecs110->registers = (struct registers *) -+ (dc_service_alloc(clk_src_init_data->ctx, sizeof(struct registers) * controllers_num)); -+ -+ if (ecs110->registers == NULL) { -+ ECS_ERROR("ECS110:Failed to allocate 'registers'!\n"); -+ return false; -+ } -+ -+ registers = ecs110->registers; -+ -+ /* Assign register address. No break between cases */ -+ switch (controllers_num) { -+ case 3: -+ registers[2].dp_dtox_phase = mmDP_DTO2_PHASE; -+ registers[2].dp_dtox_modulo = mmDP_DTO2_MODULO; -+ registers[2].crtcx_pixel_rate_cntl = mmCRTC2_PIXEL_RATE_CNTL; -+ /* fallthrough */ -+ case 2: -+ registers[1].dp_dtox_phase = mmDP_DTO1_PHASE; -+ registers[1].dp_dtox_modulo = mmDP_DTO1_MODULO; -+ registers[1].crtcx_pixel_rate_cntl = mmCRTC1_PIXEL_RATE_CNTL; -+ /* fallthrough */ -+ case 1: -+ registers[0].dp_dtox_phase = mmDP_DTO0_PHASE; -+ registers[0].dp_dtox_modulo = mmDP_DTO0_MODULO; -+ registers[0].crtcx_pixel_rate_cntl = mmCRTC0_PIXEL_RATE_CNTL; -+ break; -+ -+ default: -+ /* We can not get here because we checked number of -+ * controllers already. */ -+ break; -+ } -+ -+ dal_clock_source_get_ss_info_from_atombios( -+ base, -+ AS_SIGNAL_TYPE_DISPLAY_PORT, -+ &base->dp_ss_params, -+ &base->dp_ss_params_cnt); -+ -+ return true; -+} -+ -+ -+struct clock_source *dal_ext_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct ext_clock_source_dce110 *ecs110; -+ -+ ecs110 = dc_service_alloc(clk_src_init_data->ctx, sizeof(struct ext_clock_source_dce110)); -+ -+ if (ecs110 == NULL) -+ return NULL; -+ -+ if (!construct(ecs110, clk_src_init_data)) { -+ dc_service_free(clk_src_init_data->ctx, ecs110); -+ return NULL; -+ } -+ -+ return &ecs110->base.base; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h -new file mode 100644 -index 0000000..4ea2ae2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.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_EXT_CLOCK_SOURCE_DCE110__ -+#define __DAL_EXT_CLOCK_SOURCE_DCE110__ -+ -+#include "../ext_clock_source.h" -+ -+struct ext_clock_source_dce110 { -+ struct ext_clock_source base; -+ struct registers *registers; -+}; -+ -+struct clock_source *dal_ext_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data); -+ -+#endif /*__DAL_EXT_CLOCK_SOURCE_DCE110__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c -new file mode 100644 -index 0000000..d83eea3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c -@@ -0,0 +1,718 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#include "include/logger_interface.h" -+#include "include/bios_parser_interface.h" -+#include "include/adapter_service_interface.h" -+#include "include/fixed32_32.h" -+#include "gpu/calc_pll_clock_source.h" -+#include "gpu/clock_source.h" -+#include "gpu/pll_clock_source.h" -+ -+#include "gpu/dce110/pll_clock_source_dce110.h" -+ -+enum fract_fb_divider_dec_points { -+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM = 6, -+ FRACT_FB_DIVIDER_DEC_POINTS_NO_DS_NUM = 1, -+}; -+ -+#define FROM_CLK_SRC(clk_src_ptr)\ -+ container_of(\ -+ container_of((clk_src_ptr), struct pll_clock_source, base), \ -+ struct pll_clock_source_dce110, base) -+ -+static bool calculate_ss( -+ struct pll_clock_source_dce110 *clk_src, -+ 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; -+ -+ -+ dc_service_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 disable_spread_spectrum(struct pll_clock_source_dce110 *clk_src) -+{ -+ enum bp_result result; -+ struct bp_spread_spectrum_parameters bp_ss_params = {0}; -+ struct clock_source *clock_source = NULL; -+ -+ clock_source = &clk_src->base.base; -+ bp_ss_params.pll_id = clock_source->clk_src_id; -+ -+ /*Call ASICControl to process ATOMBIOS Exec table*/ -+ result = dal_bios_parser_enable_spread_spectrum_on_ppll( -+ clock_source->bios_parser, -+ &bp_ss_params, -+ false); -+ -+ return result == BP_RESULT_OK; -+} -+ -+static bool enable_spread_spectrum( -+ struct pll_clock_source_dce110 *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; -+ struct clock_source *clock_source = NULL; -+ const struct spread_spectrum_data *ss_data = NULL; -+ -+ clock_source = &clk_src->base.base; -+ ss_data = dal_clock_source_get_ss_data_entry( -+ clock_source, -+ 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(clk_src, 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 = clock_source->clk_src_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 != -+ dal_bios_parser_enable_spread_spectrum_on_ppll( -+ clock_source->bios_parser, -+ &bp_params, -+ true)) -+ return false; -+ } else -+ return false; -+ } -+ return true; -+} -+ -+static void program_pixel_clk_resync( -+ struct pll_clock_source_dce110 *clk_src, -+ enum signal_type signal_type, -+ enum dc_color_depth colordepth) -+{ -+ struct clock_source *clock_source = NULL; -+ uint32_t value = 0; -+ -+ clock_source = &clk_src->base.base; -+ -+ value = dal_read_reg( -+ clock_source->ctx, -+ clk_src->pixclkx_resync_cntl); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ PIXCLK1_RESYNC_CNTL, -+ DCCG_DEEP_COLOR_CNTL1); -+ -+ /* -+ 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) -+ 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) -+ 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) -+ 48 bit mode: TMDS clock = 2 x pixel clock (2:1) -+ */ -+ if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) -+ return; -+ -+ switch (colordepth) { -+ case COLOR_DEPTH_888: -+ set_reg_field_value( -+ value, -+ 0, -+ PIXCLK1_RESYNC_CNTL, -+ DCCG_DEEP_COLOR_CNTL1); -+ break; -+ case COLOR_DEPTH_101010: -+ set_reg_field_value( -+ value, -+ 1, -+ PIXCLK1_RESYNC_CNTL, -+ DCCG_DEEP_COLOR_CNTL1); -+ break; -+ case COLOR_DEPTH_121212: -+ set_reg_field_value( -+ value, -+ 2, -+ PIXCLK1_RESYNC_CNTL, -+ DCCG_DEEP_COLOR_CNTL1); -+ break; -+ case COLOR_DEPTH_161616: -+ set_reg_field_value( -+ value, -+ 3, -+ PIXCLK1_RESYNC_CNTL, -+ DCCG_DEEP_COLOR_CNTL1); -+ break; -+ default: -+ break; -+ } -+ -+ dal_write_reg( -+ clock_source->ctx, -+ clk_src->pixclkx_resync_cntl, -+ value); -+} -+ -+static bool program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct pll_clock_source_dce110 *pll_clk_src_dce110 = -+ FROM_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 (!dc_is_dp_signal(pix_clk_params->signal_type)) -+ disable_spread_spectrum(pll_clk_src_dce110); -+ -+ /*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->clk_src_id; -+ bp_pc_params.target_pixel_clock = -+ pll_settings->actual_pix_clk; -+ bp_pc_params.reference_divider = pll_settings->reference_divider; -+ bp_pc_params.feedback_divider = pll_settings->feedback_divider; -+ bp_pc_params.fractional_feedback_divider = -+ pll_settings->fract_feedback_divider; -+ bp_pc_params.pixel_clock_post_divider = -+ pll_settings->pix_clk_post_divider; -+ bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; -+ bp_pc_params.signal_type = pix_clk_params->signal_type; -+ bp_pc_params.dvo_config = pix_clk_params->dvo_cfg; -+ bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = -+ pll_settings->use_external_clk; -+ -+ if (dal_bios_parser_set_pixel_clock(clk_src->bios_parser, -+ &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 (pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( -+ pix_clk_params->signal_type)) -+ if (!enable_spread_spectrum(pll_clk_src_dce110, -+ pix_clk_params->signal_type, -+ pll_settings)) -+ return false; -+ -+/* Resync deep color DTO */ -+ program_pixel_clk_resync(pll_clk_src_dce110, -+ pix_clk_params->signal_type, -+ pix_clk_params->color_depth); -+ -+ return true; -+} -+ -+static void ss_info_from_atombios_destroy( -+ struct pll_clock_source_dce110 *clk_src) -+{ -+ struct clock_source *cs = &clk_src->base.base; -+ -+ if (NULL != cs->ep_ss_params) { -+ dc_service_free(cs->ctx, cs->ep_ss_params); -+ cs->ep_ss_params = NULL; -+ } -+ -+ if (NULL != cs->dp_ss_params) { -+ dc_service_free(cs->ctx, cs->dp_ss_params); -+ cs->dp_ss_params = NULL; -+ } -+ -+ if (NULL != cs->hdmi_ss_params) { -+ dc_service_free(cs->ctx, cs->hdmi_ss_params); -+ cs->hdmi_ss_params = NULL; -+ } -+ -+ if (NULL != cs->dvi_ss_params) { -+ dc_service_free(cs->ctx, cs->dvi_ss_params); -+ cs->dvi_ss_params = NULL; -+ } -+} -+ -+static void destruct( -+ struct pll_clock_source_dce110 *pll_cs) -+{ -+ ss_info_from_atombios_destroy(pll_cs); -+ -+ if (NULL != pll_cs->registers) { -+ dc_service_free(pll_cs->base.base.ctx, pll_cs->registers); -+ pll_cs->registers = NULL; -+ } -+} -+ -+static void destroy(struct clock_source **clk_src) -+{ -+ struct pll_clock_source_dce110 *pll_clk_src; -+ -+ pll_clk_src = FROM_CLK_SRC(*clk_src); -+ -+ destruct(pll_clk_src); -+ dc_service_free((*clk_src)->ctx, pll_clk_src); -+ -+ *clk_src = NULL; -+} -+ -+/** -+ * 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 get_pix_clk_dividers( -+ struct clock_source *cs, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct pll_clock_source_dce110 *pll_cs_110 = FROM_CLK_SRC(cs); -+ struct pll_clock_source *pll_base = &pll_cs_110->base; -+ uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; -+ uint32_t addr = 0; -+ uint32_t value = 0; -+ uint32_t field = 0; -+ -+ if (pix_clk_params == NULL || pll_settings == NULL -+ || pix_clk_params->requested_pix_clk == 0) { -+ dal_logger_write(cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameters!!\n", __func__); -+ return pll_calc_error; -+ } -+ -+ dc_service_memset(pll_settings, 0, sizeof(*pll_settings)); -+ -+ /* Check if reference clock is external (not pcie/xtalin) -+ * HW Dce80 spec: -+ * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB -+ * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ -+ addr = pll_cs_110->pxpll_cntl; -+ value = dal_read_reg(cs->ctx, addr); -+ field = get_reg_field_value(value, PLL_CNTL, PLL_REF_DIV_SRC); -+ pll_settings->use_external_clk = (field > 1); -+ -+ /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always -+ * (we do not care any more from SI for some older DP Sink which -+ * does not report SS support, no known issues) */ -+ if ((pix_clk_params->flags.ENABLE_SS) || -+ (dc_is_dp_signal(pix_clk_params->signal_type))) { -+ -+ const struct spread_spectrum_data *ss_data = -+ dal_clock_source_get_ss_data_entry( -+ cs, -+ 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 (!dal_pll_clock_source_adjust_pix_clk(pll_base, -+ pix_clk_params, pll_settings)) { -+ /* Should never happen, ASSERT and fill up values to be able -+ * to continue. */ -+ dal_logger_write(cs->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Failed to adjust pixel clock!!", __func__); -+ pll_settings->actual_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ pll_settings->adjusted_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ -+ if (dc_is_dp_signal(pix_clk_params->signal_type)) -+ pll_settings->adjusted_pix_clk = 100000; -+ } -+ -+ /* Calculate Dividers */ -+ if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) -+ /*Calculate Dividers by HDMI object, no SS case or SS case */ -+ pll_calc_error = -+ dal_clock_source_calculate_pixel_clock_pll_dividers( -+ &pll_cs_110->calc_pll_clock_source_hdmi, -+ pll_settings); -+ else -+ /*Calculate Dividers by default object, no SS case or SS case */ -+ pll_calc_error = -+ dal_clock_source_calculate_pixel_clock_pll_dividers( -+ &pll_cs_110->calc_pll_clock_source, -+ pll_settings); -+ -+ return pll_calc_error; -+} -+ -+static const struct clock_source_impl funcs = { -+ .program_pix_clk = program_pix_clk, -+ .adjust_pll_pixel_rate = NULL, -+ .adjust_dto_pixel_rate = NULL, -+ .retrieve_pll_pix_rate_hz = NULL, -+ .get_pix_clk_dividers = get_pix_clk_dividers, -+ .destroy = destroy, -+ .retrieve_dto_pix_rate_hz = NULL, -+ .power_down_pll = dal_pll_clock_source_power_down_pll, -+}; -+ -+static void ss_info_from_atombios_create( -+ struct pll_clock_source_dce110 *clk_src) -+{ -+ struct clock_source *base = &clk_src->base.base; -+ -+ dal_clock_source_get_ss_info_from_atombios( -+ base, -+ AS_SIGNAL_TYPE_DISPLAY_PORT, -+ &base->dp_ss_params, -+ &base->dp_ss_params_cnt); -+ dal_clock_source_get_ss_info_from_atombios( -+ base, -+ AS_SIGNAL_TYPE_LVDS, -+ &base->ep_ss_params, -+ &base->ep_ss_params_cnt); -+ dal_clock_source_get_ss_info_from_atombios( -+ base, -+ AS_SIGNAL_TYPE_HDMI, -+ &base->hdmi_ss_params, -+ &base->hdmi_ss_params_cnt); -+ dal_clock_source_get_ss_info_from_atombios( -+ base, -+ AS_SIGNAL_TYPE_DVI, -+ &base->dvi_ss_params, -+ &base->dvi_ss_params_cnt); -+} -+ -+ -+static bool construct( -+ struct pll_clock_source_dce110 *pll_cs_dce110, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ uint32_t controllers_num = 1; -+ -+/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */ -+ struct calc_pll_clock_source_init_data calc_pll_cs_init_data = { -+ dal_adapter_service_get_bios_parser(clk_src_init_data->as), -+ 1, /* minPixelClockPLLPostDivider */ -+ PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, -+ /* maxPixelClockPLLPostDivider*/ -+ 1,/* minPLLRefDivider*/ -+ PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ -+ 0, -+/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ -+ 0, -+/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ -+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, -+/*numberOfFractFBDividerDecimalPoints*/ -+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, -+/*number of decimal point to round off for fractional feedback divider value*/ -+ clk_src_init_data->ctx -+ }; -+/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */ -+ struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi = { -+ dal_adapter_service_get_bios_parser(clk_src_init_data->as), -+ 1, /* minPixelClockPLLPostDivider */ -+ PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, -+ /* maxPixelClockPLLPostDivider*/ -+ 1,/* minPLLRefDivider*/ -+ PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ -+ 13500, -+ /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ -+ 27000, -+ /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ -+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, -+ /*numberOfFractFBDividerDecimalPoints*/ -+ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, -+/*number of decimal point to round off for fractional feedback divider value*/ -+ clk_src_init_data->ctx -+ }; -+ -+ struct pll_clock_source *base = &pll_cs_dce110->base; -+ struct clock_source *superbase = &base->base; -+ -+ if (!dal_pll_clock_source_construct(base, clk_src_init_data)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ superbase->funcs = &funcs; -+ -+ superbase->is_clock_source_with_fixed_freq = false; -+ superbase->clk_sharing_lvl = CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE; -+ -+ pll_cs_dce110->registers = NULL; -+ -+/* PLL3 should not be used although it is available in online register spec */ -+ if ((superbase->clk_src_id != CLOCK_SOURCE_ID_PLL1) -+ && (superbase->clk_src_id != CLOCK_SOURCE_ID_PLL0)) { -+ -+ -+ ASSERT_CRITICAL(false); -+ goto failure; -+ } -+ -+/* From Driver side PLL0 is now used for non DP timing also, -+ * so it supports all signals except Wireless. -+ * Wireless signal type does not require a PLL clock source, -+ * so we will not waste a clock on it. -+*/ -+ superbase->output_signals &= ~SIGNAL_TYPE_WIRELESS; -+ -+ if (!dal_calc_pll_clock_source_max_vco_init( -+ &pll_cs_dce110->calc_pll_clock_source, -+ &calc_pll_cs_init_data)) { -+ ASSERT_CRITICAL(false); -+ goto failure; -+ } -+ -+ if (base->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 (base->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 (!dal_calc_pll_clock_source_max_vco_init( -+ &pll_cs_dce110->calc_pll_clock_source_hdmi, -+ &calc_pll_cs_init_data_hdmi)) { -+ ASSERT_CRITICAL(false); -+ goto failure; -+ } -+ -+ switch (superbase->clk_src_id) { -+ case CLOCK_SOURCE_ID_PLL0: -+ pll_cs_dce110->pixclkx_resync_cntl = mmPIXCLK0_RESYNC_CNTL; -+ pll_cs_dce110->ppll_fb_div = mmBPHYC_PLL0_PLL_FB_DIV; -+ pll_cs_dce110->ppll_ref_div = mmBPHYC_PLL0_PLL_REF_DIV; -+ pll_cs_dce110->ppll_post_div = mmBPHYC_PLL0_PLL_POST_DIV; -+ pll_cs_dce110->pxpll_ds_cntl = mmBPHYC_PLL0_PLL_DS_CNTL; -+ pll_cs_dce110->pxpll_ss_cntl = mmBPHYC_PLL0_PLL_SS_CNTL; -+ pll_cs_dce110->pxpll_ss_dsfrac = -+ mmBPHYC_PLL0_PLL_SS_AMOUNT_DSFRAC; -+ pll_cs_dce110->pxpll_cntl = mmBPHYC_PLL0_PLL_CNTL; -+ break; -+ case CLOCK_SOURCE_ID_PLL1: -+ pll_cs_dce110->pixclkx_resync_cntl = mmPIXCLK1_RESYNC_CNTL; -+ pll_cs_dce110->ppll_fb_div = mmBPHYC_PLL1_PLL_FB_DIV; -+ pll_cs_dce110->ppll_ref_div = mmBPHYC_PLL1_PLL_REF_DIV; -+ pll_cs_dce110->ppll_post_div = mmBPHYC_PLL1_PLL_POST_DIV; -+ pll_cs_dce110->pxpll_ds_cntl = mmBPHYC_PLL1_PLL_DS_CNTL; -+ pll_cs_dce110->pxpll_ss_cntl = mmBPHYC_PLL1_PLL_SS_CNTL; -+ pll_cs_dce110->pxpll_ss_dsfrac = -+ mmBPHYC_PLL1_PLL_SS_AMOUNT_DSFRAC; -+ pll_cs_dce110->pxpll_cntl = mmBPHYC_PLL1_PLL_CNTL; -+ break; -+ case CLOCK_SOURCE_ID_PLL2: -+ /* PLL2 is not supported */ -+ default: -+ break; -+ } -+ -+ controllers_num = dal_adapter_service_get_controllers_num( -+ superbase->adapter_service); -+ -+ pll_cs_dce110->registers = dc_service_alloc( -+ clk_src_init_data->ctx, -+ sizeof(struct registers) * controllers_num); -+ -+ if (pll_cs_dce110->registers == NULL) { -+ ASSERT_CRITICAL(false); -+ goto failure; -+ } -+ -+ /* Assign register address. No break between cases */ -+ switch (controllers_num) { -+ case 6: -+ pll_cs_dce110->registers[5].dp_dtox_phase = -+ mmDP_DTO5_PHASE; -+ pll_cs_dce110->registers[5].dp_dtox_modulo = -+ mmDP_DTO5_MODULO; -+ pll_cs_dce110->registers[5].crtcx_pixel_rate_cntl = -+ mmCRTC5_PIXEL_RATE_CNTL; -+ /* fall through*/ -+ -+ case 5: -+ pll_cs_dce110->registers[4].dp_dtox_phase = -+ mmDP_DTO4_PHASE; -+ pll_cs_dce110->registers[4].dp_dtox_modulo = -+ mmDP_DTO4_MODULO; -+ pll_cs_dce110->registers[4].crtcx_pixel_rate_cntl = -+ mmCRTC4_PIXEL_RATE_CNTL; -+ /* fall through*/ -+ -+ case 4: -+ pll_cs_dce110->registers[3].dp_dtox_phase = -+ mmDP_DTO3_PHASE; -+ pll_cs_dce110->registers[3].dp_dtox_modulo = -+ mmDP_DTO3_MODULO; -+ pll_cs_dce110->registers[3].crtcx_pixel_rate_cntl = -+ mmCRTC3_PIXEL_RATE_CNTL; -+ /* fall through*/ -+ -+ case 3: -+ pll_cs_dce110->registers[2].dp_dtox_phase = -+ mmDP_DTO2_PHASE; -+ pll_cs_dce110->registers[2].dp_dtox_modulo = -+ mmDP_DTO2_MODULO; -+ pll_cs_dce110->registers[2].crtcx_pixel_rate_cntl = -+ mmCRTC2_PIXEL_RATE_CNTL; -+ /* fall through*/ -+ -+ case 2: -+ pll_cs_dce110->registers[1].dp_dtox_phase = -+ mmDP_DTO1_PHASE; -+ pll_cs_dce110->registers[1].dp_dtox_modulo = -+ mmDP_DTO1_MODULO; -+ pll_cs_dce110->registers[1].crtcx_pixel_rate_cntl = -+ mmCRTC1_PIXEL_RATE_CNTL; -+ /* fall through*/ -+ -+ case 1: -+ pll_cs_dce110->registers[0].dp_dtox_phase = -+ mmDP_DTO0_PHASE; -+ pll_cs_dce110->registers[0].dp_dtox_modulo = -+ mmDP_DTO0_MODULO; -+ pll_cs_dce110->registers[0].crtcx_pixel_rate_cntl = -+ mmCRTC0_PIXEL_RATE_CNTL; -+ -+ break; -+ -+ default: -+ ASSERT_CRITICAL(false); -+ goto failure; -+ } -+ -+ ss_info_from_atombios_create(pll_cs_dce110); -+ -+ return true; -+ -+failure: -+ destruct(pll_cs_dce110); -+ -+ return false; -+} -+ -+struct clock_source *dal_pll_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct pll_clock_source_dce110 *clk_src = -+ dc_service_alloc(clk_src_init_data->ctx, sizeof(struct pll_clock_source_dce110)); -+ -+ if (clk_src == NULL) -+ return NULL; -+ -+ if (!construct(clk_src, clk_src_init_data)) { -+ dc_service_free(clk_src_init_data->ctx, clk_src); -+ return NULL; -+ } -+ return &(clk_src->base.base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h -new file mode 100644 -index 0000000..166b29a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h -@@ -0,0 +1,55 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_PLL_CLOCK_SOURCE_DCE110_H__ -+#define __DAL_PLL_CLOCK_SOURCE_DCE110_H__ -+ -+#include "../pll_clock_source.h" -+#include "../calc_pll_clock_source.h" -+ -+struct pll_clock_source_dce110 { -+ struct pll_clock_source base; -+ -+ struct calc_pll_clock_source calc_pll_clock_source; -+/* object for normal circumstances, SS = 0 or SS >= 0.2% (LVDS or DP) -+ * or even for SS =~0.02 (DVI) */ -+ -+ struct calc_pll_clock_source calc_pll_clock_source_hdmi; -+/* object for HDMI no SS or SS <= 0.06% */ -+ -+ struct registers *registers; -+ -+ uint32_t pixclkx_resync_cntl; -+ uint32_t ppll_fb_div; -+ uint32_t ppll_ref_div; -+ uint32_t ppll_post_div; -+ uint32_t pxpll_ds_cntl; -+ uint32_t pxpll_ss_cntl; -+ uint32_t pxpll_ss_dsfrac; -+ uint32_t pxpll_cntl; -+}; -+ -+struct clock_source *dal_pll_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data); -+ -+#endif /*__DAL_PLL_CLOCK_SOURCE_DCE110__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c -new file mode 100644 -index 0000000..ce59228 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c -@@ -0,0 +1,193 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#include "dal_services.h" -+#include "vce_clock_source_dce110.h" -+#include "include/clock_source_types.h" -+#include "include/bios_parser_interface.h" -+#include "include/logger_interface.h" -+ -+struct vce_clock_source_dce110 { -+ struct clock_source base; -+ uint32_t ref_freq_khz; -+}; -+ -+static uint32_t get_pix_clk_dividers( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct vce_clock_source_dce110 *vce_clk_src_dce110 = -+ container_of( -+ clk_src, -+ struct vce_clock_source_dce110, -+ base); -+ if (pix_clk_params == NULL || -+ pll_settings == NULL || -+ pix_clk_params->requested_pix_clk == 0) { -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameters!!", __func__); -+ return MAX_PLL_CALC_ERROR; -+ } -+ -+ dc_service_memset(pll_settings, 0, sizeof(struct pll_settings)); -+ pll_settings->reference_freq = vce_clk_src_dce110->ref_freq_khz; -+ pll_settings->actual_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ pll_settings->adjusted_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ pll_settings->calculated_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ -+ return 0; -+} -+static bool program_pix_clk(struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct bp_pixel_clock_parameters bp_pix_clk_params = { 0 }; -+ -+ if (pll_settings->actual_pix_clk == 0) -+ return false; -+ /* this is SimNow for Nutmeg*/ -+ -+ bp_pix_clk_params.controller_id = pix_clk_params->controller_id; -+ bp_pix_clk_params.pll_id = clk_src->clk_src_id; -+ bp_pix_clk_params.target_pixel_clock = pll_settings->actual_pix_clk; -+ bp_pix_clk_params.encoder_object_id = pix_clk_params->encoder_object_id; -+ bp_pix_clk_params.signal_type = pix_clk_params->signal_type; -+ -+ if (dal_bios_parser_set_pixel_clock(clk_src->bios_parser, -+ &bp_pix_clk_params) == BP_RESULT_OK) -+ return true; -+ -+ return false; -+} -+ -+static bool power_down_pll(struct clock_source *clk_src, -+ enum controller_id controller_id) -+{ -+ return true; -+} -+ -+static void destruct( -+ struct vce_clock_source_dce110 *vce_clk_src) -+{ -+ -+} -+ -+static void destroy( -+ struct clock_source **clk_src) -+{ -+ struct vce_clock_source_dce110 *vce_clk_src; -+ -+ vce_clk_src = -+ container_of(*clk_src, struct vce_clock_source_dce110, base); -+ -+ destruct(vce_clk_src); -+ dc_service_free((*clk_src)->ctx, vce_clk_src); -+ -+ *clk_src = NULL; -+} -+ -+static const struct clock_source_impl funcs = { -+ .program_pix_clk = program_pix_clk, -+ .adjust_pll_pixel_rate = dal_clock_source_base_adjust_pll_pixel_rate, -+ .adjust_dto_pixel_rate = dal_clock_source_base_adjust_dto_pix_rate, -+ .retrieve_pll_pix_rate_hz = -+ dal_clock_source_base_retrieve_pll_pix_rate_hz, -+ .get_pix_clk_dividers = get_pix_clk_dividers, -+ .destroy = destroy, -+ .retrieve_dto_pix_rate_hz = -+ dal_clock_source_base_retrieve_dto_pix_rate_hz, -+ .power_down_pll = power_down_pll, -+}; -+ -+static bool construct( -+ struct vce_clock_source_dce110 *vce_clk_src, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct firmware_info fw_info = { { 0 } }; -+ -+ if (!dal_clock_source_construct( -+ &vce_clk_src->base, clk_src_init_data)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (vce_clk_src->base.clk_src_id != CLOCK_SOURCE_ID_VCE) { -+ dal_logger_write(clk_src_init_data->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "Invalid ClockSourceId = %d!\n", -+ vce_clk_src->base.clk_src_id); -+ ASSERT_CRITICAL(false); -+ dal_logger_write(clk_src_init_data->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_GPU, -+ "Failed to create DCE110VceClockSource.\n"); -+ return false; -+ } -+ -+ vce_clk_src->base.funcs = &funcs; -+ vce_clk_src->base.clk_sharing_lvl = CLOCK_SHARING_LEVEL_NOT_SHAREABLE; -+ vce_clk_src->base.is_clock_source_with_fixed_freq = false; -+ -+ -+ /*VCE clock source only supports SignalType_Wireless*/ -+ vce_clk_src->base.output_signals |= SIGNAL_TYPE_WIRELESS; -+ -+ /*Get Reference frequency, Input frequency range into PLL -+ * and Output frequency range of the PLL -+ * from ATOMBIOS Data table */ -+ if (dal_bios_parser_get_firmware_info( -+ vce_clk_src->base.bios_parser, -+ &fw_info) != BP_RESULT_OK) -+ return false; -+ -+ vce_clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; -+ -+ return true; -+} -+ -+ -+struct clock_source *dal_vce_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data) -+ -+{ -+ struct vce_clock_source_dce110 *clk_src; -+ -+ clk_src = dc_service_alloc(clk_src_init_data->ctx, sizeof(struct vce_clock_source_dce110)); -+ -+ if (clk_src == NULL) -+ return NULL; -+ -+ if (!construct(clk_src, clk_src_init_data)) { -+ dc_service_free(clk_src_init_data->ctx, clk_src); -+ return NULL; -+ } -+ -+ return &clk_src->base; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h -new file mode 100644 -index 0000000..227b169 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.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_VCE_CLOCK_SOURCE_DCE110__ -+#define __DAL_VCE_CLOCK_SOURCE_DCE110__ -+ -+#include "../clock_source.h" -+ -+struct clock_source *dal_vce_clock_source_dce110_create( -+ struct clock_source_init_data *clk_src_init_data); -+ -+#endif /*__DAL_VCE_CLOCK_SOURCE_DCE110__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c -new file mode 100644 -index 0000000..a11aa84 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c -@@ -0,0 +1,204 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "display_clock.h" -+#include "adapter_service_interface.h" -+ -+void dal_display_clock_base_set_dp_ref_clock_source( -+ struct display_clock *disp_clk, -+ enum clock_source_id clk_src) -+{/*must be implemented in derived*/ -+ -+} -+ -+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, -+ struct display_clock_state clk_state) -+{ -+ /*Implemented only in DCE81*/ -+} -+struct display_clock_state dal_display_clock_base_get_clock_state( -+ struct display_clock *disp_clk) -+{ -+ /*Implemented only in DCE81*/ -+ struct display_clock_state state = {0}; -+ return state; -+} -+uint32_t dal_display_clock_base_get_dfs_bypass_threshold( -+ struct display_clock *disp_clk) -+{ -+ /*Implemented only in DCE81*/ -+ return 0; -+} -+ -+bool dal_display_clock_construct_base( -+ struct display_clock *base, -+ struct dc_context *ctx, -+ struct adapter_service *as) -+{ -+ base->ctx = ctx; -+ base->id = CLOCK_SOURCE_ID_DCPLL; -+ base->min_display_clk_threshold_khz = 0; -+ base->as = as; -+ -+/* Initially set current min clocks state to invalid since we -+ * cannot make any assumption about PPLIB's initial state. This will be updated -+ * by HWSS via SetMinClocksState() on first mode set prior to programming -+ * state dependent clocks.*/ -+ base->cur_min_clks_state = CLOCKS_STATE_INVALID; -+ -+ return true; -+} -+ -+void dal_display_clock_destroy(struct display_clock **disp_clk) -+{ -+ if (!disp_clk || !*disp_clk) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ (*disp_clk)->funcs->destroy(disp_clk); -+ -+ *disp_clk = NULL; -+} -+ -+bool dal_display_clock_validate( -+ struct display_clock *disp_clk, -+ struct min_clock_params *params) -+{ -+ return disp_clk->funcs->validate(disp_clk, params); -+} -+ -+uint32_t dal_display_clock_calculate_min_clock( -+ struct display_clock *disp_clk, -+ uint32_t path_num, -+ struct min_clock_params *params) -+{ -+ return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params); -+} -+ -+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_validation_clock(disp_clk); -+} -+ -+void dal_display_clock_set_clock( -+ struct display_clock *disp_clk, -+ uint32_t requested_clock_khz) -+{ -+ disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); -+} -+ -+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_clock(disp_clk); -+} -+ -+enum clocks_state dal_display_clock_get_min_clocks_state( -+ struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_min_clocks_state(disp_clk); -+} -+ -+enum clocks_state dal_display_clock_get_required_clocks_state( -+ struct display_clock *disp_clk, -+ struct state_dependent_clocks *req_clocks) -+{ -+ return disp_clk->funcs->get_required_clocks_state(disp_clk, req_clocks); -+} -+ -+bool dal_display_clock_set_min_clocks_state( -+ struct display_clock *disp_clk, -+ enum clocks_state clocks_state) -+{ -+ return disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state); -+} -+ -+uint32_t dal_display_clock_get_dp_ref_clk_frequency( -+ struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); -+} -+ -+/*the second parameter of "switchreferenceclock" is -+ * a dummy argument for all pre dce 6.0 versions*/ -+ -+void dal_display_clock_switch_reference_clock( -+ struct display_clock *disp_clk, -+ bool use_external_ref_clk, -+ uint32_t requested_clk_khz) -+{ -+ /* TODO: requires Asic Control*/ -+ /* -+ struct ac_pixel_clk_params params; -+ struct asic_control *ac = -+ dal_adapter_service_get_asic_control(disp_clk->as); -+ dc_service_memset(¶ms, 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, ¶ms); -+ */ -+} -+ -+void dal_display_clock_set_dp_ref_clock_source( -+ struct display_clock *disp_clk, -+ enum clock_source_id clk_src) -+{ -+ disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src); -+} -+ -+void dal_display_clock_store_max_clocks_state( -+ struct display_clock *disp_clk, -+ enum clocks_state max_clocks_state) -+{ -+ disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); -+} -+ -+void dal_display_clock_set_clock_state( -+ struct display_clock *disp_clk, -+ struct display_clock_state clk_state) -+{ -+ disp_clk->funcs->set_clock_state(disp_clk, clk_state); -+} -+ -+struct display_clock_state dal_display_clock_get_clock_state( -+ struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_clock_state(disp_clk); -+} -+ -+uint32_t dal_display_clock_get_dfs_bypass_threshold( -+ struct display_clock *disp_clk) -+{ -+ return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk); -+} -+ -+void dal_display_clock_invalid_clock_state( -+ struct display_clock *disp_clk) -+{ -+ disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h -new file mode 100644 -index 0000000..845393b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h -@@ -0,0 +1,82 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DISPLAY_CLOCK_H__ -+#define __DAL_DISPLAY_CLOCK_H__ -+ -+#include "include/display_clock_interface.h" -+ -+struct display_clock_funcs { -+ void (*destroy)(struct display_clock **to_destroy); -+ bool (*validate)(struct display_clock *disp_clk, -+ struct min_clock_params *params); -+ uint32_t (*calculate_min_clock)(struct display_clock *disp_clk, -+ uint32_t path_num, struct min_clock_params *params); -+ uint32_t (*get_validation_clock)(struct display_clock *disp_clk); -+ void (*set_clock)(struct display_clock *disp_clk, -+ uint32_t requested_clock_khz); -+ uint32_t (*get_clock)(struct display_clock *disp_clk); -+ enum clocks_state (*get_min_clocks_state)( -+ struct display_clock *disp_clk); -+ enum clocks_state (*get_required_clocks_state)( -+ struct display_clock *disp_clk, -+ struct state_dependent_clocks *req_clocks); -+ bool (*set_min_clocks_state)(struct display_clock *disp_clk, -+ enum clocks_state clocks_state); -+ uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); -+ void (*set_dp_ref_clock_source)(struct display_clock *disp_clk, -+ enum clock_source_id clk_src); -+ void (*store_max_clocks_state)(struct display_clock *disp_clk, -+ enum clocks_state max_clocks_state); -+ void (*set_clock_state)(struct display_clock *disp_clk, -+ struct display_clock_state clk_state); -+ struct display_clock_state (*get_clock_state)( -+ struct display_clock *disp_clk); -+ uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk); -+}; -+ -+struct display_clock { -+ struct dc_context *ctx; -+ const struct display_clock_funcs *funcs; -+ uint32_t min_display_clk_threshold_khz; -+ enum clock_source_id id; -+ struct adapter_service *as; -+ -+ enum clocks_state cur_min_clks_state; -+}; -+void dal_display_clock_base_set_dp_ref_clock_source( -+ struct display_clock *disp_clk, -+ enum clock_source_id clk_src); -+struct display_clock_state dal_display_clock_base_get_clock_state( -+ struct display_clock *disp_clk); -+uint32_t dal_display_clock_base_get_dfs_bypass_threshold( -+ struct display_clock *disp_clk); -+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, -+ struct display_clock_state clk_state); -+bool dal_display_clock_construct_base( -+ struct display_clock *base, -+ struct dc_context *ctx, -+ struct adapter_service *as); -+#endif /* __DAL_DISPLAY_CLOCK_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c -new file mode 100644 -index 0000000..3b04447 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c -@@ -0,0 +1,127 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#include "dal_services.h" -+#include "divider_range.h" -+ -+bool dal_divider_range_construct( -+ struct divider_range *div_range, -+ uint32_t range_start, -+ uint32_t range_step, -+ uint32_t did_min, -+ uint32_t did_max) -+{ -+ div_range->div_range_start = range_start; -+ div_range->div_range_step = range_step; -+ div_range->did_min = did_min; -+ div_range->did_max = did_max; -+ -+ if (div_range->div_range_step == 0) { -+ div_range->div_range_step = 1; -+ /*div_range_step cannot be zero*/ -+ BREAK_TO_DEBUGGER(); -+ } -+ /* Calculate this based on the other inputs.*/ -+ /* See DividerRange.h for explanation of */ -+ /* the relationship between divider id (DID) and a divider.*/ -+ /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ -+ /* Maximum divider identified in this range = -+ * (Number of Divider IDs)*Step size between dividers -+ * + The start of this range.*/ -+ div_range->div_range_end = (did_max - did_min) * range_step -+ + range_start; -+ return true; -+} -+ -+static uint32_t dal_divider_range_calc_divider( -+ struct divider_range *div_range, -+ uint32_t did) -+{ -+ /* Is this DID within our range?*/ -+ if ((did < div_range->did_min) || (did >= div_range->did_max)) -+ return INVALID_DIVIDER; -+ -+ return ((did - div_range->did_min) * div_range->div_range_step) -+ + div_range->div_range_start; -+ -+} -+ -+static uint32_t dal_divider_range_calc_did( -+ struct divider_range *div_range, -+ uint32_t div) -+{ -+ uint32_t did; -+ /* Check before dividing.*/ -+ if (div_range->div_range_step == 0) { -+ div_range->div_range_step = 1; -+ /*div_range_step cannot be zero*/ -+ BREAK_TO_DEBUGGER(); -+ } -+ /* Is this divider within our range?*/ -+ if ((div < div_range->div_range_start) -+ || (div >= div_range->div_range_end)) -+ return INVALID_DID; -+/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ -+ did = div - div_range->div_range_start; -+ did += div_range->div_range_step - 1; -+ did /= div_range->div_range_step; -+ did += div_range->did_min; -+ return did; -+} -+ -+uint32_t dal_divider_range_get_divider( -+ struct divider_range *div_range, -+ uint32_t ranges_num, -+ uint32_t did) -+{ -+ uint32_t div = INVALID_DIVIDER; -+ uint32_t i; -+ -+ for (i = 0; i < ranges_num; i++) { -+ /* Calculate divider with given divider ID*/ -+ div = dal_divider_range_calc_divider(&div_range[i], did); -+ /* Found a valid return divider*/ -+ if (div != INVALID_DIVIDER) -+ break; -+ } -+ return div; -+} -+uint32_t dal_divider_range_get_did( -+ struct divider_range *div_range, -+ uint32_t ranges_num, -+ uint32_t divider) -+{ -+ uint32_t did = INVALID_DID; -+ uint32_t i; -+ -+ for (i = 0; i < ranges_num; i++) { -+ /* CalcDid returns InvalidDid if a divider ID isn't found*/ -+ did = dal_divider_range_calc_did(&div_range[i], divider); -+ /* Found a valid return did*/ -+ if (did != INVALID_DID) -+ break; -+ } -+ return did; -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h -new file mode 100644 -index 0000000..2ec1034 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h -@@ -0,0 +1,63 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DIVIDER_RANGE_H__ -+#define __DAL_DIVIDER_RANGE_H__ -+ -+enum divider_error_types { -+ INVALID_DID = 0, -+ INVALID_DIVIDER = 1 -+}; -+ -+struct divider_range { -+ uint32_t div_range_start; -+ /* The end of this range of dividers.*/ -+ uint32_t div_range_end; -+ /* The distance between each divider in this range.*/ -+ uint32_t div_range_step; -+ /* The divider id for the lowest divider.*/ -+ uint32_t did_min; -+ /* The divider id for the highest divider.*/ -+ uint32_t did_max; -+}; -+ -+bool dal_divider_range_construct( -+ struct divider_range *div_range, -+ uint32_t range_start, -+ uint32_t range_step, -+ uint32_t did_min, -+ uint32_t did_max); -+ -+uint32_t dal_divider_range_get_divider( -+ struct divider_range *div_range, -+ uint32_t ranges_num, -+ uint32_t did); -+uint32_t dal_divider_range_get_did( -+ struct divider_range *div_range, -+ uint32_t ranges_num, -+ uint32_t divider); -+ -+ -+#endif /* __DAL_DIVIDER_RANGE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c -new file mode 100644 -index 0000000..ac27cd7 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c -@@ -0,0 +1,119 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/clock_source_types.h" -+#include "include/bios_parser_interface.h" -+#include "include/logger_interface.h" -+#include "ext_clock_source.h" -+ -+uint32_t dal_ext_clock_source_get_pix_clk_dividers( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct ext_clock_source *ext_clk_src = container_of( -+ clk_src, -+ struct ext_clock_source, -+ base); -+ -+ if (pix_clk_params == NULL || -+ pll_settings == NULL || -+ pix_clk_params->requested_pix_clk == 0) { -+ dal_logger_write(clk_src->ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_GPU, -+ "%s: Invalid parameters!!", __func__); -+ return MAX_PLL_CALC_ERROR; -+ } -+ -+ dc_service_memset(pll_settings, 0, sizeof(struct pll_settings)); -+ pll_settings->adjusted_pix_clk = ext_clk_src->ext_clk_freq_khz; -+ pll_settings->calculated_pix_clk = ext_clk_src->ext_clk_freq_khz; -+ pll_settings->actual_pix_clk = -+ pix_clk_params->requested_pix_clk; -+ return 0; -+} -+ -+bool dal_ext_clock_source_program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings) -+{ -+ struct bp_pixel_clock_parameters bp_pix_clk_params = {0}; -+ -+ bp_pix_clk_params.controller_id = pix_clk_params->controller_id; -+ bp_pix_clk_params.pll_id = clk_src->clk_src_id; -+ bp_pix_clk_params.target_pixel_clock = -+ pix_clk_params->requested_pix_clk; -+ bp_pix_clk_params.encoder_object_id = pix_clk_params->encoder_object_id; -+ bp_pix_clk_params.signal_type = pix_clk_params->signal_type; -+ bp_pix_clk_params.dvo_config = pix_clk_params->dvo_cfg; -+ -+ -+ if (dal_bios_parser_set_pixel_clock( -+ clk_src->bios_parser, -+ &bp_pix_clk_params) == BP_RESULT_OK) -+ return true; -+ return false; -+ -+} -+ -+bool dal_ext_clock_source_power_down_pll(struct clock_source *clk_src, -+ enum controller_id controller_id) -+{ -+ return true; -+} -+ -+bool dal_ext_clock_source_construct( -+ struct ext_clock_source *ext_clk_src, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct firmware_info fw_info = { { 0 } }; -+ -+ if (!dal_clock_source_construct( -+ &ext_clk_src->base, clk_src_init_data)) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ ext_clk_src->base.clk_sharing_lvl = -+ CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE; -+ ext_clk_src->base.is_clock_source_with_fixed_freq = true; -+ /* ExtClock has fixed frequency, -+ * so it supports only DisplayPort signals.*/ -+ ext_clk_src->base.output_signals = -+ SIGNAL_TYPE_DISPLAY_PORT | -+ SIGNAL_TYPE_DISPLAY_PORT_MST | -+ SIGNAL_TYPE_EDP; -+ -+ /*Get External clock frequency from ATOMBIOS Data table */ -+ if (dal_bios_parser_get_firmware_info( -+ ext_clk_src->base.bios_parser, -+ &fw_info) != BP_RESULT_OK) -+ return false; -+ ext_clk_src->ext_clk_freq_khz = fw_info. -+ external_clock_source_frequency_for_dp; -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h -new file mode 100644 -index 0000000..bef1dc4 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h -@@ -0,0 +1,47 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_EXT_CLOCK_SOURCE_H__ -+#define __DAL_EXT_CLOCK_SOURCE_H__ -+ -+#include "clock_source.h" -+ -+struct ext_clock_source { -+ struct clock_source base; -+ uint32_t ext_clk_freq_khz; -+}; -+ -+bool dal_ext_clock_source_construct( -+ struct ext_clock_source *ext_cs, -+ struct clock_source_init_data *clk_src_init_data); -+bool dal_ext_clock_source_power_down_pll(struct clock_source *clk_src, -+ enum controller_id controller_id); -+uint32_t dal_ext_clock_source_get_pix_clk_dividers( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+bool dal_ext_clock_source_program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+#endif /*__DAL_EXT_CLOCK_SOURCE_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c -new file mode 100644 -index 0000000..8bb0304 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.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 "dal_services.h" -+#include "include/bios_parser_interface.h" -+#include "pll_clock_source.h" -+ -+bool dal_pll_clock_source_power_down_pll( -+ struct clock_source *clk_src, -+ enum controller_id controller_id) -+{ -+ -+ enum bp_result bp_result; -+ struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; -+ -+ /* If Pixel Clock is 0 it means Power Down Pll*/ -+ bp_pixel_clock_params.controller_id = controller_id; -+ bp_pixel_clock_params.pll_id = clk_src->clk_src_id; -+ bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; -+ -+ /*Call ASICControl to process ATOMBIOS Exec table*/ -+ bp_result = dal_bios_parser_set_pixel_clock( -+ clk_src->bios_parser, -+ &bp_pixel_clock_params); -+ -+ return bp_result == BP_RESULT_OK; -+} -+ -+bool dal_pll_clock_source_adjust_pix_clk( -+ struct pll_clock_source *pll_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.dvo_config = pix_clk_params->dvo_cfg; -+ bp_adjust_pixel_clock_params. -+ display_pll_config = pix_clk_params->disp_pll_cfg; -+ bp_adjust_pixel_clock_params. -+ ss_enable = pix_clk_params->flags.ENABLE_SS; -+ bp_result = dal_bios_parser_adjust_pixel_clock( -+ pll_clk_src->base.bios_parser, -+ &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; -+} -+ -+bool dal_pll_clock_source_construct( -+ struct pll_clock_source *pll_clk_src, -+ struct clock_source_init_data *clk_src_init_data) -+{ -+ struct firmware_info fw_info = { { 0 } }; -+ -+ if (!dal_clock_source_construct( -+ &pll_clk_src->base, -+ clk_src_init_data)) -+ return false; -+ -+ if (dal_bios_parser_get_firmware_info( -+ pll_clk_src->base.bios_parser, -+ &fw_info) != BP_RESULT_OK) -+ return false; -+ pll_clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h -new file mode 100644 -index 0000000..8339e1f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h -@@ -0,0 +1,52 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_PLL_CLOCK_SOURCE_H__ -+#define __DAL_PLL_CLOCK_SOURCE_H__ -+ -+#include "gpu/clock_source.h" -+ -+struct pll_clock_source { -+ struct clock_source base; -+ uint32_t ref_freq_khz; -+}; -+ -+struct delta_sigma_data { -+ uint32_t feedback_amount; -+ uint32_t nfrac_amount; -+ uint32_t ds_frac_size; -+ uint32_t ds_frac_amount; -+}; -+ -+bool dal_pll_clock_source_construct( -+ struct pll_clock_source *pll_clk_src, -+ struct clock_source_init_data *clk_src_init_data); -+ -+bool dal_pll_clock_source_adjust_pix_clk( -+ struct pll_clock_source *pll_clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+bool dal_pll_clock_source_power_down_pll( -+ struct clock_source *clk_src, -+ enum controller_id controller_id); -+#endif /*__DAL_PLL_CLOCK_SOURCE_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile -new file mode 100644 -index 0000000..15902a8 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile -@@ -0,0 +1,23 @@ -+# -+# Makefile for the 'i2c' sub-component of DAL. -+# It provides the control and status of HW i2c engine of the adapter. -+ -+I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \ -+ i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o -+ -+AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX)) -+ -+AMD_DAL_FILES += $(AMD_DAL_I2CAUX) -+ -+ -+############################################################################### -+# DCE 11x family -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \ -+ aux_engine_dce110.o -+ -+AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110)) -+ -+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DCE110) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c -new file mode 100644 -index 0000000..824ceec ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c -@@ -0,0 +1,568 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+#include "engine.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "aux_engine.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#include "include/link_service_types.h" -+ -+/* -+ * This unit -+ */ -+ -+enum { -+ AUX_INVALID_REPLY_RETRY_COUNTER = 1, -+ AUX_TIMED_OUT_RETRY_COUNTER = 2, -+ AUX_DEFER_RETRY_COUNTER = 6 -+}; -+ -+#define FROM_ENGINE(ptr) \ -+ container_of((ptr), struct aux_engine, base) -+ -+enum i2caux_engine_type dal_aux_engine_get_engine_type( -+ const struct engine *engine) -+{ -+ return I2CAUX_ENGINE_TYPE_AUX; -+} -+ -+bool dal_aux_engine_acquire( -+ struct engine *engine, -+ struct ddc *ddc) -+{ -+ struct aux_engine *aux_engine = FROM_ENGINE(engine); -+ -+ enum gpio_result result; -+ -+ result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, -+ GPIO_DDC_CONFIG_TYPE_MODE_AUX); -+ -+ if (result != GPIO_RESULT_OK) -+ return false; -+ -+ if (!aux_engine->funcs->acquire_engine(aux_engine)) { -+ dal_ddc_close(ddc); -+ return false; -+ } -+ -+ engine->ddc = ddc; -+ -+ return true; -+} -+ -+struct read_command_context { -+ uint8_t *buffer; -+ uint8_t current_read_length; -+ uint32_t offset; -+ enum i2caux_transaction_status status; -+ -+ struct aux_request_transaction_data request; -+ struct aux_reply_transaction_data reply; -+ -+ uint8_t returned_byte; -+ -+ uint32_t timed_out_retry_aux; -+ uint32_t invalid_reply_retry_aux; -+ uint32_t defer_retry_aux; -+ uint32_t defer_retry_i2c; -+ uint32_t invalid_reply_retry_aux_on_ack; -+ -+ bool transaction_complete; -+ bool operation_succeeded; -+}; -+ -+static void process_read_reply( -+ struct aux_engine *engine, -+ struct read_command_context *ctx) -+{ -+ engine->funcs->process_channel_reply(engine, &ctx->reply); -+ -+ switch (ctx->reply.status) { -+ case AUX_TRANSACTION_REPLY_AUX_ACK: -+ ctx->defer_retry_aux = 0; -+ if (ctx->returned_byte > ctx->current_read_length) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; -+ ctx->operation_succeeded = false; -+ } else if (ctx->returned_byte < ctx->current_read_length) { -+ ctx->current_read_length -= ctx->returned_byte; -+ -+ ctx->offset += ctx->returned_byte; -+ -+ ++ctx->invalid_reply_retry_aux_on_ack; -+ -+ if (ctx->invalid_reply_retry_aux_on_ack > -+ AUX_INVALID_REPLY_RETRY_COUNTER) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; -+ ctx->operation_succeeded = false; -+ } -+ } else { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; -+ ctx->transaction_complete = true; -+ ctx->operation_succeeded = true; -+ } -+ break; -+ case AUX_TRANSACTION_REPLY_AUX_NACK: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; -+ ctx->operation_succeeded = false; -+ break; -+ case AUX_TRANSACTION_REPLY_AUX_DEFER: -+ ++ctx->defer_retry_aux; -+ -+ if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } -+ break; -+ case AUX_TRANSACTION_REPLY_I2C_DEFER: -+ ctx->defer_retry_aux = 0; -+ -+ ++ctx->defer_retry_i2c; -+ -+ if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } -+ break; -+ default: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; -+ ctx->operation_succeeded = false; -+ } -+} -+ -+static void process_read_request( -+ struct aux_engine *engine, -+ struct read_command_context *ctx) -+{ -+ enum aux_channel_operation_result operation_result; -+ -+ engine->funcs->submit_channel_request(engine, &ctx->request); -+ -+ operation_result = engine->funcs->get_channel_status( -+ engine, &ctx->returned_byte); -+ -+ switch (operation_result) { -+ case AUX_CHANNEL_OPERATION_SUCCEEDED: -+ if (ctx->returned_byte > ctx->current_read_length) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; -+ ctx->operation_succeeded = false; -+ } else { -+ ctx->timed_out_retry_aux = 0; -+ ctx->invalid_reply_retry_aux = 0; -+ -+ ctx->reply.length = ctx->returned_byte; -+ ctx->reply.data = ctx->buffer; -+ -+ process_read_reply(engine, ctx); -+ } -+ break; -+ case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: -+ ++ctx->invalid_reply_retry_aux; -+ -+ if (ctx->invalid_reply_retry_aux > -+ AUX_INVALID_REPLY_RETRY_COUNTER) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; -+ ctx->operation_succeeded = false; -+ } else -+ dc_service_delay_in_microseconds(engine->base.ctx, 400); -+ break; -+ case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: -+ ++ctx->timed_out_retry_aux; -+ -+ if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } else { -+ /* DP 1.2a, table 2-58: -+ * "S3: AUX Request CMD PENDING: -+ * retry 3 times, with 400usec wait on each" -+ * The HW timeout is set to 550usec, -+ * so we should not wait here */ -+ } -+ break; -+ default: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; -+ ctx->operation_succeeded = false; -+ } -+} -+ -+static bool read_command( -+ struct aux_engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction) -+{ -+ struct read_command_context ctx; -+ -+ ctx.buffer = request->payload.data; -+ ctx.current_read_length = request->payload.length; -+ ctx.offset = 0; -+ ctx.timed_out_retry_aux = 0; -+ ctx.invalid_reply_retry_aux = 0; -+ ctx.defer_retry_aux = 0; -+ ctx.defer_retry_i2c = 0; -+ ctx.invalid_reply_retry_aux_on_ack = 0; -+ ctx.transaction_complete = false; -+ ctx.operation_succeeded = true; -+ -+ if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { -+ ctx.request.type = AUX_TRANSACTION_TYPE_DP; -+ ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; -+ ctx.request.address = request->payload.address; -+ } else if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { -+ ctx.request.type = AUX_TRANSACTION_TYPE_I2C; -+ ctx.request.action = middle_of_transaction ? -+ I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_READ; -+ ctx.request.address = request->payload.address >> 1; -+ } else { -+ /* in DAL2, there was no return in such case */ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ ctx.request.delay = 0; -+ -+ do { -+ dc_service_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) -+ dc_service_sleep_in_milliseconds(engine->base.ctx, engine->delay); -+ } while (ctx.operation_succeeded && !ctx.transaction_complete); -+ -+ return ctx.operation_succeeded; -+} -+ -+struct write_command_context { -+ bool mot; -+ -+ uint8_t *buffer; -+ uint8_t current_write_length; -+ enum i2caux_transaction_status status; -+ -+ struct aux_request_transaction_data request; -+ struct aux_reply_transaction_data reply; -+ -+ uint8_t returned_byte; -+ -+ uint32_t timed_out_retry_aux; -+ uint32_t invalid_reply_retry_aux; -+ uint32_t defer_retry_aux; -+ uint32_t defer_retry_i2c; -+ uint32_t max_defer_retry; -+ uint32_t ack_m_retry; -+ -+ uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE]; -+ -+ bool transaction_complete; -+ bool operation_succeeded; -+}; -+ -+static void process_write_reply( -+ struct aux_engine *engine, -+ struct write_command_context *ctx) -+{ -+ engine->funcs->process_channel_reply(engine, &ctx->reply); -+ -+ switch (ctx->reply.status) { -+ case AUX_TRANSACTION_REPLY_AUX_ACK: -+ ctx->operation_succeeded = true; -+ -+ if (ctx->returned_byte) { -+ ctx->request.action = ctx->mot ? -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; -+ -+ ctx->current_write_length = 0; -+ -+ ++ctx->ack_m_retry; -+ -+ if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } else -+ dc_service_delay_in_microseconds(engine->base.ctx, 300); -+ } else { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; -+ ctx->defer_retry_aux = 0; -+ ctx->ack_m_retry = 0; -+ ctx->transaction_complete = true; -+ } -+ break; -+ case AUX_TRANSACTION_REPLY_AUX_NACK: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; -+ ctx->operation_succeeded = false; -+ break; -+ case AUX_TRANSACTION_REPLY_AUX_DEFER: -+ ++ctx->defer_retry_aux; -+ -+ if (ctx->defer_retry_aux > ctx->max_defer_retry) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } -+ break; -+ case AUX_TRANSACTION_REPLY_I2C_DEFER: -+ ctx->defer_retry_aux = 0; -+ ctx->current_write_length = 0; -+ -+ ctx->request.action = ctx->mot ? -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; -+ -+ ++ctx->defer_retry_i2c; -+ -+ if (ctx->defer_retry_i2c > ctx->max_defer_retry) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } -+ break; -+ default: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; -+ ctx->operation_succeeded = false; -+ } -+} -+ -+static void process_write_request( -+ struct aux_engine *engine, -+ struct write_command_context *ctx) -+{ -+ enum aux_channel_operation_result operation_result; -+ -+ engine->funcs->submit_channel_request(engine, &ctx->request); -+ -+ operation_result = engine->funcs->get_channel_status( -+ engine, &ctx->returned_byte); -+ -+ switch (operation_result) { -+ case AUX_CHANNEL_OPERATION_SUCCEEDED: -+ ctx->timed_out_retry_aux = 0; -+ ctx->invalid_reply_retry_aux = 0; -+ -+ ctx->reply.length = ctx->returned_byte; -+ ctx->reply.data = ctx->reply_data; -+ -+ process_write_reply(engine, ctx); -+ break; -+ case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: -+ ++ctx->invalid_reply_retry_aux; -+ -+ if (ctx->invalid_reply_retry_aux > -+ AUX_INVALID_REPLY_RETRY_COUNTER) { -+ ctx->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; -+ ctx->operation_succeeded = false; -+ } else -+ dc_service_delay_in_microseconds(engine->base.ctx, 400); -+ break; -+ case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: -+ ++ctx->timed_out_retry_aux; -+ -+ if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ ctx->operation_succeeded = false; -+ } else { -+ /* DP 1.2a, table 2-58: -+ * "S3: AUX Request CMD PENDING: -+ * retry 3 times, with 400usec wait on each" -+ * The HW timeout is set to 550usec, -+ * so we should not wait here */ -+ } -+ break; -+ default: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; -+ ctx->operation_succeeded = false; -+ } -+} -+ -+static bool write_command( -+ struct aux_engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction) -+{ -+ struct write_command_context ctx; -+ -+ ctx.mot = middle_of_transaction; -+ ctx.buffer = request->payload.data; -+ ctx.current_write_length = request->payload.length; -+ ctx.timed_out_retry_aux = 0; -+ ctx.invalid_reply_retry_aux = 0; -+ ctx.defer_retry_aux = 0; -+ ctx.defer_retry_i2c = 0; -+ ctx.ack_m_retry = 0; -+ ctx.transaction_complete = false; -+ ctx.operation_succeeded = true; -+ -+ if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { -+ ctx.request.type = AUX_TRANSACTION_TYPE_DP; -+ ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; -+ ctx.request.address = request->payload.address; -+ } else if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { -+ ctx.request.type = AUX_TRANSACTION_TYPE_I2C; -+ ctx.request.action = middle_of_transaction ? -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE; -+ ctx.request.address = request->payload.address >> 1; -+ } else { -+ /* in DAL2, there was no return in such case */ -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ ctx.request.delay = 0; -+ -+ ctx.max_defer_retry = -+ (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? -+ engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; -+ -+ do { -+ ctx.request.data = ctx.buffer; -+ ctx.request.length = ctx.current_write_length; -+ -+ process_write_request(engine, &ctx); -+ -+ request->status = ctx.status; -+ -+ if (ctx.operation_succeeded && !ctx.transaction_complete) -+ if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) -+ dc_service_sleep_in_milliseconds(engine->base.ctx, engine->delay); -+ } while (ctx.operation_succeeded && !ctx.transaction_complete); -+ -+ return ctx.operation_succeeded; -+} -+ -+static bool end_of_transaction_command( -+ struct aux_engine *engine, -+ struct i2caux_transaction_request *request) -+{ -+ struct i2caux_transaction_request dummy_request; -+ uint8_t dummy_data; -+ -+ /* [tcheng] We only need to send the stop (read with MOT = 0) -+ * for I2C-over-Aux, not native AUX */ -+ -+ if (request->payload.address_space != -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) -+ return false; -+ -+ dummy_request.operation = request->operation; -+ dummy_request.payload.address_space = request->payload.address_space; -+ dummy_request.payload.address = request->payload.address; -+ -+ /* -+ * Add a dummy byte due to some receiver quirk -+ * where one byte is sent along with MOT = 0. -+ * Ideally this should be 0. -+ */ -+ -+ dummy_request.payload.length = 0; -+ dummy_request.payload.data = &dummy_data; -+ -+ if (request->operation == I2CAUX_TRANSACTION_READ) -+ return read_command(engine, &dummy_request, false); -+ else -+ return write_command(engine, &dummy_request, false); -+ -+ /* according Syed, it does not need now DoDummyMOT */ -+} -+ -+bool dal_aux_engine_submit_request( -+ struct engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction) -+{ -+ struct aux_engine *aux_engine = FROM_ENGINE(engine); -+ -+ bool result; -+ bool mot_used = true; -+ -+ switch (request->operation) { -+ case I2CAUX_TRANSACTION_READ: -+ result = read_command(aux_engine, request, mot_used); -+ break; -+ case I2CAUX_TRANSACTION_WRITE: -+ result = write_command(aux_engine, request, mot_used); -+ break; -+ default: -+ result = false; -+ } -+ -+ /* [tcheng] -+ * need to send stop for the last transaction to free up the AUX -+ * if the above command fails, this would be the last transaction */ -+ -+ if (!middle_of_transaction || !result) -+ end_of_transaction_command(aux_engine, request); -+ -+ /* mask AUX interrupt */ -+ -+ return result; -+} -+ -+bool dal_aux_engine_construct( -+ struct aux_engine *engine, -+ struct dc_context *ctx) -+{ -+ if (!dal_i2caux_construct_engine(&engine->base, ctx)) -+ return false; -+ engine->delay = 0; -+ engine->max_defer_write_retry = 0; -+ return true; -+} -+ -+void dal_aux_engine_destruct( -+ struct aux_engine *engine) -+{ -+ dal_i2caux_destruct_engine(&engine->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h -new file mode 100644 -index 0000000..474f5e9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h -@@ -0,0 +1,119 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_AUX_ENGINE_H__ -+#define __DAL_AUX_ENGINE_H__ -+ -+enum aux_transaction_type { -+ AUX_TRANSACTION_TYPE_DP, -+ AUX_TRANSACTION_TYPE_I2C -+}; -+ -+struct aux_request_transaction_data { -+ enum aux_transaction_type type; -+ enum i2caux_transaction_action action; -+ /* 20-bit AUX channel transaction address */ -+ uint32_t address; -+ /* delay, in 100-microsecond units */ -+ uint8_t delay; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+enum aux_transaction_reply { -+ AUX_TRANSACTION_REPLY_AUX_ACK = 0x00, -+ AUX_TRANSACTION_REPLY_AUX_NACK = 0x01, -+ AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02, -+ -+ AUX_TRANSACTION_REPLY_I2C_ACK = 0x00, -+ AUX_TRANSACTION_REPLY_I2C_NACK = 0x10, -+ AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20, -+ -+ AUX_TRANSACTION_REPLY_INVALID = 0xFF -+}; -+ -+struct aux_reply_transaction_data { -+ enum aux_transaction_reply status; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+enum aux_channel_operation_result { -+ AUX_CHANNEL_OPERATION_SUCCEEDED, -+ AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN, -+ AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY, -+ AUX_CHANNEL_OPERATION_FAILED_TIMEOUT -+}; -+ -+struct aux_engine; -+ -+struct aux_engine_funcs { -+ void (*destroy)( -+ struct aux_engine **ptr); -+ bool (*acquire_engine)( -+ struct aux_engine *engine); -+ void (*configure)( -+ struct aux_engine *engine, -+ union aux_config cfg); -+ bool (*start_gtc_sync)( -+ struct aux_engine *engine); -+ void (*stop_gtc_sync)( -+ struct aux_engine *engine); -+ void (*submit_channel_request)( -+ struct aux_engine *engine, -+ struct aux_request_transaction_data *request); -+ void (*process_channel_reply)( -+ struct aux_engine *engine, -+ struct aux_reply_transaction_data *reply); -+ enum aux_channel_operation_result (*get_channel_status)( -+ struct aux_engine *engine, -+ uint8_t *returned_bytes); -+}; -+ -+struct aux_engine { -+ struct engine base; -+ const struct aux_engine_funcs *funcs; -+ /* following values are expressed in milliseconds */ -+ uint32_t delay; -+ uint32_t max_defer_write_retry; -+}; -+ -+bool dal_aux_engine_construct( -+ struct aux_engine *engine, -+ struct dc_context *ctx); -+ -+void dal_aux_engine_destruct( -+ struct aux_engine *engine); -+bool dal_aux_engine_submit_request( -+ struct engine *ptr, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction); -+bool dal_aux_engine_acquire( -+ struct engine *ptr, -+ struct ddc *ddc); -+enum i2caux_engine_type dal_aux_engine_get_engine_type( -+ const struct engine *engine); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c -new file mode 100644 -index 0000000..1b40a78 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c -@@ -0,0 +1,789 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+#include "../engine.h" -+#include "../aux_engine.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "aux_engine_dce110.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+/* -+ * This unit -+ */ -+ -+/* -+ * @brief -+ * Cast 'struct aux_engine *' -+ * to 'struct aux_engine_dce110 *' -+ */ -+#define FROM_AUX_ENGINE(ptr) \ -+ container_of((ptr), struct aux_engine_dce110, base) -+ -+/* -+ * @brief -+ * Cast 'struct engine *' -+ * to 'struct aux_engine_dce110 *' -+ */ -+#define FROM_ENGINE(ptr) \ -+ FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) -+ -+static void release_engine( -+ struct engine *engine) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_ENGINE(engine); -+ -+ const uint32_t addr = aux_engine->addr.aux_arb_control; -+ -+ uint32_t value = dal_read_reg(engine->ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_ARB_CONTROL, -+ AUX_SW_DONE_USING_AUX_REG); -+ -+ dal_write_reg(engine->ctx, addr, value); -+} -+ -+static void destruct( -+ struct aux_engine_dce110 *engine); -+ -+static void destroy( -+ struct aux_engine **aux_engine) -+{ -+ struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine); -+ -+ destruct(engine); -+ -+ dc_service_free((*aux_engine)->base.ctx, engine); -+ -+ *aux_engine = NULL; -+} -+ -+#define SW_CAN_ACCESS_AUX 1 -+ -+static bool acquire_engine( -+ struct aux_engine *engine) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine); -+ uint32_t value; -+ uint32_t field; -+ -+ /* enable AUX before request SW to access AUX */ -+ { -+ const uint32_t addr = aux_engine->addr.aux_control; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ AUX_CONTROL, -+ AUX_EN); -+ -+ if (field == 0) { -+ uint8_t counter = 0; -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_CONTROL, -+ AUX_EN); -+ -+ /*DP_AUX block as part of the enable sequence*/ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_CONTROL, -+ AUX_RESET); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ /*poll HW to make sure reset it done*/ -+ do { -+ dc_service_delay_in_microseconds(engine->base.ctx, 1); -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ AUX_CONTROL, -+ AUX_RESET_DONE); -+ -+ counter++; -+ -+ } while ((field == 0) && (counter < 11)); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_CONTROL, -+ AUX_RESET); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ counter = 0; -+ -+ do { -+ dc_service_delay_in_microseconds(engine->base.ctx, 1); -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ AUX_CONTROL, -+ AUX_RESET_DONE); -+ -+ counter++; -+ -+ } while ((field == 1) && (counter < 11)); -+ } /*if (field)*/ -+ } -+ -+ /* request SW to access AUX */ -+ { -+ const uint32_t addr = aux_engine->addr.aux_arb_control; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_ARB_CONTROL, -+ AUX_SW_USE_AUX_REG_REQ); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ field = get_reg_field_value( -+ value, -+ AUX_ARB_CONTROL, -+ AUX_REG_RW_CNTL_STATUS); -+ -+ return field == SW_CAN_ACCESS_AUX; -+ } -+} -+ -+static void configure( -+ struct aux_engine *engine, -+ union aux_config cfg) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine); -+ -+ const uint32_t addr = aux_engine->addr.aux_control; -+ -+ uint32_t value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ (0 != cfg.bits.ALLOW_AUX_WHEN_HPD_LOW), -+ AUX_CONTROL, -+ AUX_IGNORE_HPD_DISCON); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+} -+ -+static bool start_gtc_sync( -+ struct aux_engine *engine) -+{ -+ /*TODO*/ -+ return false; -+} -+ -+static void stop_gtc_sync( -+ struct aux_engine *engine) -+{ -+ /*TODO*/ -+} -+ -+#define COMPOSE_AUX_SW_DATA_16_20(command, address) \ -+ ((command) | ((0xF0000 & (address)) >> 16)) -+ -+#define COMPOSE_AUX_SW_DATA_8_15(address) \ -+ ((0xFF00 & (address)) >> 8) -+ -+#define COMPOSE_AUX_SW_DATA_0_7(address) \ -+ (0xFF & (address)) -+ -+static void submit_channel_request( -+ struct aux_engine *engine, -+ struct aux_request_transaction_data *request) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine); -+ uint32_t value; -+ uint32_t length; -+ -+ bool is_write = -+ ((request->type == AUX_TRANSACTION_TYPE_DP) && -+ (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || -+ ((request->type == AUX_TRANSACTION_TYPE_I2C) && -+ ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || -+ (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); -+ -+ /* clear_aux_error */ -+ { -+ const uint32_t addr = mmAUXN_IMPCAL; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUXN_IMPCAL, -+ AUXN_CALOUT_ERROR_AK); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUXN_IMPCAL, -+ AUXN_CALOUT_ERROR_AK); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ { -+ const uint32_t addr = mmAUXP_IMPCAL; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUXP_IMPCAL, -+ AUXP_CALOUT_ERROR_AK); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUXP_IMPCAL, -+ AUXP_CALOUT_ERROR_AK); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ -+ /* force_default_calibrate */ -+ { -+ const uint32_t addr = mmAUXN_IMPCAL; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUXN_IMPCAL, -+ AUXN_IMPCAL_ENABLE); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUXN_IMPCAL, -+ AUXN_IMPCAL_OVERRIDE_ENABLE); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ { -+ const uint32_t addr = mmAUXP_IMPCAL; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUXP_IMPCAL, -+ AUXP_IMPCAL_OVERRIDE_ENABLE); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUXP_IMPCAL, -+ AUXP_IMPCAL_OVERRIDE_ENABLE); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ -+ /* set the delay and the number of bytes to write */ -+ { -+ const uint32_t addr = aux_engine->addr.aux_sw_control; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ request->delay, -+ AUX_SW_CONTROL, -+ AUX_SW_START_DELAY); -+ -+ /* The length include -+ * the 4 bit header and the 20 bit address -+ * (that is 3 byte). -+ * If the requested length is non zero this means -+ * an addition byte specifying the length is required. */ -+ -+ length = request->length ? 4 : 3; -+ if (is_write) -+ length += request->length; -+ -+ set_reg_field_value( -+ value, -+ length, -+ AUX_SW_CONTROL, -+ AUX_SW_WR_BYTES); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ -+ /* program action and address and payload data (if 'is_write') */ -+ { -+ const uint32_t addr = aux_engine->addr.aux_sw_data; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_SW_DATA, -+ AUX_SW_INDEX); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_SW_DATA, -+ AUX_SW_DATA_RW); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_SW_DATA, -+ AUX_SW_AUTOINCREMENT_DISABLE); -+ -+ set_reg_field_value( -+ value, -+ COMPOSE_AUX_SW_DATA_16_20( -+ request->action, request->address), -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_SW_DATA, -+ AUX_SW_AUTOINCREMENT_DISABLE); -+ -+ set_reg_field_value( -+ value, -+ COMPOSE_AUX_SW_DATA_8_15(request->address), -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ COMPOSE_AUX_SW_DATA_0_7(request->address), -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ if (request->length) { -+ set_reg_field_value( -+ value, -+ request->length - 1, -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ -+ if (is_write) { -+ /* Load the HW buffer with the Data to be sent. -+ * This is relevant for write operation. -+ * For read, the data recived data will be -+ * processed in process_channel_reply(). */ -+ uint32_t i = 0; -+ -+ while (i < request->length) { -+ -+ set_reg_field_value( -+ value, -+ request->data[i], -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ dal_write_reg( -+ engine->base.ctx, addr, value); -+ -+ ++i; -+ } -+ } -+ } -+ -+ { -+ const uint32_t addr = aux_engine->addr.aux_interrupt_control; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_INTERRUPT_CONTROL, -+ AUX_SW_DONE_ACK); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+ -+ { -+ const uint32_t addr = aux_engine->addr.aux_sw_control; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_SW_CONTROL, -+ AUX_SW_GO); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ } -+} -+ -+static void process_channel_reply( -+ struct aux_engine *engine, -+ struct aux_reply_transaction_data *reply) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine); -+ -+ /* Need to do a read to get the number of bytes to process -+ * Alternatively, this information can be passed - -+ * but that causes coupling which isn't good either. */ -+ -+ uint32_t bytes_replied; -+ uint32_t value; -+ -+ { -+ const uint32_t addr = aux_engine->addr.aux_sw_status; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ bytes_replied = get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_REPLY_BYTE_COUNT); -+ } -+ -+ if (bytes_replied) { -+ uint32_t reply_result; -+ -+ const uint32_t addr = aux_engine->addr.aux_sw_data; -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_SW_DATA, -+ AUX_SW_INDEX); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_SW_DATA, -+ AUX_SW_AUTOINCREMENT_DISABLE); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_SW_DATA, -+ AUX_SW_DATA_RW); -+ -+ dal_write_reg(engine->base.ctx, addr, value); -+ -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ reply_result = get_reg_field_value( -+ value, -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ reply_result = reply_result >> 4; -+ -+ switch (reply_result) { -+ case 0: /* ACK */ { -+ uint32_t i = 0; -+ -+ /* first byte was already used -+ * to get the command status */ -+ --bytes_replied; -+ -+ while (i < bytes_replied) { -+ value = dal_read_reg( -+ engine->base.ctx, addr); -+ -+ reply->data[i] = get_reg_field_value( -+ value, -+ AUX_SW_DATA, -+ AUX_SW_DATA); -+ -+ ++i; -+ } -+ -+ reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; -+ } -+ break; -+ case 1: /* NACK */ -+ reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; -+ break; -+ case 2: /* DEFER */ -+ reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; -+ break; -+ case 4: /* AUX ACK / I2C NACK */ -+ reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; -+ break; -+ case 8: /* AUX ACK / I2C DEFER */ -+ reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; -+ break; -+ default: -+ reply->status = AUX_TRANSACTION_REPLY_INVALID; -+ } -+ } else { -+ /* Need to handle an error case... -+ * hopefully, upper layer function won't call this function -+ * if the number of bytes in the reply was 0 -+ * because there was surely an error that was asserted -+ * that should have been handled -+ * for hot plug case, this could happens*/ -+ if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) -+ ASSERT_CRITICAL(false); -+ } -+} -+ -+static enum aux_channel_operation_result get_channel_status( -+ struct aux_engine *engine, -+ uint8_t *returned_bytes) -+{ -+ struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine); -+ -+ const uint32_t addr = aux_engine->addr.aux_sw_status; -+ -+ uint32_t value; -+ uint32_t aux_sw_done; -+ -+ if (returned_bytes == NULL) { -+ /*caller pass NULL pointer*/ -+ ASSERT_CRITICAL(false); -+ return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; -+ } -+ *returned_bytes = 0; -+ -+ /* poll to make sure that SW_DONE is asserted */ -+ { -+ uint32_t time_elapsed = 0; -+ -+ do { -+ value = dal_read_reg(engine->base.ctx, addr); -+ -+ aux_sw_done = get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_DONE); -+ -+ if (aux_sw_done) -+ break; -+ -+ dc_service_delay_in_microseconds(engine->base.ctx, 10); -+ -+ time_elapsed += 10; -+ } while (time_elapsed < aux_engine->timeout_period); -+ -+ -+ } -+ -+ /* Note that the following bits are set in 'status.bits' -+ * during CTS 4.2.1.2: -+ * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, -+ * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. -+ * -+ * AUX_SW_RX_MIN_COUNT_VIOL is an internal, -+ * HW debugging bit and should be ignored. */ -+ if (aux_sw_done) { -+ if (get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_RX_TIMEOUT_STATE) || -+ get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_RX_TIMEOUT)) -+ return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; -+ else if (get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_RX_INVALID_STOP)) -+ return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; -+ -+ *returned_bytes = get_reg_field_value( -+ value, -+ AUX_SW_STATUS, -+ AUX_SW_REPLY_BYTE_COUNT); -+ if (*returned_bytes == 0) -+ return -+ AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; -+ else { -+ *returned_bytes -= 1; -+ return AUX_CHANNEL_OPERATION_SUCCEEDED; -+ } -+ } else { -+ /*time_elapsed >= aux_engine->timeout_period */ -+ if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) -+ ASSERT_CRITICAL(false); -+ return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; -+ } -+} -+ -+static const int32_t aux_channel_offset[] = { -+ mmDP_AUX0_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL, -+ mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL, -+ mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL, -+ mmDP_AUX3_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL, -+ mmDP_AUX4_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL, -+ mmDP_AUX5_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL -+}; -+ -+static const struct aux_engine_funcs aux_engine_funcs = { -+ .destroy = destroy, -+ .acquire_engine = acquire_engine, -+ .configure = configure, -+ .start_gtc_sync = start_gtc_sync, -+ .stop_gtc_sync = stop_gtc_sync, -+ .submit_channel_request = submit_channel_request, -+ .process_channel_reply = process_channel_reply, -+ .get_channel_status = get_channel_status, -+}; -+ -+static const struct engine_funcs engine_funcs = { -+ .release_engine = release_engine, -+ .submit_request = dal_aux_engine_submit_request, -+ .keep_power_up_count = dal_i2caux_keep_power_up_count, -+ .get_engine_type = dal_aux_engine_get_engine_type, -+ .acquire = dal_aux_engine_acquire, -+}; -+ -+static bool construct( -+ struct aux_engine_dce110 *engine, -+ const struct aux_engine_dce110_init_data *aux_init_data) -+{ -+ int32_t offset; -+ -+ if (aux_init_data->engine_id >= -+ sizeof(aux_channel_offset) / sizeof(int32_t)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ if (!dal_aux_engine_construct( -+ &engine->base, aux_init_data->ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ engine->base.base.funcs = &engine_funcs; -+ engine->base.funcs = &aux_engine_funcs; -+ offset = aux_channel_offset[aux_init_data->engine_id]; -+ engine->addr.aux_control = mmAUX_CONTROL + offset; -+ engine->addr.aux_arb_control = mmAUX_ARB_CONTROL + offset; -+ engine->addr.aux_sw_data = mmAUX_SW_DATA + offset; -+ engine->addr.aux_sw_control = mmAUX_SW_CONTROL + offset; -+ engine->addr.aux_interrupt_control = mmAUX_INTERRUPT_CONTROL + offset; -+ engine->addr.aux_sw_status = mmAUX_SW_STATUS + offset; -+ engine->addr.aux_gtc_sync_control = mmAUX_GTC_SYNC_CONTROL + offset; -+ engine->addr.aux_gtc_sync_status = mmAUX_GTC_SYNC_STATUS + offset; -+ engine->addr.aux_gtc_sync_controller_status = -+ mmAUX_GTC_SYNC_CONTROLLER_STATUS + offset; -+ -+ engine->timeout_period = aux_init_data->timeout_period; -+ -+ return true; -+} -+ -+static void destruct( -+ struct aux_engine_dce110 *engine) -+{ -+ dal_aux_engine_destruct(&engine->base); -+} -+ -+struct aux_engine *dal_aux_engine_dce110_create( -+ const struct aux_engine_dce110_init_data *aux_init_data) -+{ -+ struct aux_engine_dce110 *engine; -+ -+ if (!aux_init_data) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ engine = dc_service_alloc(aux_init_data->ctx, sizeof(*engine)); -+ -+ if (!engine) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(engine, aux_init_data)) -+ return &engine->base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(aux_init_data->ctx, engine); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h -new file mode 100644 -index 0000000..ec6899e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h -@@ -0,0 +1,56 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_AUX_ENGINE_DCE110_H__ -+#define __DAL_AUX_ENGINE_DCE110_H__ -+ -+#include "../aux_engine.h" -+ -+struct aux_engine_dce110 { -+ struct aux_engine base; -+ struct { -+ uint32_t aux_control; -+ uint32_t aux_arb_control; -+ uint32_t aux_sw_data; -+ uint32_t aux_sw_control; -+ uint32_t aux_interrupt_control; -+ uint32_t aux_sw_status; -+ uint32_t aux_gtc_sync_control; -+ uint32_t aux_gtc_sync_status; -+ uint32_t aux_gtc_sync_controller_status; -+ } addr; -+ uint32_t timeout_period; -+}; -+ -+struct aux_engine_dce110_init_data { -+ uint32_t engine_id; -+ uint32_t timeout_period; -+ struct dc_context *ctx; -+}; -+ -+struct aux_engine *dal_aux_engine_dce110_create( -+ const struct aux_engine_dce110_init_data *aux_init_data); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h -new file mode 100644 -index 0000000..e6b6a97 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h -@@ -0,0 +1,25 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c -new file mode 100644 -index 0000000..17e89ce ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c -@@ -0,0 +1,954 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+#include "include/logger_interface.h" -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+#include "../engine.h" -+#include "../i2c_engine.h" -+#include "../i2c_hw_engine.h" -+#include "../i2c_generic_hw_engine.h" -+/* -+ * Header of this unit -+ */ -+ -+#include "i2c_hw_engine_dce110.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+#include "dce/dce_11_0_d.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+/* -+ * This unit -+ */ -+ -+enum dc_i2c_status { -+ DC_I2C_STATUS__DC_I2C_STATUS_IDLE, -+ DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, -+ DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW -+}; -+ -+enum dc_i2c_arbitration { -+ DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, -+ DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH -+}; -+ -+enum { -+ /* No timeout in HW -+ * (timeout implemented in SW by querying status) */ -+ I2C_SETUP_TIME_LIMIT = 255, -+ I2C_HW_BUFFER_SIZE = 144 -+}; -+ -+/* -+ * @brief -+ * Cast pointer to 'struct i2c_hw_engine *' -+ * to pointer 'struct i2c_hw_engine_dce110 *' -+ */ -+#define FROM_I2C_HW_ENGINE(ptr) \ -+ container_of((ptr), struct i2c_hw_engine_dce110, base) -+/* -+ * @brief -+ * Cast pointer to 'struct i2c_engine *' -+ * to pointer to 'struct i2c_hw_engine_dce110 *' -+ */ -+#define FROM_I2C_ENGINE(ptr) \ -+ FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) -+ -+/* -+ * @brief -+ * Cast pointer to 'struct engine *' -+ * to 'pointer to struct i2c_hw_engine_dce110 *' -+ */ -+#define FROM_ENGINE(ptr) \ -+ FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) -+ -+ -+static void disable_i2c_hw_engine( -+ struct i2c_hw_engine_dce110 *engine) -+{ -+ const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; -+ uint32_t value = 0; -+ -+ struct dc_context *ctx = NULL; -+ -+ ctx = engine->base.base.base.ctx; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DC_I2C_DDC1_SETUP, -+ DC_I2C_DDC1_ENABLE); -+ -+ dal_write_reg(ctx, addr, value); -+} -+ -+static void release_engine( -+ struct engine *engine) -+{ -+ struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); -+ -+ struct i2c_engine *base = NULL; -+ bool safe_to_reset; -+ uint32_t value = 0; -+ -+ base = &hw_engine->base.base; -+ -+ /* Restore original HW engine speed */ -+ -+ base->funcs->set_speed(base, hw_engine->base.original_speed); -+ -+ /* Release I2C */ -+ { -+ value = dal_read_reg(engine->ctx, mmDC_I2C_ARBITRATION); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_ARBITRATION, -+ DC_I2C_SW_DONE_USING_I2C_REG); -+ -+ dal_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value); -+ } -+ -+ /* Reset HW engine */ -+ { -+ uint32_t i2c_sw_status = 0; -+ -+ value = dal_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 = dal_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); -+ -+ dal_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); -+ } -+ -+ /* HW I2c engine - clock gating feature */ -+ if (!hw_engine->engine_keep_power_up_count) -+ disable_i2c_hw_engine(hw_engine); -+} -+ -+static void keep_power_up_count( -+ struct engine *engine, -+ bool keep_power_up) -+{ -+ struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); -+ -+ if (keep_power_up) -+ ++hw_engine->engine_keep_power_up_count; -+ else { -+ --hw_engine->engine_keep_power_up_count; -+ -+ if (!hw_engine->engine_keep_power_up_count) -+ disable_i2c_hw_engine(hw_engine); -+ } -+} -+ -+static bool setup_engine( -+ struct i2c_engine *i2c_engine) -+{ -+ uint32_t value = 0; -+ struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine); -+ -+ /* Program pin select */ -+ { -+ const uint32_t addr = mmDC_I2C_CONTROL; -+ -+ value = dal_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); -+ -+ -+ dal_write_reg(i2c_engine->base.ctx, addr, value); -+ } -+ -+ /* Program time limit */ -+ { -+ const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; -+ -+ value = dal_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); -+ -+ dal_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 = dal_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); -+ -+ dal_write_reg(i2c_engine->base.ctx, -+ mmDC_I2C_ARBITRATION, value); -+ } -+ -+ return true; -+} -+ -+static uint32_t get_speed( -+ const struct i2c_engine *i2c_engine) -+{ -+ const struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine); -+ -+ const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; -+ -+ uint32_t pre_scale = 0; -+ -+ uint32_t value = dal_read_reg(i2c_engine->base.ctx, addr); -+ -+ pre_scale = get_reg_field_value( -+ value, -+ DC_I2C_DDC1_SPEED, -+ DC_I2C_DDC1_PRESCALE); -+ -+ /* [anaumov] it seems following is unnecessary */ -+ /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ -+ -+ return pre_scale ? -+ engine->reference_frequency / pre_scale : -+ engine->base.default_speed; -+} -+ -+static void set_speed( -+ struct i2c_engine *i2c_engine, -+ uint32_t speed) -+{ -+ struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine); -+ -+ if (speed) { -+ const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; -+ -+ uint32_t value = dal_read_reg(i2c_engine->base.ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ engine->reference_frequency / speed, -+ DC_I2C_DDC1_SPEED, -+ DC_I2C_DDC1_PRESCALE); -+ -+ set_reg_field_value( -+ value, -+ 2, -+ DC_I2C_DDC1_SPEED, -+ DC_I2C_DDC1_THRESHOLD); -+ -+ /*DCE11, HW add 100Khz support for I2c*/ -+ if (speed > 50) { -+ set_reg_field_value( -+ value, -+ 2, -+ DC_I2C_DDC1_SPEED, -+ DC_I2C_DDC1_START_STOP_TIMING_CNTL); -+ } else { -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_DDC1_SPEED, -+ DC_I2C_DDC1_START_STOP_TIMING_CNTL); -+ } -+ -+ dal_write_reg(i2c_engine->base.ctx, addr, value); -+ } -+} -+ -+static inline void reset_hw_engine(struct engine *engine) -+{ -+ uint32_t value = dal_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); -+ -+ dal_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 = dal_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 = dal_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); -+ -+ i2c_sw_status = get_reg_field_value( -+ value, -+ DC_I2C_SW_STATUS, -+ DC_I2C_SW_STATUS); -+ -+ return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; -+} -+ -+/* -+ * @brief -+ * DC_GPIO_DDC MM register offsets -+ */ -+static const uint32_t transaction_addr[] = { -+ mmDC_I2C_TRANSACTION0, -+ mmDC_I2C_TRANSACTION1, -+ mmDC_I2C_TRANSACTION2, -+ mmDC_I2C_TRANSACTION3 -+}; -+ -+static bool process_transaction( -+ struct i2c_hw_engine_dce110 *engine, -+ struct i2c_request_transaction_data *request) -+{ -+ uint8_t length = request->length; -+ uint8_t *buffer = request->data; -+ -+ bool last_transaction = false; -+ uint32_t value = 0; -+ -+ struct dc_context *ctx = NULL; -+ -+ ctx = engine->base.base.base.ctx; -+ -+ { -+ const uint32_t addr = -+ transaction_addr[engine->transaction_count]; -+ -+ value = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* Write the I2C address and I2C data -+ * into the hardware circular buffer, one byte per entry. -+ * As an example, the 7-bit I2C slave address for CRT monitor -+ * for reading DDC/EDID information is 0b1010001. -+ * For an I2C send operation, the LSB must be programmed to 0; -+ * for I2C receive operation, the LSB must be programmed to 1. */ -+ -+ { -+ value = 0; -+ -+ set_reg_field_value( -+ value, -+ false, -+ DC_I2C_DATA, -+ DC_I2C_DATA_RW); -+ -+ set_reg_field_value( -+ value, -+ request->address, -+ DC_I2C_DATA, -+ DC_I2C_DATA); -+ -+ if (engine->transaction_count == 0) { -+ set_reg_field_value( -+ value, -+ 0, -+ DC_I2C_DATA, -+ DC_I2C_INDEX); -+ -+ /*enable index write*/ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_DATA, -+ DC_I2C_INDEX_WRITE); -+ -+ engine->buffer_used_write = 0; -+ } -+ -+ dal_write_reg(ctx, mmDC_I2C_DATA, value); -+ -+ engine->buffer_used_write++; -+ -+ if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { -+ -+ set_reg_field_value( -+ value, -+ 0, -+ DC_I2C_DATA, -+ DC_I2C_INDEX_WRITE); -+ -+ while (length) { -+ -+ set_reg_field_value( -+ value, -+ *buffer++, -+ DC_I2C_DATA, -+ DC_I2C_DATA); -+ -+ dal_write_reg(ctx, mmDC_I2C_DATA, value); -+ -+ engine->buffer_used_write++; -+ --length; -+ } -+ } -+ } -+ -+ ++engine->transaction_count; -+ engine->buffer_used_bytes += length + 1; -+ -+ return last_transaction; -+} -+ -+static void execute_transaction( -+ struct i2c_hw_engine_dce110 *engine) -+{ -+ uint32_t value = 0; -+ struct dc_context *ctx = NULL; -+ -+ ctx = engine->base.base.base.ctx; -+ -+ { -+ const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; -+ -+ value = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ { -+ const uint32_t addr = mmDC_I2C_CONTROL; -+ -+ value = dal_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); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* start I2C transfer */ -+ { -+ const uint32_t addr = mmDC_I2C_CONTROL; -+ -+ value = dal_read_reg(ctx, addr); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_CONTROL, -+ DC_I2C_GO); -+ -+ dal_write_reg(ctx, addr, value); -+ } -+ -+ /* all transactions were executed and HW buffer became empty -+ * (even though it actually happens when status becomes DONE) */ -+ engine->transaction_count = 0; -+ engine->buffer_used_bytes = 0; -+} -+ -+static void submit_channel_request( -+ struct i2c_engine *engine, -+ struct i2c_request_transaction_data *request) -+{ -+ request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; -+ -+ if (!process_transaction(FROM_I2C_ENGINE(engine), request)) -+ return; -+ -+ if (is_hw_busy(&engine->base)) { -+ request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; -+ return; -+ } -+ -+ execute_transaction(FROM_I2C_ENGINE(engine)); -+} -+ -+static void process_channel_reply( -+ struct i2c_engine *engine, -+ struct i2c_reply_transaction_data *reply) -+{ -+ uint8_t length = reply->length; -+ uint8_t *buffer = reply->data; -+ -+ struct i2c_hw_engine_dce110 *i2c_hw_engine_dce110 = -+ FROM_I2C_ENGINE(engine); -+ -+ uint32_t value = 0; -+ -+ /*set index*/ -+ set_reg_field_value( -+ value, -+ i2c_hw_engine_dce110->buffer_used_write, -+ DC_I2C_DATA, -+ DC_I2C_INDEX); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_DATA, -+ DC_I2C_DATA_RW); -+ -+ set_reg_field_value( -+ value, -+ 1, -+ DC_I2C_DATA, -+ DC_I2C_INDEX_WRITE); -+ -+ dal_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 = dal_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 = dal_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS); -+ -+ i2c_sw_status = get_reg_field_value( -+ value, -+ DC_I2C_SW_STATUS, -+ DC_I2C_SW_STATUS); -+ -+ if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) -+ return I2C_CHANNEL_OPERATION_ENGINE_BUSY; -+ else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK) -+ return I2C_CHANNEL_OPERATION_NO_RESPONSE; -+ else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK) -+ return I2C_CHANNEL_OPERATION_TIMEOUT; -+ else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK) -+ return I2C_CHANNEL_OPERATION_FAILED; -+ else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK) -+ return I2C_CHANNEL_OPERATION_SUCCEEDED; -+ -+ /* in DAL2, I2C_RESULT_OK was returned */ -+ return I2C_CHANNEL_OPERATION_NOT_STARTED; -+} -+ -+static uint8_t get_hw_buffer_available_size( -+ const struct i2c_hw_engine *engine) -+{ -+ return I2C_HW_BUFFER_SIZE - -+ FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; -+} -+ -+static uint32_t get_transaction_timeout( -+ const struct i2c_hw_engine *engine, -+ uint32_t length) -+{ -+ uint32_t speed = engine->base.funcs->get_speed(&engine->base); -+ -+ uint32_t period_timeout; -+ uint32_t num_of_clock_stretches; -+ -+ if (!speed) -+ return 0; -+ -+ period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; -+ -+ num_of_clock_stretches = 1 + (length << 3) + 1; -+ num_of_clock_stretches += -+ (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + -+ (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); -+ -+ return period_timeout * num_of_clock_stretches; -+} -+ -+static void destroy( -+ struct i2c_engine **i2c_engine) -+{ -+ struct i2c_hw_engine_dce110 *engine_dce110 = -+ FROM_I2C_ENGINE(*i2c_engine); -+ -+ dal_i2c_hw_engine_destruct(&engine_dce110->base); -+ -+ dc_service_free((*i2c_engine)->base.ctx, engine_dce110); -+ -+ *i2c_engine = NULL; -+} -+/* -+ * @brief -+ * DC_I2C_DDC1_SETUP MM register offsets -+ * -+ * @note -+ * The indices of this offset array are DDC engine IDs -+ */ -+static const int32_t ddc_setup_offset[] = { -+ -+ mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */ -+ mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */ -+ mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */ -+ mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */ -+ mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */ -+ mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */ -+ mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */ -+}; -+ -+/* -+ * @brief -+ * DC_I2C_DDC1_SPEED MM register offsets -+ * -+ * @note -+ * The indices of this offset array are DDC engine IDs -+ */ -+static const int32_t ddc_speed_offset[] = { -+ mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */ -+ mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */ -+ mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */ -+ mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */ -+ mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */ -+ mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */ -+ mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */ -+}; -+ -+static const struct i2c_engine_funcs i2c_engine_funcs = { -+ .destroy = destroy, -+ .get_speed = get_speed, -+ .set_speed = set_speed, -+ .setup_engine = setup_engine, -+ .submit_channel_request = submit_channel_request, -+ .process_channel_reply = process_channel_reply, -+ .get_channel_status = get_channel_status, -+ .acquire_engine = dal_i2c_hw_engine_acquire_engine, -+}; -+ -+static const struct engine_funcs engine_funcs = { -+ .release_engine = release_engine, -+ .keep_power_up_count = keep_power_up_count, -+ .get_engine_type = dal_i2c_hw_engine_get_engine_type, -+ .acquire = dal_i2c_engine_acquire, -+ .submit_request = dal_i2c_hw_engine_submit_request, -+}; -+ -+static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { -+ .get_hw_buffer_available_size = get_hw_buffer_available_size, -+ .get_transaction_timeout = get_transaction_timeout, -+ .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, -+}; -+ -+static bool construct( -+ struct i2c_hw_engine_dce110 *engine_dce110, -+ const struct i2c_hw_engine_dce110_create_arg *arg) -+{ -+ uint32_t xtal_ref_div = 0; -+ uint32_t value = 0; -+ -+ /*ddc_setup_offset of dce80 and dce110 have the same register name -+ * but different offset. Do not need different array*/ -+ if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) -+ return false; -+ if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) -+ return false; -+ if (!arg->reference_frequency) -+ return false; -+ -+ if (!dal_i2c_hw_engine_construct(&engine_dce110->base, arg->ctx)) -+ return false; -+ -+ engine_dce110->base.base.base.funcs = &engine_funcs; -+ engine_dce110->base.base.funcs = &i2c_engine_funcs; -+ engine_dce110->base.funcs = &i2c_hw_engine_funcs; -+ engine_dce110->base.default_speed = arg->default_speed; -+ -+ engine_dce110->engine_id = arg->engine_id; -+ -+ engine_dce110->buffer_used_bytes = 0; -+ engine_dce110->transaction_count = 0; -+ engine_dce110->engine_keep_power_up_count = 1; -+ -+ /*values which are not included by arg*/ -+ engine_dce110->addr.DC_I2C_DDCX_SETUP = -+ mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id]; -+ engine_dce110->addr.DC_I2C_DDCX_SPEED = -+ mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id]; -+ -+ -+ value = dal_read_reg( -+ engine_dce110->base.base.base.ctx, -+ mmMICROSECOND_TIME_BASE_DIV); -+ -+ xtal_ref_div = get_reg_field_value( -+ value, -+ MICROSECOND_TIME_BASE_DIV, -+ XTAL_REF_DIV); -+ -+ if (xtal_ref_div == 0) { -+ dal_logger_write( -+ engine_dce110->base.base.base.ctx->logger, -+ LOG_MAJOR_WARNING, -+ LOG_MINOR_COMPONENT_I2C_AUX, -+ "Invalid base timer divider\n", -+ __func__); -+ xtal_ref_div = 2; -+ } -+ -+ /*Calculating Reference Clock by divding original frequency by -+ * XTAL_REF_DIV. -+ * At upper level, uint32_t reference_frequency = -+ * dal_i2caux_get_reference_clock(as) >> 1 -+ * which already divided by 2. So we need x2 to get original -+ * reference clock from ppll_info -+ */ -+ engine_dce110->reference_frequency = -+ (arg->reference_frequency * 2) / xtal_ref_div; -+ -+ -+ return true; -+} -+ -+struct i2c_engine *dal_i2c_hw_engine_dce110_create( -+ const struct i2c_hw_engine_dce110_create_arg *arg) -+{ -+ struct i2c_hw_engine_dce110 *engine_dce10; -+ -+ if (!arg) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ engine_dce10 = dc_service_alloc(arg->ctx, sizeof(struct i2c_hw_engine_dce110)); -+ -+ if (!engine_dce10) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(engine_dce10, arg)) -+ return &engine_dce10->base.base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(arg->ctx, engine_dce10); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h -new file mode 100644 -index 0000000..fc2ae36 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h -@@ -0,0 +1,58 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__ -+#define __DAL_I2C_HW_ENGINE_DCE110_H__ -+ -+struct i2c_hw_engine_dce110 { -+ struct i2c_hw_engine base; -+ struct { -+ uint32_t DC_I2C_DDCX_SETUP; -+ uint32_t DC_I2C_DDCX_SPEED; -+ } addr; -+ uint32_t engine_id; -+ /* expressed in kilohertz */ -+ uint32_t reference_frequency; -+ /* number of bytes currently used in HW buffer */ -+ uint32_t buffer_used_bytes; -+ /* number of bytes used for write transaction in HW buffer -+ * - this will be used as the index to read from*/ -+ uint32_t buffer_used_write; -+ /* number of pending transactions (before GO) */ -+ uint32_t transaction_count; -+ uint32_t engine_keep_power_up_count; -+}; -+ -+struct i2c_hw_engine_dce110_create_arg { -+ uint32_t engine_id; -+ uint32_t reference_frequency; -+ uint32_t default_speed; -+ struct dc_context *ctx; -+}; -+ -+struct i2c_engine *dal_i2c_hw_engine_dce110_create( -+ const struct i2c_hw_engine_dce110_create_arg *arg); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c -new file mode 100644 -index 0000000..c415a4e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c -@@ -0,0 +1,172 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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); -+ -+ dc_service_free((*engine)->base.ctx, sw_engine); -+ -+ *engine = NULL; -+} -+ -+static bool acquire_engine( -+ struct i2c_engine *engine, -+ struct ddc *ddc_handle) -+{ -+ return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); -+} -+ -+static const struct i2c_engine_funcs i2c_engine_funcs = { -+ .acquire_engine = acquire_engine, -+ .destroy = destroy, -+ .get_speed = dal_i2c_sw_engine_get_speed, -+ .set_speed = dal_i2c_sw_engine_set_speed, -+ .setup_engine = dal_i2c_engine_setup_i2c_engine, -+ .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, -+ .process_channel_reply = dal_i2c_engine_process_channel_reply, -+ .get_channel_status = dal_i2c_sw_engine_get_channel_status, -+}; -+ -+static const struct engine_funcs engine_funcs = { -+ .release_engine = release_engine, -+ .get_engine_type = dal_i2c_sw_engine_get_engine_type, -+ .acquire = dal_i2c_engine_acquire, -+ .submit_request = dal_i2c_sw_engine_submit_request, -+ .keep_power_up_count = dal_i2caux_keep_power_up_count, -+}; -+ -+static bool construct( -+ struct i2c_sw_engine_dce110 *engine_dce110, -+ const struct i2c_sw_engine_dce110_create_arg *arg_dce110) -+{ -+ struct i2c_sw_engine_create_arg arg_base; -+ -+ arg_base.ctx = arg_dce110->ctx; -+ arg_base.default_speed = arg_dce110->default_speed; -+ -+ if (!dal_i2c_sw_engine_construct( -+ &engine_dce110->base, &arg_base)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ /*struct engine struct engine_funcs*/ -+ engine_dce110->base.base.base.funcs = &engine_funcs; -+ /*struct i2c_engine struct i2c_engine_funcs*/ -+ engine_dce110->base.base.funcs = &i2c_engine_funcs; -+ engine_dce110->base.default_speed = arg_dce110->default_speed; -+ engine_dce110->engine_id = arg_dce110->engine_id; -+ -+ return true; -+} -+ -+struct i2c_engine *dal_i2c_sw_engine_dce110_create( -+ const struct i2c_sw_engine_dce110_create_arg *arg) -+{ -+ struct i2c_sw_engine_dce110 *engine_dce110; -+ -+ if (!arg) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ engine_dce110 = dc_service_alloc(arg->ctx, sizeof(struct i2c_sw_engine_dce110)); -+ -+ if (!engine_dce110) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(engine_dce110, arg)) -+ return &engine_dce110->base.base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(arg->ctx, engine_dce110); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h -new file mode 100644 -index 0000000..c48c61f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__ -+#define __DAL_I2C_SW_ENGINE_DCE110_H__ -+ -+struct i2c_sw_engine_dce110 { -+ struct i2c_sw_engine base; -+ uint32_t engine_id; -+}; -+ -+struct i2c_sw_engine_dce110_create_arg { -+ uint32_t engine_id; -+ uint32_t default_speed; -+ struct dc_context *ctx; -+}; -+ -+struct i2c_engine *dal_i2c_sw_engine_dce110_create( -+ const struct i2c_sw_engine_dce110_create_arg *arg); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c -new file mode 100644 -index 0000000..71d1a6c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c -@@ -0,0 +1,260 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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); -+ -+ dc_service_free((*i2c_engine)->ctx, i2caux_dce110); -+ -+ *i2c_engine = NULL; -+} -+ -+static struct i2c_engine *acquire_i2c_hw_engine( -+ struct i2caux *i2caux, -+ struct ddc *ddc) -+{ -+ struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); -+ -+ struct i2c_engine *engine = NULL; -+ /* generic hw engine is not used for EDID read -+ * It may be needed for external i2c device, like thermal chip, -+ * TODO will be implemented when needed. -+ * check dce80 bool non_generic for generic hw engine; -+ */ -+ -+ if (!ddc) -+ return NULL; -+ -+ if (dal_ddc_is_hw_supported(ddc)) { -+ enum gpio_ddc_line line = dal_ddc_get_line(ddc); -+ -+ if (line < GPIO_DDC_LINE_COUNT) -+ engine = i2caux->i2c_hw_engines[line]; -+ } -+ -+ if (!engine) -+ return NULL; -+ -+ if (!i2caux_dce110->i2c_hw_buffer_in_use && -+ engine->base.funcs->acquire(&engine->base, ddc)) { -+ i2caux_dce110->i2c_hw_buffer_in_use = true; -+ return engine; -+ } -+ -+ return NULL; -+} -+ -+static void release_engine( -+ struct i2caux *i2caux, -+ struct engine *engine) -+{ -+ struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); -+ -+ if (engine->funcs->get_engine_type(engine) == -+ I2CAUX_ENGINE_TYPE_I2C_DDC_HW) -+ i2caux_dce110->i2c_hw_buffer_in_use = false; -+ -+ dal_i2caux_release_engine(i2caux, engine); -+} -+ -+static const enum gpio_ddc_line hw_ddc_lines[] = { -+ GPIO_DDC_LINE_DDC1, -+ GPIO_DDC_LINE_DDC2, -+ GPIO_DDC_LINE_DDC3, -+}; -+ -+static const enum gpio_ddc_line hw_aux_lines[] = { -+ GPIO_DDC_LINE_DDC1, -+ GPIO_DDC_LINE_DDC2, -+ GPIO_DDC_LINE_DDC3, -+}; -+ -+/* function table */ -+static const struct i2caux_funcs i2caux_funcs = { -+ .destroy = destroy, -+ .acquire_i2c_hw_engine = acquire_i2c_hw_engine, -+ .release_engine = release_engine, -+ .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, -+ .acquire_aux_engine = dal_i2caux_acquire_aux_engine, -+}; -+ -+static bool construct( -+ struct i2caux_dce110 *i2caux_dce110, -+ struct adapter_service *as, -+ struct dc_context *ctx) -+{ -+ uint32_t i = 0; -+ uint32_t reference_frequency = 0; -+ bool use_i2c_sw_engine = false; -+ struct i2caux *base = NULL; -+ /*TODO: For CZ bring up, if dal_i2caux_get_reference_clock -+ * does not return 48KHz, we need hard coded for 48Khz. -+ * Some BIOS setting incorrect cause this -+ * For production, we always get value from BIOS*/ -+ reference_frequency = -+ dal_i2caux_get_reference_clock(as) >> 1; -+ -+ use_i2c_sw_engine = dal_adapter_service_is_feature_supported( -+ FEATURE_RESTORE_USAGE_I2C_SW_ENGINE); -+ -+ base = &i2caux_dce110->base; -+ -+ if (!dal_i2caux_construct(base, as, ctx)) { -+ ASSERT_CRITICAL(false); -+ return false; -+ } -+ -+ i2caux_dce110->base.funcs = &i2caux_funcs; -+ i2caux_dce110->i2c_hw_buffer_in_use = false; -+ /* Create I2C engines (DDC lines per connector) -+ * different I2C/AUX usage cases, DDC, Generic GPIO, AUX. -+ */ -+ do { -+ enum gpio_ddc_line line_id = hw_ddc_lines[i]; -+ -+ struct i2c_hw_engine_dce110_create_arg hw_arg_dce110; -+ -+ if (use_i2c_sw_engine) { -+ struct i2c_sw_engine_dce110_create_arg sw_arg; -+ -+ sw_arg.engine_id = i; -+ sw_arg.default_speed = base->default_i2c_sw_speed; -+ sw_arg.ctx = ctx; -+ base->i2c_sw_engines[line_id] = -+ dal_i2c_sw_engine_dce110_create(&sw_arg); -+ } -+ -+ hw_arg_dce110.engine_id = i; -+ hw_arg_dce110.reference_frequency = reference_frequency; -+ hw_arg_dce110.default_speed = base->default_i2c_hw_speed; -+ hw_arg_dce110.ctx = ctx; -+ -+ base->i2c_hw_engines[line_id] = -+ dal_i2c_hw_engine_dce110_create(&hw_arg_dce110); -+ -+ ++i; -+ } while (i < ARRAY_SIZE(hw_ddc_lines)); -+ -+ /* Create AUX engines for all lines which has assisted HW AUX -+ * 'i' (loop counter) used as DDC/AUX engine_id */ -+ -+ i = 0; -+ -+ do { -+ enum gpio_ddc_line line_id = hw_aux_lines[i]; -+ -+ struct aux_engine_dce110_init_data aux_init_data; -+ -+ aux_init_data.engine_id = i; -+ aux_init_data.timeout_period = base->aux_timeout_period; -+ aux_init_data.ctx = ctx; -+ -+ base->aux_engines[line_id] = -+ dal_aux_engine_dce110_create(&aux_init_data); -+ -+ ++i; -+ } while (i < ARRAY_SIZE(hw_aux_lines)); -+ -+ /*TODO Generic I2C SW and HW*/ -+ -+ return true; -+} -+ -+/* -+ * dal_i2caux_dce110_create -+ * -+ * @brief -+ * public interface to allocate memory for DCE11 I2CAUX -+ * -+ * @param -+ * struct adapter_service *as - [in] -+ * struct dc_context *ctx - [in] -+ * -+ * @return -+ * pointer to the base struct of DCE11 I2CAUX -+ */ -+struct i2caux *dal_i2caux_dce110_create( -+ struct adapter_service *as, -+ struct dc_context *ctx) -+{ -+ struct i2caux_dce110 *i2caux_dce110 = -+ dc_service_alloc(ctx, sizeof(struct i2caux_dce110)); -+ -+ if (!i2caux_dce110) { -+ ASSERT_CRITICAL(false); -+ return NULL; -+ } -+ -+ if (construct(i2caux_dce110, as, ctx)) -+ return &i2caux_dce110->base; -+ -+ ASSERT_CRITICAL(false); -+ -+ dc_service_free(ctx, i2caux_dce110); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h -new file mode 100644 -index 0000000..1a7ba1b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h -@@ -0,0 +1,39 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_AUX_DCE110_H__ -+#define __DAL_I2C_AUX_DCE110_H__ -+ -+struct i2caux_dce110 { -+ struct i2caux base; -+ /* indicate the I2C HW circular buffer is in use */ -+ bool i2c_hw_buffer_in_use; -+}; -+ -+struct i2caux *dal_i2caux_dce110_create( -+ struct adapter_service *as, -+ struct dc_context *ctx); -+ -+#endif /* __DAL_I2C_AUX_DCE110_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h -new file mode 100644 -index 0000000..d3635f8 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h -@@ -0,0 +1,129 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ENGINE_H__ -+#define __DAL_ENGINE_H__ -+ -+enum i2caux_transaction_operation { -+ I2CAUX_TRANSACTION_READ, -+ I2CAUX_TRANSACTION_WRITE -+}; -+ -+enum i2caux_transaction_address_space { -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD -+}; -+ -+struct i2caux_transaction_payload { -+ enum i2caux_transaction_address_space address_space; -+ uint32_t address; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+enum i2caux_transaction_status { -+ I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), -+ I2CAUX_TRANSACTION_STATUS_SUCCEEDED, -+ I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, -+ I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, -+ I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, -+ I2CAUX_TRANSACTION_STATUS_FAILED_NACK, -+ I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, -+ I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, -+ I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, -+ I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW -+}; -+ -+struct i2caux_transaction_request { -+ enum i2caux_transaction_operation operation; -+ struct i2caux_transaction_payload payload; -+ enum i2caux_transaction_status status; -+}; -+ -+enum i2caux_engine_type { -+ I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), -+ I2CAUX_ENGINE_TYPE_AUX, -+ I2CAUX_ENGINE_TYPE_I2C_DDC_HW, -+ I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, -+ I2CAUX_ENGINE_TYPE_I2C_SW -+}; -+ -+enum i2c_default_speed { -+ I2CAUX_DEFAULT_I2C_HW_SPEED = 50, -+ I2CAUX_DEFAULT_I2C_SW_SPEED = 50 -+}; -+ -+enum i2caux_transaction_action { -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00, -+ I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10, -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20, -+ -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40, -+ I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50, -+ I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60, -+ -+ I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80, -+ I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90 -+}; -+ -+struct engine; -+ -+struct engine_funcs { -+ enum i2caux_engine_type (*get_engine_type)( -+ const struct engine *engine); -+ bool (*acquire)( -+ struct engine *engine, -+ struct ddc *ddc); -+ bool (*submit_request)( -+ struct engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction); -+ /* [anaumov] Actually, following method is meaningful -+ * only in I2C HW engines */ -+ void (*keep_power_up_count)( -+ struct engine *engine, -+ bool keep_power_up); -+ void (*release_engine)( -+ struct engine *engine); -+}; -+ -+struct engine { -+ const struct engine_funcs *funcs; -+ struct ddc *ddc; -+ struct dc_context *ctx; -+}; -+ -+bool dal_i2caux_construct_engine( -+ struct engine *engine, -+ struct dc_context *ctx); -+ -+void dal_i2caux_destruct_engine( -+ struct engine *engine); -+ -+void dal_i2caux_keep_power_up_count( -+ struct engine *engine, -+ bool keep_power_up); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c -new file mode 100644 -index 0000000..2f87a65 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c -@@ -0,0 +1,68 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "engine.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+void dal_i2caux_keep_power_up_count( -+ struct engine *engine, -+ bool keep_power_up) -+{ -+ -+} -+ -+bool dal_i2caux_construct_engine( -+ struct engine *engine, -+ struct dc_context *ctx) -+{ -+ engine->ddc = NULL; -+ engine->ctx = ctx; -+ return true; -+} -+ -+void dal_i2caux_destruct_engine( -+ struct engine *engine) -+{ -+ /* nothing to do */ -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c -new file mode 100644 -index 0000000..78c7d61 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c -@@ -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 -+ * -+ */ -+ -+#include "dal_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 */ -+ -+ dc_service_delay_in_microseconds(engine->ctx, 10); -+ -+ ++counter; -+ } while (counter < 2); -+ -+ if (result) { -+ if (!i2c_engine->funcs->setup_engine(i2c_engine)) { -+ engine->funcs->release_engine(engine); -+ result = false; -+ } -+ } -+ -+ return result; -+} -+ -+bool dal_i2c_engine_setup_i2c_engine( -+ struct i2c_engine *engine) -+{ -+ /* Derivative classes do not have to override this */ -+ -+ return true; -+} -+ -+void dal_i2c_engine_submit_channel_request( -+ struct i2c_engine *engine, -+ struct i2c_request_transaction_data *request) -+{ -+ -+} -+ -+void dal_i2c_engine_process_channel_reply( -+ struct i2c_engine *engine, -+ struct i2c_reply_transaction_data *reply) -+{ -+ -+} -+ -+bool dal_i2c_engine_construct( -+ struct i2c_engine *engine, -+ struct dc_context *ctx) -+{ -+ if (!dal_i2caux_construct_engine(&engine->base, ctx)) -+ return false; -+ -+ engine->timeout_delay = 0; -+ return true; -+} -+ -+void dal_i2c_engine_destruct( -+ struct i2c_engine *engine) -+{ -+ dal_i2caux_destruct_engine(&engine->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h -new file mode 100644 -index 0000000..20299fd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h -@@ -0,0 +1,113 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_ENGINE_H__ -+#define __DAL_I2C_ENGINE_H__ -+ -+enum i2c_channel_operation_result { -+ I2C_CHANNEL_OPERATION_SUCCEEDED, -+ I2C_CHANNEL_OPERATION_FAILED, -+ I2C_CHANNEL_OPERATION_NOT_GRANTED, -+ I2C_CHANNEL_OPERATION_IS_BUSY, -+ I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED, -+ I2C_CHANNEL_OPERATION_CHANNEL_IN_USE, -+ I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED, -+ I2C_CHANNEL_OPERATION_ENGINE_BUSY, -+ I2C_CHANNEL_OPERATION_TIMEOUT, -+ I2C_CHANNEL_OPERATION_NO_RESPONSE, -+ I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS, -+ I2C_CHANNEL_OPERATION_WRONG_PARAMETER, -+ I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES, -+ I2C_CHANNEL_OPERATION_NOT_STARTED -+}; -+ -+struct i2c_request_transaction_data { -+ enum i2caux_transaction_action action; -+ enum i2c_channel_operation_result status; -+ uint8_t address; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+struct i2c_reply_transaction_data { -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+struct i2c_engine; -+ -+struct i2c_engine_funcs { -+ void (*destroy)( -+ struct i2c_engine **ptr); -+ uint32_t (*get_speed)( -+ const struct i2c_engine *engine); -+ void (*set_speed)( -+ struct i2c_engine *engine, -+ uint32_t speed); -+ bool (*acquire_engine)( -+ struct i2c_engine *engine, -+ struct ddc *ddc); -+ bool (*setup_engine)( -+ struct i2c_engine *engine); -+ void (*submit_channel_request)( -+ struct i2c_engine *engine, -+ struct i2c_request_transaction_data *request); -+ void (*process_channel_reply)( -+ struct i2c_engine *engine, -+ struct i2c_reply_transaction_data *reply); -+ enum i2c_channel_operation_result (*get_channel_status)( -+ struct i2c_engine *engine, -+ uint8_t *returned_bytes); -+}; -+ -+struct i2c_engine { -+ struct engine base; -+ const struct i2c_engine_funcs *funcs; -+ uint32_t timeout_delay; -+}; -+ -+bool dal_i2c_engine_construct( -+ struct i2c_engine *engine, -+ struct dc_context *ctx); -+ -+void dal_i2c_engine_destruct( -+ struct i2c_engine *engine); -+ -+bool dal_i2c_engine_setup_i2c_engine( -+ struct i2c_engine *engine); -+ -+void dal_i2c_engine_submit_channel_request( -+ struct i2c_engine *engine, -+ struct i2c_request_transaction_data *request); -+ -+void dal_i2c_engine_process_channel_reply( -+ struct i2c_engine *engine, -+ struct i2c_reply_transaction_data *reply); -+ -+bool dal_i2c_engine_acquire( -+ struct engine *ptr, -+ struct ddc *ddc_handle); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c -new file mode 100644 -index 0000000..d91e259 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c -@@ -0,0 +1,287 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+#include "engine.h" -+#include "i2c_engine.h" -+#include "i2c_hw_engine.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "i2c_generic_hw_engine.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+/* -+ * @brief -+ * Cast 'struct i2c_hw_engine *' -+ * to 'struct i2c_generic_hw_engine *' -+ */ -+#define FROM_I2C_HW_ENGINE(ptr) \ -+ container_of((ptr), struct i2c_generic_hw_engine, base) -+ -+/* -+ * @brief -+ * Cast 'struct i2c_engine *' -+ * to 'struct i2c_generic_hw_engine *' -+ */ -+#define FROM_I2C_ENGINE(ptr) \ -+ FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) -+ -+/* -+ * @brief -+ * Cast 'struct engine *' -+ * to 'struct i2c_generic_hw_engine *' -+ */ -+#define FROM_ENGINE(ptr) \ -+ FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) -+ -+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( -+ const struct engine *engine) -+{ -+ return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW; -+} -+ -+/* -+ * @brief -+ * Single transaction handling. -+ * Since transaction may be bigger than HW buffer size, -+ * it divides transaction to sub-transactions -+ * and uses batch transaction feature of the engine. -+ */ -+bool dal_i2c_generic_hw_engine_submit_request( -+ struct engine *engine, -+ struct i2caux_transaction_request *i2caux_request, -+ bool middle_of_transaction) -+{ -+ struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine); -+ -+ struct i2c_hw_engine *base = &hw_engine->base; -+ -+ uint8_t max_payload_size = -+ base->funcs->get_hw_buffer_available_size(base); -+ -+ bool initial_stop_bit = !middle_of_transaction; -+ -+ struct i2c_generic_transaction_attributes attributes; -+ -+ enum i2c_channel_operation_result operation_result = -+ I2C_CHANNEL_OPERATION_FAILED; -+ -+ bool result = false; -+ -+ /* setup transaction initial properties */ -+ -+ uint8_t address = i2caux_request->payload.address; -+ uint8_t *current_payload = i2caux_request->payload.data; -+ uint8_t remaining_payload_size = i2caux_request->payload.length; -+ -+ bool first_iteration = true; -+ -+ if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) -+ attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ; -+ else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) -+ attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; -+ else { -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; -+ return false; -+ } -+ -+ /* Do batch transaction. -+ * Divide read/write data into payloads which fit HW buffer size. -+ * 1. Single transaction: -+ * start_bit = 1, stop_bit depends on session state, ack_on_read = 0; -+ * 2. Start of batch transaction: -+ * start_bit = 1, stop_bit = 0, ack_on_read = 1; -+ * 3. Middle of batch transaction: -+ * start_bit = 0, stop_bit = 0, ack_on_read = 1; -+ * 4. End of batch transaction: -+ * start_bit = 0, stop_bit depends on session state, ack_on_read = 0. -+ * Session stop bit is set if 'middle_of_transaction' = 0. */ -+ -+ while (remaining_payload_size) { -+ uint8_t current_transaction_size; -+ uint8_t current_payload_size; -+ -+ bool last_iteration; -+ bool stop_bit; -+ -+ /* Calculate current transaction size and payload size. -+ * Transaction size = total number of bytes in transaction, -+ * including slave's address; -+ * Payload size = number of data bytes in transaction. */ -+ -+ if (first_iteration) { -+ /* In the first sub-transaction we send slave's address -+ * thus we need to reserve one byte for it */ -+ current_transaction_size = -+ (remaining_payload_size > max_payload_size - 1) ? -+ max_payload_size : -+ remaining_payload_size + 1; -+ -+ current_payload_size = current_transaction_size - 1; -+ } else { -+ /* Second and further sub-transactions will have -+ * entire buffer reserved for data */ -+ current_transaction_size = -+ (remaining_payload_size > max_payload_size) ? -+ max_payload_size : -+ remaining_payload_size; -+ -+ current_payload_size = current_transaction_size; -+ } -+ -+ last_iteration = -+ (remaining_payload_size == current_payload_size); -+ -+ stop_bit = last_iteration ? initial_stop_bit : false; -+ -+ /* write slave device address */ -+ -+ if (first_iteration) -+ hw_engine->funcs->write_address(hw_engine, address); -+ -+ /* write current portion of data, if requested */ -+ -+ if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) -+ hw_engine->funcs->write_data( -+ hw_engine, -+ current_payload, -+ current_payload_size); -+ -+ /* execute transaction */ -+ -+ attributes.start_bit = first_iteration; -+ attributes.stop_bit = stop_bit; -+ attributes.last_read = last_iteration; -+ attributes.transaction_size = current_transaction_size; -+ -+ hw_engine->funcs->execute_transaction(hw_engine, &attributes); -+ -+ /* wait until transaction is processed; if it fails - quit */ -+ -+ operation_result = base->funcs->wait_on_operation_result( -+ base, -+ base->funcs->get_transaction_timeout( -+ base, current_transaction_size), -+ I2C_CHANNEL_OPERATION_ENGINE_BUSY); -+ -+ if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED) -+ break; -+ -+ /* read current portion of data, if requested */ -+ -+ /* the read offset should be 1 for first sub-transaction, -+ * and 0 for any next one */ -+ -+ if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) -+ hw_engine->funcs->read_data(hw_engine, current_payload, -+ current_payload_size, first_iteration ? 1 : 0); -+ -+ /* update loop variables */ -+ -+ first_iteration = false; -+ current_payload += current_payload_size; -+ remaining_payload_size -= current_payload_size; -+ } -+ -+ /* update transaction status */ -+ -+ switch (operation_result) { -+ case I2C_CHANNEL_OPERATION_SUCCEEDED: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_SUCCEEDED; -+ result = true; -+ break; -+ case I2C_CHANNEL_OPERATION_NO_RESPONSE: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_NACK; -+ break; -+ case I2C_CHANNEL_OPERATION_TIMEOUT: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ break; -+ case I2C_CHANNEL_OPERATION_FAILED: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; -+ break; -+ default: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; -+ } -+ -+ return result; -+} -+ -+/* -+ * @brief -+ * Returns number of microseconds to wait until timeout to be considered -+ */ -+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( -+ const struct i2c_hw_engine *engine, -+ uint32_t length) -+{ -+ const struct i2c_engine *base = &engine->base; -+ -+ uint32_t speed = base->funcs->get_speed(base); -+ -+ if (!speed) -+ return 0; -+ -+ /* total timeout = period_timeout * (start + data bits count + stop) */ -+ -+ return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) * -+ (1 + (length << 3) + 1); -+} -+ -+bool dal_i2c_generic_hw_engine_construct( -+ struct i2c_generic_hw_engine *engine, -+ struct dc_context *ctx) -+{ -+ if (!dal_i2c_hw_engine_construct(&engine->base, ctx)) -+ return false; -+ return true; -+} -+ -+void dal_i2c_generic_hw_engine_destruct( -+ struct i2c_generic_hw_engine *engine) -+{ -+ dal_i2c_hw_engine_destruct(&engine->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h -new file mode 100644 -index 0000000..52f2aa2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h -@@ -0,0 +1,77 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__ -+#define __DAL_I2C_GENERIC_HW_ENGINE_H__ -+ -+struct i2c_generic_transaction_attributes { -+ enum i2caux_transaction_action action; -+ uint8_t transaction_size; -+ bool start_bit; -+ bool stop_bit; -+ bool last_read; -+}; -+ -+struct i2c_generic_hw_engine; -+ -+struct i2c_generic_hw_engine_funcs { -+ void (*write_address)( -+ struct i2c_generic_hw_engine *engine, -+ uint8_t address); -+ void (*write_data)( -+ struct i2c_generic_hw_engine *engine, -+ const uint8_t *buffer, -+ uint8_t length); -+ void (*read_data)( -+ struct i2c_generic_hw_engine *engine, -+ uint8_t *buffer, -+ uint8_t length, -+ uint32_t offset); -+ void (*execute_transaction)( -+ struct i2c_generic_hw_engine *engine, -+ struct i2c_generic_transaction_attributes *attributes); -+}; -+ -+struct i2c_generic_hw_engine { -+ struct i2c_hw_engine base; -+ const struct i2c_generic_hw_engine_funcs *funcs; -+}; -+ -+bool dal_i2c_generic_hw_engine_construct( -+ struct i2c_generic_hw_engine *engine, -+ struct dc_context *ctx); -+ -+void dal_i2c_generic_hw_engine_destruct( -+ struct i2c_generic_hw_engine *engine); -+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( -+ const struct engine *engine); -+bool dal_i2c_generic_hw_engine_submit_request( -+ struct engine *ptr, -+ struct i2caux_transaction_request *i2caux_request, -+ bool middle_of_transaction); -+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( -+ const struct i2c_hw_engine *engine, -+ uint32_t length); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c -new file mode 100644 -index 0000000..77f2b84 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c -@@ -0,0 +1,247 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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; -+ -+ dc_service_delay_in_microseconds(engine->base.base.ctx, 1); -+ -+ ++i; -+ } while (i < timeout); -+ -+ return result; -+} -+ -+bool dal_i2c_hw_engine_construct( -+ struct i2c_hw_engine *engine, -+ struct dc_context *ctx) -+{ -+ if (!dal_i2c_engine_construct(&engine->base, ctx)) -+ return false; -+ engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; -+ engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; -+ return true; -+} -+ -+void dal_i2c_hw_engine_destruct( -+ struct i2c_hw_engine *engine) -+{ -+ dal_i2c_engine_destruct(&engine->base); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h -new file mode 100644 -index 0000000..5afbd70 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h -@@ -0,0 +1,80 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_HW_ENGINE_H__ -+#define __DAL_I2C_HW_ENGINE_H__ -+ -+enum { -+ TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32 -+}; -+ -+struct i2c_hw_engine; -+ -+struct i2c_hw_engine_funcs { -+ uint8_t (*get_hw_buffer_available_size)( -+ const struct i2c_hw_engine *engine); -+ enum i2c_channel_operation_result (*wait_on_operation_result)( -+ struct i2c_hw_engine *engine, -+ uint32_t timeout, -+ enum i2c_channel_operation_result expected_result); -+ uint32_t (*get_transaction_timeout)( -+ const struct i2c_hw_engine *engine, -+ uint32_t length); -+}; -+ -+struct i2c_hw_engine { -+ struct i2c_engine base; -+ const struct i2c_hw_engine_funcs *funcs; -+ -+ /* Values below are in kilohertz */ -+ uint32_t original_speed; -+ uint32_t default_speed; -+}; -+ -+bool dal_i2c_hw_engine_construct( -+ struct i2c_hw_engine *engine, -+ struct dc_context *ctx); -+ -+void dal_i2c_hw_engine_destruct( -+ struct i2c_hw_engine *engine); -+ -+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( -+ struct i2c_hw_engine *engine, -+ uint32_t timeout, -+ enum i2c_channel_operation_result expected_result); -+ -+bool dal_i2c_hw_engine_acquire_engine( -+ struct i2c_engine *engine, -+ struct ddc *ddc); -+ -+bool dal_i2c_hw_engine_submit_request( -+ struct engine *ptr, -+ struct i2caux_transaction_request *i2caux_request, -+ bool middle_of_transaction); -+ -+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( -+ const struct engine *engine); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c -new file mode 100644 -index 0000000..c253917 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c -@@ -0,0 +1,615 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+#include "engine.h" -+#include "i2c_engine.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "i2c_sw_engine.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+/* -+ * This unit -+ */ -+ -+#define SCL false -+#define SDA true -+ -+static inline bool read_bit_from_ddc( -+ struct ddc *ddc, -+ bool data_nor_clock) -+{ -+ uint32_t value = 0; -+ -+ if (data_nor_clock) -+ dal_ddc_get_data(ddc, &value); -+ else -+ dal_ddc_get_clock(ddc, &value); -+ -+ return (value != 0); -+} -+ -+static inline void write_bit_to_ddc( -+ struct ddc *ddc, -+ bool data_nor_clock, -+ bool bit) -+{ -+ uint32_t value = bit ? 1 : 0; -+ -+ if (data_nor_clock) -+ dal_ddc_set_data(ddc, value); -+ else -+ dal_ddc_set_clock(ddc, value); -+} -+ -+static bool wait_for_scl_high( -+ struct dc_context *ctx, -+ struct ddc *ddc, -+ uint16_t clock_delay_div_4) -+{ -+ uint32_t scl_retry = 0; -+ uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4; -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ /* 3 milliseconds delay -+ * to wake up some displays from "low power" state. -+ */ -+ -+ do { -+ if (read_bit_from_ddc(ddc, SCL)) -+ return true; -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ ++scl_retry; -+ } while (scl_retry <= scl_retry_max); -+ -+ return false; -+} -+ -+static bool start_sync( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4) -+{ -+ uint32_t retry = 0; -+ -+ /* The I2C communications start signal is: -+ * the SDA going low from high, while the SCL is high. */ -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ do { -+ write_bit_to_ddc(ddc_handle, SDA, true); -+ -+ if (!read_bit_from_ddc(ddc_handle, SDA)) { -+ ++retry; -+ continue; -+ } -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ break; -+ -+ write_bit_to_ddc(ddc_handle, SDA, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ return true; -+ } while (retry <= I2C_SW_RETRIES); -+ -+ return false; -+} -+ -+static bool stop_sync( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4) -+{ -+ uint32_t retry = 0; -+ -+ /* The I2C communications stop signal is: -+ * the SDA going high from low, while the SCL is high. */ -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SDA, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ return false; -+ -+ write_bit_to_ddc(ddc_handle, SDA, true); -+ -+ do { -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ if (read_bit_from_ddc(ddc_handle, SDA)) -+ return true; -+ -+ ++retry; -+ } while (retry <= 2); -+ -+ return false; -+} -+ -+static bool write_byte( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4, -+ uint8_t byte) -+{ -+ int32_t shift = 7; -+ bool ack; -+ -+ /* bits are transmitted serially, starting from MSB */ -+ -+ do { -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ return false; -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ --shift; -+ } while (shift >= 0); -+ -+ /* The display sends ACK by preventing the SDA from going high -+ * after the SCL pulse we use to send our last data bit. -+ * If the SDA goes high after that bit, it's a NACK */ -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SDA, true); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ return false; -+ -+ /* read ACK bit */ -+ -+ ack = !read_bit_from_ddc(ddc_handle, SDA); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4 << 1); -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4 << 1); -+ -+ return ack; -+} -+ -+static bool read_byte( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4, -+ uint8_t *byte, -+ bool more) -+{ -+ int32_t shift = 7; -+ -+ uint8_t data = 0; -+ -+ /* The data bits are read from MSB to LSB; -+ * bit is read while SCL is high */ -+ -+ do { -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ return false; -+ -+ if (read_bit_from_ddc(ddc_handle, SDA)) -+ data |= (1 << shift); -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4 << 1); -+ -+ --shift; -+ } while (shift >= 0); -+ -+ /* read only whole byte */ -+ -+ *byte = data; -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ /* send the acknowledge bit: -+ * SDA low means ACK, SDA high means NACK */ -+ -+ write_bit_to_ddc(ddc_handle, SDA, !more); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SCL, true); -+ -+ if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) -+ return false; -+ -+ write_bit_to_ddc(ddc_handle, SCL, false); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ write_bit_to_ddc(ddc_handle, SDA, true); -+ -+ dc_service_delay_in_microseconds(ctx, clock_delay_div_4); -+ -+ return true; -+} -+ -+static bool i2c_write( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4, -+ uint8_t address, -+ uint8_t length, -+ const uint8_t *data) -+{ -+ uint32_t i = 0; -+ -+ if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) -+ return false; -+ -+ while (i < length) { -+ if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i])) -+ return false; -+ ++i; -+ } -+ -+ return true; -+} -+ -+static bool i2c_read( -+ struct dc_context *ctx, -+ struct ddc *ddc_handle, -+ uint16_t clock_delay_div_4, -+ uint8_t address, -+ uint8_t length, -+ uint8_t *data) -+{ -+ uint32_t i = 0; -+ -+ if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) -+ return false; -+ -+ while (i < length) { -+ if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i, -+ i < length - 1)) -+ return false; -+ ++i; -+ } -+ -+ return true; -+} -+ -+/* -+ * @brief -+ * Cast 'struct i2c_engine *' -+ * to 'struct i2c_sw_engine *' -+ */ -+#define FROM_I2C_ENGINE(ptr) \ -+ container_of((ptr), struct i2c_sw_engine, base) -+ -+/* -+ * @brief -+ * Cast 'struct engine *' -+ * to 'struct i2c_sw_engine *' -+ */ -+#define FROM_ENGINE(ptr) \ -+ FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) -+ -+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( -+ const struct engine *engine) -+{ -+ return I2CAUX_ENGINE_TYPE_I2C_SW; -+} -+ -+bool dal_i2c_sw_engine_submit_request( -+ struct engine *engine, -+ struct i2caux_transaction_request *i2caux_request, -+ bool middle_of_transaction) -+{ -+ struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine); -+ -+ struct i2c_engine *base = &sw_engine->base; -+ -+ struct i2c_request_transaction_data request; -+ bool operation_succeeded = false; -+ -+ if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) -+ request.action = middle_of_transaction ? -+ I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_READ; -+ else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) -+ request.action = middle_of_transaction ? -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : -+ I2CAUX_TRANSACTION_ACTION_I2C_WRITE; -+ else { -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; -+ /* in DAL2, there was no "return false" */ -+ return false; -+ } -+ -+ request.address = (uint8_t)i2caux_request->payload.address; -+ request.length = i2caux_request->payload.length; -+ request.data = i2caux_request->payload.data; -+ -+ base->funcs->submit_channel_request(base, &request); -+ -+ if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) || -+ (request.status == I2C_CHANNEL_OPERATION_FAILED)) -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; -+ else { -+ enum i2c_channel_operation_result operation_result; -+ -+ do { -+ operation_result = -+ base->funcs->get_channel_status(base, NULL); -+ -+ switch (operation_result) { -+ case I2C_CHANNEL_OPERATION_SUCCEEDED: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_SUCCEEDED; -+ operation_succeeded = true; -+ break; -+ case I2C_CHANNEL_OPERATION_NO_RESPONSE: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_NACK; -+ break; -+ case I2C_CHANNEL_OPERATION_TIMEOUT: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; -+ break; -+ case I2C_CHANNEL_OPERATION_FAILED: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; -+ break; -+ default: -+ i2caux_request->status = -+ I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; -+ break; -+ } -+ } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY); -+ } -+ -+ return operation_succeeded; -+} -+ -+uint32_t dal_i2c_sw_engine_get_speed( -+ const struct i2c_engine *engine) -+{ -+ return FROM_I2C_ENGINE(engine)->speed; -+} -+ -+void dal_i2c_sw_engine_set_speed( -+ struct i2c_engine *engine, -+ uint32_t speed) -+{ -+ struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); -+ -+ ASSERT(speed); -+ -+ sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED; -+ -+ sw_engine->clock_delay = 1000 / sw_engine->speed; -+ -+ if (sw_engine->clock_delay < 12) -+ sw_engine->clock_delay = 12; -+} -+ -+bool dal_i2caux_i2c_sw_engine_acquire_engine( -+ struct i2c_engine *engine, -+ struct ddc *ddc) -+{ -+ enum gpio_result result; -+ -+ result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT, -+ GPIO_DDC_CONFIG_TYPE_MODE_I2C); -+ -+ if (result != GPIO_RESULT_OK) -+ return false; -+ -+ engine->base.ddc = ddc; -+ -+ return true; -+} -+ -+void dal_i2c_sw_engine_submit_channel_request( -+ struct i2c_engine *engine, -+ struct i2c_request_transaction_data *req) -+{ -+ struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); -+ -+ struct ddc *ddc = engine->base.ddc; -+ uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2; -+ -+ /* send sync (start / repeated start) */ -+ -+ bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4); -+ -+ /* process payload */ -+ -+ if (result) { -+ switch (req->action) { -+ case I2CAUX_TRANSACTION_ACTION_I2C_WRITE: -+ case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT: -+ result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4, -+ req->address, req->length, req->data); -+ break; -+ case I2CAUX_TRANSACTION_ACTION_I2C_READ: -+ case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT: -+ result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4, -+ req->address, req->length, req->data); -+ break; -+ default: -+ result = false; -+ break; -+ } -+ } -+ -+ /* send stop if not 'mot' or operation failed */ -+ -+ if (!result || -+ (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || -+ (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ)) -+ if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4)) -+ result = false; -+ -+ req->status = result ? -+ I2C_CHANNEL_OPERATION_SUCCEEDED : -+ I2C_CHANNEL_OPERATION_FAILED; -+} -+ -+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( -+ struct i2c_engine *engine, -+ uint8_t *returned_bytes) -+{ -+ return dal_ddc_check_line_aborted(engine->base.ddc) ? -+ I2C_CHANNEL_OPERATION_FAILED : -+ I2C_CHANNEL_OPERATION_SUCCEEDED; -+} -+ -+void dal_i2c_sw_engine_destruct( -+ struct i2c_sw_engine *engine) -+{ -+ dal_i2c_engine_destruct(&engine->base); -+} -+ -+static void destroy( -+ struct i2c_engine **ptr) -+{ -+ dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); -+ -+ dc_service_free((*ptr)->base.ctx, *ptr); -+ *ptr = NULL; -+} -+ -+static const struct i2c_engine_funcs i2c_engine_funcs = { -+ .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine, -+ .destroy = destroy, -+ .get_speed = dal_i2c_sw_engine_get_speed, -+ .set_speed = dal_i2c_sw_engine_set_speed, -+ .setup_engine = dal_i2c_engine_setup_i2c_engine, -+ .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, -+ .process_channel_reply = dal_i2c_engine_process_channel_reply, -+ .get_channel_status = dal_i2c_sw_engine_get_channel_status, -+}; -+ -+static void release_engine( -+ struct engine *engine) -+{ -+ -+} -+ -+static const struct engine_funcs engine_funcs = { -+ .release_engine = release_engine, -+ .get_engine_type = dal_i2c_sw_engine_get_engine_type, -+ .acquire = dal_i2c_engine_acquire, -+ .submit_request = dal_i2c_sw_engine_submit_request, -+ .keep_power_up_count = dal_i2caux_keep_power_up_count, -+}; -+ -+bool dal_i2c_sw_engine_construct( -+ struct i2c_sw_engine *engine, -+ const struct i2c_sw_engine_create_arg *arg) -+{ -+ if (!dal_i2c_engine_construct(&engine->base, arg->ctx)) -+ return false; -+ -+ dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); -+ engine->base.funcs = &i2c_engine_funcs; -+ engine->base.base.funcs = &engine_funcs; -+ return true; -+} -+ -+ -+ -+struct i2c_engine *dal_i2c_sw_engine_create( -+ const struct i2c_sw_engine_create_arg *arg) -+{ -+ struct i2c_sw_engine *engine; -+ -+ if (!arg) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ engine = dc_service_alloc(arg->ctx, sizeof(struct i2c_sw_engine)); -+ -+ if (!engine) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ if (dal_i2c_sw_engine_construct(engine, arg)) -+ return &engine->base; -+ -+ BREAK_TO_DEBUGGER(); -+ -+ dc_service_free(arg->ctx, engine); -+ -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h -new file mode 100644 -index 0000000..e0cb4c3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h -@@ -0,0 +1,81 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_SW_ENGINE_H__ -+#define __DAL_I2C_SW_ENGINE_H__ -+ -+enum { -+ I2C_SW_RETRIES = 10, -+ I2C_SW_SCL_READ_RETRIES = 128, -+ /* following value is in microseconds */ -+ I2C_SW_TIMEOUT_DELAY = 3000 -+}; -+ -+struct i2c_sw_engine; -+ -+struct i2c_sw_engine { -+ struct i2c_engine base; -+ uint32_t clock_delay; -+ /* Values below are in KHz */ -+ uint32_t speed; -+ uint32_t default_speed; -+}; -+ -+struct i2c_sw_engine_create_arg { -+ uint32_t default_speed; -+ struct dc_context *ctx; -+}; -+ -+bool dal_i2c_sw_engine_construct( -+ struct i2c_sw_engine *engine, -+ const struct i2c_sw_engine_create_arg *arg); -+ -+bool dal_i2caux_i2c_sw_engine_acquire_engine( -+ struct i2c_engine *engine, -+ struct ddc *ddc_handle); -+ -+void dal_i2c_sw_engine_destruct( -+ struct i2c_sw_engine *engine); -+ -+struct i2c_engine *dal_i2c_sw_engine_create( -+ const struct i2c_sw_engine_create_arg *arg); -+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( -+ const struct engine *engine); -+bool dal_i2c_sw_engine_submit_request( -+ struct engine *ptr, -+ struct i2caux_transaction_request *i2caux_request, -+ bool middle_of_transaction); -+uint32_t dal_i2c_sw_engine_get_speed( -+ const struct i2c_engine *engine); -+void dal_i2c_sw_engine_set_speed( -+ struct i2c_engine *ptr, -+ uint32_t speed); -+void dal_i2c_sw_engine_submit_channel_request( -+ struct i2c_engine *ptr, -+ struct i2c_request_transaction_data *req); -+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( -+ struct i2c_engine *engine, -+ uint8_t *returned_bytes); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c -new file mode 100644 -index 0000000..50262a4 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c -@@ -0,0 +1,519 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_services.h" -+ -+/* -+ * Pre-requisites: headers required by header of this unit -+ */ -+ -+#include "include/i2caux_interface.h" -+ -+/* -+ * Header of this unit -+ */ -+ -+#include "i2caux.h" -+ -+/* -+ * Post-requisites: headers required by this unit -+ */ -+ -+#include "engine.h" -+#include "i2c_engine.h" -+#include "aux_engine.h" -+ -+/* -+ * This unit -+ */ -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/i2caux_dce110.h" -+#endif -+ -+/* -+ * @brief -+ * Plain API, available publicly -+ */ -+ -+struct i2caux *dal_i2caux_create( -+ struct adapter_service *as, -+ struct dc_context *ctx) -+{ -+ enum dce_version dce_version; -+ -+ if (!as) { -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+ -+ dce_version = dal_adapter_service_get_dce_version(as); -+ -+ switch (dce_version) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ return dal_i2caux_dce110_create(as, ctx); -+#endif -+ default: -+ BREAK_TO_DEBUGGER(); -+ return NULL; -+ } -+} -+ -+bool dal_i2caux_submit_i2c_command( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ struct i2c_command *cmd) -+{ -+ struct i2c_engine *engine; -+ uint8_t index_of_payload = 0; -+ bool result; -+ -+ if (!ddc) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!cmd) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ switch (cmd->engine) { -+ case I2C_COMMAND_ENGINE_SW: -+ /* try to acquire SW engine first, -+ * acquire HW engine if SW engine not available */ -+ engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc); -+ -+ if (!engine) -+ engine = i2caux->funcs->acquire_i2c_hw_engine( -+ i2caux, ddc); -+ break; -+ case I2C_COMMAND_ENGINE_HW: -+ case I2C_COMMAND_ENGINE_DEFAULT: -+ default: -+ /* try to acquire HW engine first, -+ * acquire SW engine if HW engine not available */ -+ engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc); -+ -+ if (!engine) -+ engine = i2caux->funcs->acquire_i2c_sw_engine( -+ i2caux, ddc); -+ } -+ -+ if (!engine) -+ return false; -+ -+ engine->funcs->set_speed(engine, cmd->speed); -+ -+ result = true; -+ -+ while (index_of_payload < cmd->number_of_payloads) { -+ bool mot = (index_of_payload != cmd->number_of_payloads - 1); -+ -+ struct i2c_payload *payload = cmd->payloads + index_of_payload; -+ -+ struct i2caux_transaction_request request = { 0 }; -+ -+ request.operation = payload->write ? -+ I2CAUX_TRANSACTION_WRITE : -+ I2CAUX_TRANSACTION_READ; -+ -+ request.payload.address_space = -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; -+ request.payload.address = (payload->address << 1) | -+ !payload->write; -+ request.payload.length = payload->length; -+ request.payload.data = payload->data; -+ -+ if (!engine->base.funcs->submit_request( -+ &engine->base, &request, mot)) { -+ result = false; -+ break; -+ } -+ -+ ++index_of_payload; -+ } -+ -+ i2caux->funcs->release_engine(i2caux, &engine->base); -+ -+ return result; -+} -+ -+bool dal_i2caux_submit_aux_command( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ struct aux_command *cmd) -+{ -+ struct aux_engine *engine; -+ uint8_t index_of_payload = 0; -+ bool result; -+ -+ if (!ddc) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!cmd) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc); -+ -+ if (!engine) -+ return false; -+ -+ engine->delay = cmd->defer_delay; -+ engine->max_defer_write_retry = cmd->max_defer_write_retry; -+ -+ result = true; -+ -+ while (index_of_payload < cmd->number_of_payloads) { -+ bool mot = (index_of_payload != cmd->number_of_payloads - 1); -+ -+ struct aux_payload *payload = cmd->payloads + index_of_payload; -+ -+ struct i2caux_transaction_request request = { 0 }; -+ -+ request.operation = payload->write ? -+ I2CAUX_TRANSACTION_WRITE : -+ I2CAUX_TRANSACTION_READ; -+ -+ if (payload->i2c_over_aux) { -+ request.payload.address_space = -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; -+ -+ request.payload.address = (payload->address << 1) | -+ !payload->write; -+ } else { -+ request.payload.address_space = -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD; -+ -+ request.payload.address = payload->address; -+ } -+ -+ request.payload.length = payload->length; -+ request.payload.data = payload->data; -+ -+ if (!engine->base.funcs->submit_request( -+ &engine->base, &request, mot)) { -+ result = false; -+ break; -+ } -+ -+ ++index_of_payload; -+ } -+ -+ i2caux->funcs->release_engine(i2caux, &engine->base); -+ -+ return result; -+} -+ -+static bool get_hw_supported_ddc_line( -+ struct ddc *ddc, -+ enum gpio_ddc_line *line) -+{ -+ enum gpio_ddc_line line_found; -+ -+ if (!ddc) { -+ BREAK_TO_DEBUGGER(); -+ return false; -+ } -+ -+ if (!dal_ddc_is_hw_supported(ddc)) -+ return false; -+ -+ line_found = dal_ddc_get_line(ddc); -+ -+ if (line_found >= GPIO_DDC_LINE_COUNT) -+ return false; -+ -+ *line = line_found; -+ -+ return true; -+} -+ -+void dal_i2caux_keep_engine_power_up( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ bool keep_power_up) -+{ -+ enum gpio_ddc_line line; -+ struct i2c_engine *engine; -+ -+ if (!get_hw_supported_ddc_line(ddc, &line)) -+ return; -+ -+ engine = i2caux->i2c_hw_engines[line]; -+ -+ engine->base.funcs->keep_power_up_count(&engine->base, keep_power_up); -+} -+ -+bool dal_i2caux_start_gtc_sync( -+ struct i2caux *i2caux, -+ struct ddc *ddc) -+{ -+ enum gpio_ddc_line line; -+ -+ struct aux_engine *engine; -+ -+ bool result; -+ -+ if (!get_hw_supported_ddc_line(ddc, &line)) -+ return false; -+ -+ engine = i2caux->aux_engines[line]; -+ -+ if (!engine) -+ return false; -+ -+ if (!engine->base.funcs->acquire(&engine->base, ddc)) -+ return false; -+ -+ result = engine->funcs->start_gtc_sync(engine); -+ -+ i2caux->funcs->release_engine(i2caux, &engine->base); -+ -+ return result; -+} -+ -+bool dal_i2caux_stop_gtc_sync( -+ struct i2caux *i2caux, -+ struct ddc *ddc) -+{ -+ enum gpio_ddc_line line; -+ -+ struct aux_engine *engine; -+ -+ if (!get_hw_supported_ddc_line(ddc, &line)) -+ return false; -+ -+ engine = i2caux->aux_engines[line]; -+ -+ if (!engine) -+ return false; -+ -+ if (!engine->base.funcs->acquire(&engine->base, ddc)) -+ return false; -+ -+ engine->funcs->stop_gtc_sync(engine); -+ -+ i2caux->funcs->release_engine(i2caux, &engine->base); -+ -+ return true; -+} -+ -+void dal_i2caux_configure_aux( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ union aux_config cfg) -+{ -+ struct aux_engine *engine = -+ i2caux->funcs->acquire_aux_engine(i2caux, ddc); -+ -+ if (!engine) -+ return; -+ -+ engine->funcs->configure(engine, cfg); -+ -+ i2caux->funcs->release_engine(i2caux, &engine->base); -+} -+ -+void dal_i2caux_destroy( -+ struct i2caux **i2caux) -+{ -+ if (!i2caux || !*i2caux) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ (*i2caux)->funcs->destroy(i2caux); -+ -+ *i2caux = NULL; -+} -+ -+/* -+ * @brief -+ * An utility function used by 'struct i2caux' and its descendants -+ */ -+ -+uint32_t dal_i2caux_get_reference_clock( -+ struct adapter_service *as) -+{ -+ struct firmware_info info = { { 0 } }; -+ -+ if (!dal_adapter_service_get_firmware_info(as, &info)) -+ return 0; -+ -+ return info.pll_info.crystal_frequency; -+} -+ -+/* -+ * @brief -+ * i2caux -+ */ -+ -+enum { -+ /* following are expressed in KHz */ -+ DEFAULT_I2C_SW_SPEED = 50, -+ DEFAULT_I2C_HW_SPEED = 50, -+ -+ /* This is the timeout as defined in DP 1.2a, -+ * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ -+ AUX_TIMEOUT_PERIOD = 400, -+ -+ /* Ideally, the SW timeout should be just above 550usec -+ * which is programmed in HW. -+ * But the SW timeout of 600usec is not reliable, -+ * because on some systems, delay_in_microseconds() -+ * returns faster than it should. -+ * EPR #379763: by trial-and-error on different systems, -+ * 700usec is the minimum reliable SW timeout for polling -+ * the AUX_SW_STATUS.AUX_SW_DONE bit. -+ * This timeout expires *only* when there is -+ * AUX Error or AUX Timeout conditions - not during normal operation. -+ * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set -+ * at most within ~240usec. That means, -+ * increasing this timeout will not affect normal operation, -+ * and we'll timeout after -+ * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec. -+ * This timeout is especially important for -+ * resume from S3 and CTS. */ -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4 -+}; -+ -+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( -+ struct i2caux *i2caux, -+ struct ddc *ddc) -+{ -+ enum gpio_ddc_line line; -+ struct i2c_engine *engine = NULL; -+ -+ if (get_hw_supported_ddc_line(ddc, &line)) -+ engine = i2caux->i2c_sw_engines[line]; -+ -+ if (!engine) -+ engine = i2caux->i2c_generic_sw_engine; -+ -+ if (!engine) -+ return NULL; -+ -+ if (!engine->base.funcs->acquire(&engine->base, ddc)) -+ return NULL; -+ -+ return engine; -+} -+ -+struct aux_engine *dal_i2caux_acquire_aux_engine( -+ struct i2caux *i2caux, -+ struct ddc *ddc) -+{ -+ enum gpio_ddc_line line; -+ struct aux_engine *engine; -+ -+ if (!get_hw_supported_ddc_line(ddc, &line)) -+ return NULL; -+ -+ engine = i2caux->aux_engines[line]; -+ -+ if (!engine) -+ return NULL; -+ -+ if (!engine->base.funcs->acquire(&engine->base, ddc)) -+ return NULL; -+ -+ return engine; -+} -+ -+void dal_i2caux_release_engine( -+ struct i2caux *i2caux, -+ struct engine *engine) -+{ -+ engine->funcs->release_engine(engine); -+ -+ dal_ddc_close(engine->ddc); -+ -+ engine->ddc = NULL; -+} -+ -+bool dal_i2caux_construct( -+ struct i2caux *i2caux, -+ struct adapter_service *as, -+ struct dc_context *ctx) -+{ -+ uint32_t i = 0; -+ -+ i2caux->ctx = ctx; -+ do { -+ i2caux->i2c_sw_engines[i] = NULL; -+ i2caux->i2c_hw_engines[i] = NULL; -+ i2caux->aux_engines[i] = NULL; -+ -+ ++i; -+ } while (i < GPIO_DDC_LINE_COUNT); -+ -+ i2caux->i2c_generic_sw_engine = NULL; -+ i2caux->i2c_generic_hw_engine = NULL; -+ -+ i2caux->aux_timeout_period = -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; -+ -+ i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; -+ i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; -+ -+ return true; -+} -+ -+void dal_i2caux_destruct( -+ struct i2caux *i2caux) -+{ -+ uint32_t i = 0; -+ -+ if (i2caux->i2c_generic_hw_engine) -+ i2caux->i2c_generic_hw_engine->funcs->destroy( -+ &i2caux->i2c_generic_hw_engine); -+ -+ if (i2caux->i2c_generic_sw_engine) -+ i2caux->i2c_generic_sw_engine->funcs->destroy( -+ &i2caux->i2c_generic_sw_engine); -+ -+ do { -+ if (i2caux->aux_engines[i]) -+ i2caux->aux_engines[i]->funcs->destroy( -+ &i2caux->aux_engines[i]); -+ -+ if (i2caux->i2c_hw_engines[i]) -+ i2caux->i2c_hw_engines[i]->funcs->destroy( -+ &i2caux->i2c_hw_engines[i]); -+ -+ if (i2caux->i2c_sw_engines[i]) -+ i2caux->i2c_sw_engines[i]->funcs->destroy( -+ &i2caux->i2c_sw_engines[i]); -+ -+ ++i; -+ } while (i < GPIO_DDC_LINE_COUNT); -+} -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h -new file mode 100644 -index 0000000..76f5b63 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h -@@ -0,0 +1,123 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2C_AUX_H__ -+#define __DAL_I2C_AUX_H__ -+ -+uint32_t dal_i2caux_get_reference_clock( -+ struct adapter_service *as); -+ -+struct i2caux; -+ -+struct engine; -+ -+struct i2caux_funcs { -+ void (*destroy)(struct i2caux **ptr); -+ struct i2c_engine * (*acquire_i2c_sw_engine)( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ struct i2c_engine * (*acquire_i2c_hw_engine)( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ struct aux_engine * (*acquire_aux_engine)( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ void (*release_engine)( -+ struct i2caux *i2caux, -+ struct engine *engine); -+}; -+ -+struct i2c_engine; -+struct aux_engine; -+ -+struct i2caux { -+ struct dc_context *ctx; -+ const struct i2caux_funcs *funcs; -+ /* On ASIC we have certain amount of lines with HW DDC engine -+ * (4, 6, or maybe more in the future). -+ * For every such line, we create separate HW DDC engine -+ * (since we have these engines in HW) and separate SW DDC engine -+ * (to allow concurrent use of few lines). -+ * In similar way we have AUX engines. */ -+ -+ /* I2C SW engines, per DDC line. -+ * Only lines with HW DDC support will be initialized */ -+ struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT]; -+ -+ /* I2C HW engines, per DDC line. -+ * Only lines with HW DDC support will be initialized */ -+ struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT]; -+ -+ /* AUX engines, per DDC line. -+ * Only lines with HW AUX support will be initialized */ -+ struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT]; -+ -+ /* For all other lines, we can use -+ * single instance of generic I2C HW engine -+ * (since in HW, there is single instance of it) -+ * or single instance of generic I2C SW engine. -+ * AUX is not supported for other lines. */ -+ -+ /* General-purpose I2C SW engine. -+ * Can be assigned dynamically to any line per transaction */ -+ struct i2c_engine *i2c_generic_sw_engine; -+ -+ /* General-purpose I2C generic HW engine. -+ * Can be assigned dynamically to almost any line per transaction */ -+ struct i2c_engine *i2c_generic_hw_engine; -+ -+ /* [anaumov] in DAL2, there is a Mutex */ -+ -+ uint32_t aux_timeout_period; -+ -+ /* expressed in KHz */ -+ uint32_t default_i2c_sw_speed; -+ uint32_t default_i2c_hw_speed; -+}; -+ -+bool dal_i2caux_construct( -+ struct i2caux *i2caux, -+ struct adapter_service *as, -+ struct dc_context *ctx); -+ -+void dal_i2caux_release_engine( -+ struct i2caux *i2caux, -+ struct engine *engine); -+ -+void dal_i2caux_destruct( -+ struct i2caux *i2caux); -+ -+void dal_i2caux_destroy( -+ struct i2caux **ptr); -+ -+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ -+struct aux_engine *dal_i2caux_acquire_aux_engine( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h -new file mode 100644 -index 0000000..f7315c6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h -@@ -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 -+ * -+ */ -+ -+/** -+ * Bandwidth and Watermark calculations interface. -+ * (Refer to "DCE11_mode_support.xlsm" from Perforce.) -+ */ -+#ifndef __BANDWIDTH_CALCS_H__ -+#define __BANDWIDTH_CALCS_H__ -+ -+#include "bw_fixed.h" -+/******************************************************************************* -+ * There are three types of input into Calculations: -+ * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP -+ * 2. board-level values - these are generally coming from VBIOS parser -+ * 3. mode/configuration values - depending Mode, Scaling number of Displays etc. -+ ******************************************************************************/ -+ -+enum bw_stereo_mode { -+ mono, -+ side_by_side, -+ top_bottom -+}; -+ -+enum bw_ul_mode { -+ ul_none, -+ ul_only, -+ ul_blend -+}; -+ -+enum bw_tiling_mode { -+ linear, -+ tiled -+}; -+ -+enum bw_panning_and_bezel_adj { -+ none, -+ any_lines -+}; -+ -+enum bw_underlay_surface_type { -+ yuv_420, -+ yuv_422 -+}; -+ -+struct bw_calcs_input_dceip { -+ struct bw_fixed dmif_request_buffer_size; -+ struct bw_fixed de_tiling_buffer; -+ struct bw_fixed dcfclk_request_generation; -+ struct bw_fixed lines_interleaved_into_lb; -+ struct bw_fixed chunk_width; -+ struct bw_fixed number_of_graphics_pipes; -+ struct bw_fixed 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; -+ struct bw_fixed max_dmif_buffer_allocated; -+ struct bw_fixed graphics_dmif_size; -+ struct bw_fixed underlay_luma_dmif_size; -+ struct bw_fixed underlay_chroma_dmif_size; -+ bool pre_downscaler_enabled; -+ bool underlay_downscale_prefetch_enabled; -+ struct bw_fixed lb_write_pixels_per_dispclk; -+ struct bw_fixed lb_size_per_component444; -+ bool graphics_lb_nodownscaling_multi_line_prefetching; -+ struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor; -+ struct bw_fixed underlay420_luma_lb_size_per_component; -+ struct bw_fixed underlay420_chroma_lb_size_per_component; -+ struct bw_fixed underlay422_lb_size_per_component; -+ struct bw_fixed cursor_chunk_width; -+ struct bw_fixed cursor_dcp_buffer_lines; -+ struct bw_fixed cursor_memory_interface_buffer_pixels; -+ struct bw_fixed underlay_maximum_width_efficient_for_tiling; -+ struct bw_fixed underlay_maximum_height_efficient_for_tiling; -+ struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; -+ struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; -+ struct bw_fixed minimum_outstanding_pte_request_limit; -+ struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw; -+ bool limit_excessive_outstanding_dmif_requests; -+ struct bw_fixed linear_mode_line_request_alternation_slice; -+ struct bw_fixed scatter_gather_lines_of_pte_prefetching_in_linear_mode; -+ struct bw_fixed display_write_back420_luma_mcifwr_buffer_size; -+ struct bw_fixed 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; -+ struct bw_fixed scatter_gather_pte_request_rows_in_tiling_mode; -+ struct bw_fixed mcifwr_all_surfaces_burst_time; /* 0 todo: this is a bug*/ -+}; -+ -+struct bw_calcs_input_vbios { -+ struct bw_fixed dram_channel_width_in_bits; -+ struct bw_fixed number_of_dram_channels; -+ struct bw_fixed number_of_dram_banks; -+ struct bw_fixed high_yclk; -+ struct bw_fixed high_dram_bandwidth_per_channel; -+ struct bw_fixed low_yclk; -+ struct bw_fixed low_dram_bandwidth_per_channel; -+ struct bw_fixed low_sclk; -+ struct bw_fixed mid_sclk; -+ struct bw_fixed high_sclk; -+ struct bw_fixed low_voltage_max_dispclk; -+ struct bw_fixed mid_voltage_max_dispclk; -+ struct bw_fixed high_voltage_max_dispclk; -+ struct bw_fixed data_return_bus_width; -+ struct bw_fixed trc; -+ struct bw_fixed dmifmc_urgent_latency; -+ struct bw_fixed stutter_self_refresh_exit_latency; -+ struct bw_fixed nbp_state_change_latency; -+ struct bw_fixed mcifwrmc_urgent_latency; -+ bool scatter_gather_enable; -+ struct bw_fixed down_spread_percentage; -+ struct bw_fixed cursor_width; -+ struct bw_fixed average_compression_rate; -+ struct bw_fixed number_of_request_slots_gmc_reserves_for_dmif_per_channel; -+ struct bw_fixed blackout_duration; -+ struct bw_fixed maximum_blackout_recovery_time; -+}; -+ -+struct bw_calcs_input_mode_data_internal { -+ /* data for all displays */ -+ uint32_t number_of_displays; -+ struct bw_fixed graphics_rotation_angle; -+ struct bw_fixed underlay_rotation_angle; -+ bool display_synchronization_enabled; -+ enum bw_underlay_surface_type underlay_surface_type; -+ enum bw_panning_and_bezel_adj panning_and_bezel_adjustment; -+ enum bw_tiling_mode graphics_tiling_mode; -+ bool graphics_interlace_mode; -+ struct bw_fixed graphics_bytes_per_pixel; -+ struct bw_fixed graphics_htaps; -+ struct bw_fixed graphics_vtaps; -+ struct bw_fixed graphics_lb_bpc; -+ struct bw_fixed underlay_lb_bpc; -+ enum bw_tiling_mode underlay_tiling_mode; -+ struct bw_fixed underlay_htaps; -+ struct bw_fixed underlay_vtaps; -+ struct bw_fixed underlay_src_width; -+ struct bw_fixed underlay_src_height; -+ struct bw_fixed underlay_pitch_in_pixels; -+ enum bw_stereo_mode underlay_stereo_mode; -+ bool d0_fbc_enable; -+ bool d0_lpt_enable; -+ struct bw_fixed d0_htotal; -+ struct bw_fixed d0_pixel_rate; -+ struct bw_fixed d0_graphics_src_width; -+ struct bw_fixed d0_graphics_src_height; -+ struct bw_fixed d0_graphics_scale_ratio; -+ enum bw_stereo_mode d0_graphics_stereo_mode; -+ enum bw_ul_mode d0_underlay_mode; -+ struct bw_fixed d0_underlay_scale_ratio; -+ struct bw_fixed d1_htotal; -+ struct bw_fixed d1_pixel_rate; -+ struct bw_fixed d1_graphics_src_width; -+ struct bw_fixed d1_graphics_src_height; -+ struct bw_fixed d1_graphics_scale_ratio; -+ enum bw_stereo_mode d1_graphics_stereo_mode; -+ bool d1_display_write_back_dwb_enable; -+ enum bw_ul_mode d1_underlay_mode; -+ struct bw_fixed d1_underlay_scale_ratio; -+ struct bw_fixed d2_htotal; -+ struct bw_fixed d2_pixel_rate; -+ struct bw_fixed d2_graphics_src_width; -+ struct bw_fixed d2_graphics_src_height; -+ struct bw_fixed d2_graphics_scale_ratio; -+ enum bw_stereo_mode d2_graphics_stereo_mode; -+}; -+ -+struct bw_calcs_input_single_display { -+ uint32_t graphics_rotation_angle; -+ uint32_t underlay_rotation_angle; -+ enum bw_underlay_surface_type underlay_surface_type; -+ enum bw_panning_and_bezel_adj panning_and_bezel_adjustment; -+ uint32_t graphics_bytes_per_pixel; -+ bool graphics_interlace_mode; -+ enum bw_tiling_mode graphics_tiling_mode; -+ uint32_t graphics_h_taps; -+ uint32_t graphics_v_taps; -+ uint32_t graphics_lb_bpc; -+ uint32_t underlay_lb_bpc; -+ enum bw_tiling_mode underlay_tiling_mode; -+ uint32_t underlay_h_taps; -+ uint32_t underlay_v_taps; -+ uint32_t underlay_src_width; -+ uint32_t underlay_src_height; -+ uint32_t underlay_pitch_in_pixels; -+ enum bw_stereo_mode underlay_stereo_mode; -+ bool fbc_enable; -+ bool lpt_enable; -+ uint32_t h_total; -+ struct bw_fixed pixel_rate; -+ uint32_t graphics_src_width; -+ uint32_t graphics_src_height; -+ struct bw_fixed graphics_scale_ratio; -+ enum bw_stereo_mode graphics_stereo_mode; -+ enum bw_ul_mode underlay_mode; -+}; -+ -+#define BW_CALCS_MAX_NUM_DISPLAYS 3 -+ -+struct bw_calcs_input_mode_data { -+ /* data for all displays */ -+ uint8_t number_of_displays; -+ bool display_synchronization_enabled; -+ -+ struct bw_calcs_input_single_display -+ displays_data[BW_CALCS_MAX_NUM_DISPLAYS]; -+}; -+ -+/******************************************************************************* -+ * Output data structure(s). -+ ******************************************************************************/ -+#define maximum_number_of_surfaces 12 -+struct bw_results_internal { -+ bool cpup_state_change_enable; -+ bool cpuc_state_change_enable; -+ bool nbp_state_change_enable; -+ bool stutter_mode_enable; -+ struct bw_fixed number_of_underlay_surfaces; -+ struct bw_fixed src_width_after_surface_type; -+ struct bw_fixed src_height_after_surface_type; -+ struct bw_fixed hsr_after_surface_type; -+ struct bw_fixed vsr_after_surface_type; -+ struct bw_fixed src_width_after_rotation; -+ struct bw_fixed src_height_after_rotation; -+ struct bw_fixed hsr_after_rotation; -+ struct bw_fixed vsr_after_rotation; -+ struct bw_fixed source_height_pixels; -+ struct bw_fixed hsr_after_stereo; -+ struct bw_fixed vsr_after_stereo; -+ struct bw_fixed source_width_in_lb; -+ struct bw_fixed lb_line_pitch; -+ struct bw_fixed underlay_maximum_source_efficient_for_tiling; -+ struct bw_fixed num_lines_at_frame_start; -+ struct bw_fixed min_dmif_size_in_time; -+ struct bw_fixed min_mcifwr_size_in_time; -+ struct bw_fixed total_requests_for_dmif_size; -+ struct bw_fixed peak_pte_request_to_eviction_ratio_limiting; -+ struct bw_fixed useful_pte_per_pte_request; -+ struct bw_fixed scatter_gather_pte_request_rows; -+ struct bw_fixed scatter_gather_row_height; -+ struct bw_fixed scatter_gather_pte_requests_in_vblank; -+ struct bw_fixed inefficient_linear_pitch_in_bytes; -+ struct bw_fixed inefficient_underlay_pitch_in_pixels; -+ struct bw_fixed minimum_underlay_pitch_padding_recommended_for_efficiency; -+ struct bw_fixed cursor_total_data; -+ struct bw_fixed cursor_total_request_groups; -+ struct bw_fixed scatter_gather_total_pte_requests; -+ struct bw_fixed scatter_gather_total_pte_request_groups; -+ struct bw_fixed tile_width_in_pixels; -+ struct bw_fixed dmif_total_number_of_data_request_page_close_open; -+ struct bw_fixed mcifwr_total_number_of_data_request_page_close_open; -+ struct bw_fixed bytes_per_page_close_open; -+ struct bw_fixed mcifwr_total_page_close_open_time; -+ struct bw_fixed total_requests_for_adjusted_dmif_size; -+ struct bw_fixed total_dmifmc_urgent_trips; -+ struct bw_fixed total_dmifmc_urgent_latency; -+ struct bw_fixed total_display_reads_required_data; -+ struct bw_fixed total_display_reads_required_dram_access_data; -+ struct bw_fixed total_display_writes_required_data; -+ struct bw_fixed total_display_writes_required_dram_access_data; -+ struct bw_fixed display_reads_required_data; -+ struct bw_fixed display_reads_required_dram_access_data; -+ struct bw_fixed dmif_total_page_close_open_time; -+ struct bw_fixed min_cursor_memory_interface_buffer_size_in_time; -+ struct bw_fixed min_read_buffer_size_in_time; -+ struct bw_fixed display_reads_time_for_data_transfer; -+ struct bw_fixed display_writes_time_for_data_transfer; -+ struct bw_fixed dmif_required_dram_bandwidth; -+ struct bw_fixed mcifwr_required_dram_bandwidth; -+ struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open; -+ struct bw_fixed required_mcifmcwr_urgent_latency; -+ struct bw_fixed required_dram_bandwidth_gbyte_per_second; -+ struct bw_fixed dram_bandwidth; -+ struct bw_fixed dmif_required_sclk; -+ struct bw_fixed mcifwr_required_sclk; -+ struct bw_fixed required_sclk; -+ struct bw_fixed downspread_factor; -+ struct bw_fixed v_scaler_efficiency; -+ struct bw_fixed scaler_limits_factor; -+ struct bw_fixed display_pipe_pixel_throughput; -+ struct bw_fixed total_dispclk_required_with_ramping; -+ struct bw_fixed total_dispclk_required_without_ramping; -+ struct bw_fixed total_read_request_bandwidth; -+ struct bw_fixed total_write_request_bandwidth; -+ struct bw_fixed dispclk_required_for_total_read_request_bandwidth; -+ struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth; -+ struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth; -+ struct bw_fixed dispclk; -+ struct bw_fixed blackout_recovery_time; -+ struct bw_fixed min_pixels_per_data_fifo_entry; -+ struct bw_fixed sclk_deep_sleep; -+ struct bw_fixed chunk_request_time; -+ struct bw_fixed cursor_request_time; -+ struct bw_fixed line_source_pixels_transfer_time; -+ struct bw_fixed dmifdram_access_efficiency; -+ struct bw_fixed mcifwrdram_access_efficiency; -+ struct bw_fixed total_average_bandwidth_no_compression; -+ struct bw_fixed total_average_bandwidth; -+ struct bw_fixed total_stutter_cycle_duration; -+ struct bw_fixed stutter_burst_time; -+ struct bw_fixed time_in_self_refresh; -+ struct bw_fixed stutter_efficiency; -+ struct bw_fixed worst_number_of_trips_to_memory; -+ struct bw_fixed immediate_flip_time; -+ struct bw_fixed latency_for_non_dmif_clients; -+ struct bw_fixed latency_for_non_mcifwr_clients; -+ struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk; -+ struct bw_fixed nbp_state_dram_speed_change_margin; -+ struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency; -+ bool 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]; -+ struct bw_fixed bytes_per_pixel[maximum_number_of_surfaces]; -+ struct bw_fixed h_total[maximum_number_of_surfaces]; -+ struct bw_fixed pixel_rate[maximum_number_of_surfaces]; -+ struct bw_fixed src_width[maximum_number_of_surfaces]; -+ struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces]; -+ struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces]; -+ struct bw_fixed src_height[maximum_number_of_surfaces]; -+ struct bw_fixed scale_ratio[maximum_number_of_surfaces]; -+ struct bw_fixed h_taps[maximum_number_of_surfaces]; -+ struct bw_fixed v_taps[maximum_number_of_surfaces]; -+ struct bw_fixed rotation_angle[maximum_number_of_surfaces]; -+ struct bw_fixed lb_bpc[maximum_number_of_surfaces]; -+ struct bw_fixed compression_rate[maximum_number_of_surfaces]; -+ struct bw_fixed hsr[maximum_number_of_surfaces]; -+ struct bw_fixed vsr[maximum_number_of_surfaces]; -+ struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces]; -+ struct bw_fixed source_width_pixels[maximum_number_of_surfaces]; -+ struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces]; -+ struct bw_fixed display_bandwidth[maximum_number_of_surfaces]; -+ struct bw_fixed request_bandwidth[maximum_number_of_surfaces]; -+ struct bw_fixed bytes_per_request[maximum_number_of_surfaces]; -+ struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces]; -+ struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces]; -+ struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces]; -+ struct bw_fixed lb_partitions[maximum_number_of_surfaces]; -+ struct bw_fixed lb_partitions_max[maximum_number_of_surfaces]; -+ struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces]; -+ struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces]; -+ struct bw_fixed data_buffer_size[maximum_number_of_surfaces]; -+ struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces]; -+ struct bw_fixed urgent_watermark[maximum_number_of_surfaces]; -+ struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces]; -+ struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces]; -+ struct bw_fixed v_filter_init[maximum_number_of_surfaces]; -+ struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces]; -+ struct bw_fixed average_bandwidth[maximum_number_of_surfaces]; -+ struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces]; -+ struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces]; -+ struct bw_fixed lb_size_per_component[maximum_number_of_surfaces]; -+ struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces]; -+ struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces]; -+ struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces]; -+ struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces]; -+ struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces]; -+ struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces]; -+ struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces]; -+ struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces]; -+ struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces]; -+ struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces]; -+ struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces]; -+ struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces]; -+ struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces]; -+ struct bw_fixed line_buffer_prefetch[maximum_number_of_surfaces]; -+ struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces]; -+ struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces]; -+ struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces]; -+ struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces]; -+ struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces]; -+ struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces]; -+ struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces]; -+ struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces]; -+ struct bw_fixed active_time[maximum_number_of_surfaces]; -+ struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces]; -+ struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces]; -+ struct bw_fixed dmif_burst_time[3][3]; -+ struct bw_fixed mcifwr_burst_time[3][3]; -+ struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][3]; -+ struct bw_fixed dram_speed_change_margin[3][3]; -+ struct bw_fixed dispclk_required_for_dram_speed_change[3][3]; -+ struct bw_fixed blackout_duration_margin[3][3]; -+ struct bw_fixed dispclk_required_for_blackout_duration[3][3]; -+ struct bw_fixed dispclk_required_for_blackout_recovery[3][3]; -+ struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; -+}; -+ -+struct bw_watermarks { -+ uint32_t a_mark; -+ uint32_t b_mark; -+}; -+ -+struct bw_calcs_output { -+ bool cpuc_state_change_enable; -+ bool cpup_state_change_enable; -+ bool stutter_mode_enable; -+ bool nbp_state_change_enable; -+ struct bw_watermarks urgent_watermark[4]; -+ struct bw_watermarks stutter_exit_watermark[4]; -+ struct bw_watermarks nbp_state_change_watermark[4]; -+ uint32_t required_sclk; -+ uint32_t dispclk; -+}; -+ -+ -+/** -+ * Initialize structures with data which will NOT change at runtime. -+ */ -+void bw_calcs_init( -+ struct bw_calcs_input_dceip *bw_dceip, -+ struct bw_calcs_input_vbios *bw_vbios); -+ -+/** -+ * Return: -+ * true - Display(s) configuration supported. -+ * In this case 'calcs_output' contains data for HW programming -+ * false - Display(s) configuration not supported (not enough bandwidth). -+ */ -+bool bw_calcs( -+ struct dc_context *ctx, -+ const struct bw_calcs_input_dceip *dceip, -+ const struct bw_calcs_input_vbios *vbios, -+ const struct bw_calcs_input_mode_data *mode_data, -+ struct bw_calcs_output *calcs_output); -+ -+ -+#endif /* __BANDWIDTH_CALCS_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h -new file mode 100644 -index 0000000..f9e267b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.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 BW_FIXED_H_ -+#define BW_FIXED_H_ -+ -+struct bw_fixed { -+ signed long long 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 int_to_fixed(long long value); -+ -+struct bw_fixed frc_to_fixed(long long num, long long denum); -+ -+struct bw_fixed fixed31_32_to_bw_fixed(long long raw); -+ -+struct bw_fixed add(const struct bw_fixed arg1, const struct bw_fixed arg2); -+struct bw_fixed sub(const struct bw_fixed arg1, const struct bw_fixed arg2); -+struct bw_fixed 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_min(const struct bw_fixed arg1, const struct bw_fixed arg2); -+struct bw_fixed bw_max(const struct bw_fixed arg1, const struct bw_fixed arg2); -+struct bw_fixed bw_floor(const struct bw_fixed arg, const struct bw_fixed significance); -+struct bw_fixed bw_ceil(const struct bw_fixed arg, const struct bw_fixed significance); -+ -+bool equ(const struct bw_fixed arg1, const struct bw_fixed arg2); -+bool neq(const struct bw_fixed arg1, const struct bw_fixed arg2); -+bool leq(const struct bw_fixed arg1, const struct bw_fixed arg2); -+bool geq(const struct bw_fixed arg1, const struct bw_fixed arg2); -+bool ltn(const struct bw_fixed arg1, const struct bw_fixed arg2); -+bool gtn(const struct bw_fixed arg1, const struct bw_fixed arg2); -+ -+#endif //BW_FIXED_H_ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/compressor.h b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h -new file mode 100644 -index 0000000..4992ffd ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h -@@ -0,0 +1,140 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_COMPRESSOR_H__ -+#define __DAL_COMPRESSOR_H__ -+ -+#include "include/grph_object_id.h" -+ -+enum fbc_compress_ratio { -+ FBC_COMPRESS_RATIO_INVALID = 0, -+ FBC_COMPRESS_RATIO_1TO1 = 1, -+ FBC_COMPRESS_RATIO_2TO1 = 2, -+ FBC_COMPRESS_RATIO_4TO1 = 4, -+ FBC_COMPRESS_RATIO_8TO1 = 8, -+}; -+ -+union fbc_physical_address { -+ struct { -+ uint32_t low_part; -+ int32_t high_part; -+ } addr; -+}; -+ -+struct compr_addr_and_pitch_params { -+ uint32_t inst; -+ uint32_t source_view_width; -+ uint32_t source_view_height; -+}; -+ -+struct fbc_lpt_config { -+ uint32_t mem_channels_num; -+ uint32_t banks_num; -+ uint32_t chan_interleave_size; -+ uint32_t row_size; -+}; -+ -+struct fbc_input_info { -+ bool dynamic_fbc_buffer_alloc; -+ uint32_t source_view_width; -+ uint32_t source_view_height; -+ uint32_t active_targets_num; -+ struct fbc_lpt_config lpt_config; -+}; -+ -+struct fbc_requested_compressed_size { -+ uint32_t preferred_size; -+ uint32_t preferred_size_alignment; -+ uint32_t min_size; -+ uint32_t min_size_alignment; -+ union { -+ struct { -+ /*Above preferred_size must be allocated in FB pool */ -+ uint32_t PREFERRED_MUST_BE_FRAME_BUFFER_POOL:1; -+ /*Above min_size must be allocated in FB pool */ -+ uint32_t MIN_MUST_BE_FRAME_BUFFER_POOL:1; -+ } flags; -+ uint32_t bits; -+ }; -+}; -+ -+struct fbc_compressed_surface_info { -+ union fbc_physical_address compressed_surface_address; -+ uint32_t allocated_size; -+ union { -+ struct { -+ uint32_t FB_POOL:1; /*Allocated in FB Pool */ -+ uint32_t DYNAMIC_ALLOC:1; /*Dynamic allocation */ -+ } allocation_flags; -+ uint32_t bits; -+ }; -+}; -+ -+enum fbc_hw_max_resolution_supported { -+ FBC_MAX_X = 3840, -+ FBC_MAX_Y = 2400 -+}; -+ -+struct fbc_max_resolution_supported { -+ uint32_t source_view_width; -+ uint32_t source_view_height; -+}; -+ -+struct compressor { -+ struct dc_context *ctx; -+ uint32_t attached_inst; -+ bool is_enabled; -+ -+ union { -+ uint32_t raw; -+ struct { -+ uint32_t FBC_SUPPORT:1; -+ uint32_t FB_POOL:1; -+ uint32_t DYNAMIC_ALLOC:1; -+ uint32_t LPT_SUPPORT:1; -+ uint32_t LPT_MC_CONFIG:1; -+ uint32_t DUMMY_BACKEND:1; -+ uint32_t CLK_GATING_DISABLED:1; -+ -+ } bits; -+ } options; -+ -+ union fbc_physical_address compr_surface_address; -+ -+ uint32_t embedded_panel_h_size; -+ uint32_t embedded_panel_v_size; -+ uint32_t memory_bus_width; -+ uint32_t banks_num; -+ uint32_t raw_size; -+ uint32_t channel_interleave_size; -+ uint32_t dram_channels_num; -+ -+ uint32_t allocated_size; -+ uint32_t preferred_requested_size; -+ uint32_t lpt_channels_num; -+ enum fbc_compress_ratio min_compress_ratio; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h -new file mode 100644 -index 0000000..dc246e8 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h -@@ -0,0 +1,39 @@ -+/* -+ * 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" -+ -+ -+struct dc { -+ struct dc_context *ctx; -+ -+ /** link-related data - begin **/ -+ uint8_t link_count; -+ struct core_link **links; -+ /** link-related data - end **/ -+ -+ /* TODO: determine max number of targets*/ -+ struct validate_context current_context; -+ struct resource_pool res_pool; -+ -+ /*Power State*/ -+ enum dc_video_power_state previous_power_state; -+ enum dc_video_power_state current_power_state; -+ -+ /* Inputs into BW and WM calculations. */ -+ struct bw_calcs_input_dceip bw_dceip; -+ struct bw_calcs_input_vbios bw_vbios; -+ -+ /* HW functions */ -+ struct hw_sequencer_funcs hwss; -+}; -+ -+#endif /* __CORE_DC_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h -new file mode 100644 -index 0000000..9682cf8 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h -@@ -0,0 +1,46 @@ -+/* -+ * Copyright 2015 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef _CORE_STATUS_H_ -+#define _CORE_STATUS_H_ -+ -+enum dc_status { -+ DC_OK = 1, -+ -+ DC_NO_CONTROLLER_RESOURCE, -+ DC_NO_STREAM_ENG_RESOURCE, -+ DC_NO_STREAM_AUDIO_RESOURCE, -+ DC_NO_CLOCK_SOURCE_RESOURCE, -+ DC_FAIL_CONTROLLER_VALIDATE, -+ DC_FAIL_ENC_VALIDATE, -+ DC_FAIL_ATTACH_SURFACES, -+ DC_NO_DP_LINK_BANDWIDTH, -+ DC_EXCEED_DONGLE_MAX_CLK, -+ DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ -+ -+ DC_ERROR_UNEXPECTED = -1 -+}; -+ -+#endif /* _CORE_STATUS_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h -new file mode 100644 -index 0000000..22ab6cb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h -@@ -0,0 +1,308 @@ -+/* -+ * Copyright 2015 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef _CORE_TYPES_H_ -+#define _CORE_TYPES_H_ -+ -+#include "dc.h" -+#include "bandwidth_calcs.h" -+#include "ddc_service_types.h" -+ -+struct core_stream; -+/********* core_target *************/ -+ -+#define CONST_DC_TARGET_TO_CORE(dc_target) \ -+ container_of(dc_target, const struct core_target, public) -+#define DC_TARGET_TO_CORE(dc_target) \ -+ container_of(dc_target, struct core_target, public) -+ -+#define MAX_PIPES 6 -+#define MAX_STREAMS 6 -+#define MAX_CLOCK_SOURCES 4 -+ -+struct core_target { -+ struct dc_target public; -+ struct dc_target_status status; -+ -+ struct core_stream *streams[MAX_STREAMS]; -+ uint8_t stream_count; -+ struct dc_context *ctx; -+}; -+ -+/********* core_surface **********/ -+#define DC_SURFACE_TO_CORE(dc_surface) \ -+ container_of(dc_surface, struct core_surface, public) -+ -+struct core_surface { -+ struct dc_surface public; -+ struct dc_surface_status status; -+ struct dc_context *ctx; -+}; -+ -+void enable_surface_flip_reporting(struct dc_surface *dc_surface, -+ uint32_t controller_id); -+ -+/********* core_stream ************/ -+#include "grph_object_id.h" -+#include "encoder_interface.h" -+#include "clock_source_interface.h" -+#include "audio_interface.h" -+ -+#define DC_STREAM_TO_CORE(dc_stream) container_of( \ -+ dc_stream, struct core_stream, public) -+ -+#define PIXEL_CLOCK 27030 -+ -+struct core_stream { -+ struct dc_stream public; -+ -+ /* field internal to DC */ -+ const struct core_sink *sink; -+ -+ struct clock_source *clock_source; -+ -+ struct mem_input *mi; -+ struct input_pixel_processor *ipp; -+ struct transform *xfm; -+ struct output_pixel_processor *opp; -+ struct timing_generator *tg; -+ struct stream_encoder *stream_enc; -+ struct display_clock *dis_clk; -+ -+ struct overscan_info overscan; -+ struct scaling_ratios ratios; -+ struct rect viewport; -+ struct scaling_taps taps; -+ enum pixel_format format; -+ -+ uint8_t controller_idx; -+ -+ struct audio *audio; -+ -+ enum signal_type signal; -+ -+ /* TODO: move these members into appropriate places (work in progress)*/ -+ /* timing validation (HDMI only) */ -+ uint32_t max_tmds_clk_from_edid_in_mhz; -+ /* maximum supported deep color depth for HDMI */ -+ enum dc_color_depth max_hdmi_deep_color; -+ /* maximum supported pixel clock for HDMI */ -+ uint32_t max_hdmi_pixel_clock; -+ /* end of TODO */ -+ -+ /*TODO: AUTO merge if possible*/ -+ struct pixel_clk_params pix_clk_params; -+ struct pll_settings pll_settings; -+ -+ /*fmt*/ -+ /*TODO: AUTO new codepath in apply_context to hw to -+ * generate these bw unrelated/no fail params*/ -+ struct bit_depth_reduction_params fmt_bit_depth; -+ struct clamping_and_pixel_encoding_params clamping; -+ struct hw_info_frame info_frame; -+ struct encoder_info_frame encoder_info_frame; -+ -+ struct audio_output audio_output; -+ struct dc_context *ctx; -+}; -+ -+ -+/************ core_sink *****************/ -+ -+#define DC_SINK_TO_CORE(dc_sink) \ -+ container_of(dc_sink, struct core_sink, public) -+ -+struct core_sink { -+ /** The public, read-only (for DM) area of sink. **/ -+ struct dc_sink public; -+ /** End-of-public area. **/ -+ -+ /** The 'protected' area - read/write access, for use only inside DC **/ -+ /* not used for now */ -+ struct core_link *link; -+ struct dc_context *ctx; -+ uint32_t dongle_max_pix_clk; -+ bool converter_disable_audio; -+}; -+ -+/************ link *****************/ -+#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public) -+ -+struct link_init_data { -+ const struct dc *dc; -+ struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ -+ uint32_t connector_index; /* this will be mapped to the HPD pins */ -+ uint32_t link_index; /* this is mapped to DAL display_index -+ TODO: remove it when DC is complete. */ -+ struct adapter_service *adapter_srv; -+}; -+ -+struct link_caps { -+ /* support for Spread Spectrum(SS) */ -+ bool ss_supported; -+ /* DP link settings (laneCount, linkRate, Spread) */ -+ uint32_t lane_count; -+ uint32_t rate; -+ uint32_t spread; -+ enum dpcd_revision dpcd_revision; -+}; -+ -+struct dpcd_caps { -+ union dpcd_rev dpcd_rev; -+ union max_lane_count max_ln_count; -+ -+ /* dongle type (DP converter, CV smart dongle) */ -+ enum display_dongle_type dongle_type; -+ /* Dongle's downstream count. */ -+ union sink_count sink_count; -+ /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, -+ indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ -+ bool is_dp_hdmi_s3d_converter; -+ -+ bool allow_invalid_MSA_timing_param; -+ bool panel_mode_edp; -+ uint32_t sink_dev_id; -+ uint32_t branch_dev_id; -+ int8_t branch_dev_name[6]; -+}; -+ -+union dp_wa { -+ struct { -+ /* keep DP receiver powered up on DisplayOutput */ -+ uint32_t KEEP_RECEIVER_POWERED:1; -+ -+ /* TODO: may add other member in.*/ -+ } bits; -+ uint32_t raw; -+}; -+ -+struct core_link { -+ struct dc_link public; -+ const struct dc *dc; -+ -+ struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ -+ -+ uint8_t connector_index; /* this will be mapped to the HPD pins */ -+ uint8_t link_index; /* this is mapped to DAL display_index -+ TODO: #flip remove it as soon as possible. */ -+ -+ struct adapter_service *adapter_srv; -+ struct connector *connector; -+ struct link_encoder *link_enc; -+ struct ddc_service *ddc; -+ struct graphics_object_id link_id; -+ /* caps is the same as reported_link_cap. link_traing use -+ * reported_link_cap. Will clean up. TODO */ -+ struct link_settings reported_link_cap; -+ struct link_settings verified_link_cap; -+ struct link_settings max_link_setting; -+ struct link_settings cur_link_settings; -+ struct lane_settings ln_setting; -+ struct dpcd_caps dpcd_caps; -+ unsigned int dpcd_sink_count; -+ -+ enum edp_revision edp_revision; -+ union dp_wa dp_wa; -+}; -+ -+#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 core_link_enable(struct core_stream *stream); -+ -+enum dc_status core_link_disable(struct core_stream *stream); -+ -+enum dc_status dc_link_validate_mode_timing( -+ const struct core_sink *sink, -+ struct core_link *link, -+ const struct dc_crtc_timing *timing); -+ -+void core_link_resume(struct core_link *link); -+ -+/********** DAL Core*********************/ -+#include "display_clock_interface.h" -+ -+struct resource_pool { -+ struct scaler_filter * scaler_filter; -+ -+ struct mem_input *mis[MAX_PIPES]; -+ struct input_pixel_processor *ipps[MAX_PIPES]; -+ struct transform *transforms[MAX_PIPES]; -+ struct output_pixel_processor *opps[MAX_PIPES]; -+ struct timing_generator *timing_generators[MAX_STREAMS]; -+ struct stream_encoder *stream_enc[MAX_STREAMS]; -+ -+ uint8_t controller_count; -+ uint8_t stream_enc_count; -+ -+ union supported_stream_engines stream_engines; -+ -+ struct clock_source *clock_sources[MAX_CLOCK_SOURCES]; -+ uint8_t clk_src_count; -+ -+ struct audio *audios[MAX_STREAMS]; -+ uint8_t audio_count; -+ -+ struct display_clock *display_clock; -+ struct adapter_service *adapter_srv; -+ struct irq_service *irqs; -+}; -+ -+struct controller_ctx { -+ struct core_surface *surface; -+ struct core_stream *stream; -+ struct flags { -+ bool unchanged; -+ bool timing_changed; -+ } flags; -+}; -+ -+struct resource_context { -+ struct resource_pool pool; -+ struct controller_ctx controller_ctx[MAX_PIPES]; -+ union supported_stream_engines used_stream_engines; -+ bool is_stream_enc_acquired[MAX_STREAMS]; -+ bool is_audio_acquired[MAX_STREAMS]; -+ uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; -+ }; -+ -+struct target_flags { -+ bool unchanged; -+}; -+struct validate_context { -+ struct core_target *targets[MAX_PIPES]; -+ struct target_flags target_flags[MAX_PIPES]; -+ uint8_t target_count; -+ -+ struct resource_context res_ctx; -+ -+ struct bw_calcs_input_mode_data bw_mode_data; -+ /* The output from BW and WM calculations. */ -+ struct bw_calcs_output bw_results; -+}; -+ -+ -+#endif /* _CORE_TYPES_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h -new file mode 100644 -index 0000000..e3e4778 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h -@@ -0,0 +1,51 @@ -+/* -+ * 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__ -+ -+bool dp_hbr_verify_link_cap( -+ struct core_link *link, -+ struct link_settings *known_limit_link_setting); -+ -+bool dp_validate_mode_timing( -+ struct core_link *link, -+ const struct dc_crtc_timing *timing); -+ -+void decide_link_settings( -+ struct core_stream *stream, -+ struct link_settings *link_setting); -+ -+bool perform_link_training( -+ struct core_link *link, -+ const struct link_settings *link_setting, -+ bool skip_video_pattern); -+ -+/*dp mst functions*/ -+bool is_mst_supported(struct core_link *link); -+ -+void detect_dp_sink_caps(struct core_link *link); -+ -+#endif /* __DC_LINK_DP_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h -new file mode 100644 -index 0000000..2c5738f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h -@@ -0,0 +1,170 @@ -+/* -+ * Copyright 2015 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_HW_SEQUENCER_H__ -+#define __DC_HW_SEQUENCER_H__ -+#include "core_types.h" -+ -+struct hw_sequencer_funcs { -+ -+ enum dc_status (*apply_ctx_to_hw)( -+ const struct dc *dc, -+ struct validate_context *context); -+ -+ void (*reset_hw_ctx)(struct dc *dc, -+ struct validate_context *context, -+ uint8_t target_count); -+ -+ bool (*set_plane_config)( -+ struct core_surface *surface, -+ struct core_target *target); -+ -+ bool (*update_plane_address)( -+ const struct core_surface *surface, -+ struct core_target *target); -+ -+ bool (*enable_memory_requests)(struct timing_generator *tg); -+ -+ bool (*disable_memory_requests)(struct timing_generator *tg); -+ -+ bool (*transform_power_up)(struct transform *xfm); -+ -+ bool (*cursor_set_attributes)( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_attributes *attributes); -+ -+ bool (*cursor_set_position)( -+ struct input_pixel_processor *ipp, -+ const struct dc_cursor_position *position); -+ -+ bool (*set_gamma_ramp)( -+ struct input_pixel_processor *ipp, -+ struct output_pixel_processor *opp, -+ const struct gamma_ramp *ramp, -+ const struct gamma_parameters *params); -+ -+ void (*power_down)(struct validate_context *context); -+ -+ void (*enable_accelerated_mode)(struct validate_context *context); -+ -+ void (*get_crtc_positions)( -+ struct timing_generator *tg, -+ int32_t *h_position, -+ int32_t *v_position); -+ -+ uint32_t (*get_vblank_counter)(struct timing_generator *tg); -+ -+ void (*enable_timing_synchronization)( -+ struct dc_context *dc_ctx, -+ uint32_t timing_generator_num, -+ struct timing_generator *tgs[]); -+ -+ void (*disable_vga)(struct timing_generator *tg); -+ -+ -+ -+ /* link encoder sequences */ -+ struct link_encoder *(*encoder_create)(const struct encoder_init_data *init); -+ -+ void (*encoder_destroy)(struct link_encoder **enc); -+ -+ enum encoder_result (*encoder_power_up)( -+ struct link_encoder *enc); -+ -+ enum encoder_result (*encoder_enable_output)( -+ struct link_encoder *enc, -+ const struct link_settings *link_settings, -+ enum engine_id engine, -+ enum clock_source_id clock_source, -+ enum signal_type signal, -+ enum dc_color_depth color_depth, -+ uint32_t pixel_clock); -+ -+ enum encoder_result (*encoder_disable_output)( -+ struct link_encoder *enc, -+ enum signal_type signal); -+ -+ void (*encoder_set_dp_phy_pattern)( -+ struct link_encoder *enc, -+ const struct encoder_set_dp_phy_pattern_param *param); -+ -+ enum encoder_result (*encoder_dp_set_lane_settings)( -+ struct link_encoder *enc, -+ const struct link_training_settings *link_settings); -+ -+ /* backlight control */ -+ void (*encoder_set_lcd_backlight_level)(struct link_encoder *enc, -+ uint32_t level); -+ -+ -+ /* power management */ -+ void (*clock_gating_power_up)( -+ struct dc_context *ctx, -+ bool enable); -+ -+ void (*enable_display_pipe_clock_gating)( -+ struct dc_context *ctx, -+ bool clock_gating); -+ -+ bool (*enable_display_power_gating)( -+ struct dc_context *ctx, -+ uint8_t controller_id, -+ struct bios_parser *bp, -+ enum pipe_gating_control power_gating); -+ -+ void (*set_afmt_memory_power_state)( -+ const struct dc_context *ctx, -+ enum engine_id id, -+ bool enable); -+ -+ /* resource management and validation*/ -+ bool (*construct_resource_pool)( -+ struct adapter_service *adapter_serv, -+ struct dc *dc, -+ struct resource_pool *pool); -+ -+ void (*destruct_resource_pool)(struct resource_pool *pool); -+ -+ enum dc_status (*validate_with_context)( -+ const struct dc *dc, -+ const struct dc_validation_set set[], -+ uint8_t set_count, -+ struct validate_context *context); -+ -+ enum dc_status (*validate_bandwidth)( -+ const struct dc *dc, -+ struct validate_context *context); -+ void (*program_bw)( -+ struct dc *dc, -+ struct validate_context *context); -+ -+}; -+ -+bool dc_construct_hw_sequencer( -+ struct adapter_service *adapter_serv, -+ struct dc *dc); -+ -+ -+#endif /* __DC_HW_SEQUENCER_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h -new file mode 100644 -index 0000000..602b4cb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h -@@ -0,0 +1,66 @@ -+/* -+ * Copyright 2015 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IPP_H__ -+#define __DAL_IPP_H__ -+ -+#include "include/plane_types.h" -+#include "include/grph_object_id.h" -+#include "include/grph_csc_types.h" -+#include "include/video_csc_types.h" -+#include "include/hw_sequencer_types.h" -+ -+ -+#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; -+}; -+ -+enum wide_gamut_degamma_mode { -+ /* 00 - BITS1:0 Bypass */ -+ WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_BYPASS, -+ /* 0x1 - PWL gamma ROM A */ -+ WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_A, -+ /* 0x2 - PWL gamma ROM B */ -+ WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_B, -+ /* 00 - BITS5:4 Bypass */ -+ WIDE_GAMUT_DEGAMMA_MODE_OVL_BYPASS, -+ /* 0x1 - PWL gamma ROM A */ -+ WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_A, -+ /* 0x2 - PWL gamma ROM B */ -+ WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_B, -+}; -+ -+struct dcp_video_matrix { -+ enum ovl_color_space color_space; -+ int32_t value[MAXTRIX_COEFFICIENTS_NUMBER]; -+}; -+ -+#endif /* __DAL_IPP_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h -new file mode 100644 -index 0000000..7110357 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h -@@ -0,0 +1,67 @@ -+/* -+ * 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); -+ -+enum dc_status dp_enable_link_phy( -+ struct core_link *link, -+ enum signal_type signal, -+ enum engine_id engine, -+ const struct link_settings *link_settings); -+ -+void dp_receiver_power_ctrl(struct core_link *link, bool on); -+ -+void dp_disable_link_phy(struct core_link *link, enum signal_type signal); -+ -+bool dp_set_hw_training_pattern( -+ struct core_link *link, -+ enum hw_dp_training_pattern pattern); -+ -+bool dp_set_hw_lane_settings( -+ struct core_link *link, -+ const struct link_training_settings *link_settings); -+ -+void dp_set_hw_test_pattern( -+ struct core_link *link, -+ enum dp_test_pattern test_pattern); -+ -+enum dp_panel_mode dp_get_panel_mode(struct core_link *link); -+ -+#endif /* __DC_LINK_HWSS_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h -new file mode 100644 -index 0000000..458e7b5 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h -@@ -0,0 +1,55 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_MEM_INPUT_H__ -+#define __DAL_MEM_INPUT_H__ -+ -+#include "include/plane_types.h" -+#include "include/grph_object_id.h" -+#include "dc.h" -+ -+struct mem_input { -+ struct dc_context *ctx; -+ uint32_t inst; -+}; -+ -+enum stutter_mode_type { -+ STUTTER_MODE_LEGACY = 0X00000001, -+ STUTTER_MODE_ENHANCED = 0X00000002, -+ STUTTER_MODE_FID_NBP_STATE = 0X00000004, -+ STUTTER_MODE_WATERMARK_NBP_STATE = 0X00000008, -+ STUTTER_MODE_SINGLE_DISPLAY_MODEL = 0X00000010, -+ STUTTER_MODE_MIXED_DISPLAY_MODEL = 0X00000020, -+ STUTTER_MODE_DUAL_DMIF_BUFFER = 0X00000040, -+ STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION = 0X00000080, -+ STUTTER_MODE_NO_ADVANCED_REQUEST = 0X00000100, -+ STUTTER_MODE_NO_LB_RESET = 0X00000200, -+ STUTTER_MODE_DISABLED = 0X00000400, -+ STUTTER_MODE_AGGRESSIVE_MARKS = 0X00000800, -+ STUTTER_MODE_URGENCY = 0X00001000, -+ STUTTER_MODE_QUAD_DMIF_BUFFER = 0X00002000, -+ STUTTER_MODE_NOT_USED = 0X00008000 -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h -new file mode 100644 -index 0000000..3293e3b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h -@@ -0,0 +1,206 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_OPP_H__ -+#define __DAL_OPP_H__ -+ -+#include "dc_temp.h" -+#include "grph_object_id.h" -+#include "grph_csc_types.h" -+ -+struct fixed31_32; -+ -+/* TODO: Need cleanup */ -+ -+enum wide_gamut_regamma_mode { -+ /* 0x0 - BITS2:0 Bypass */ -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS, -+ /* 0x1 - Fixed curve sRGB 2.4 */ -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24, -+ /* 0x2 - Fixed curve xvYCC 2.22 */ -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22, -+ /* 0x3 - Programmable control A */ -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A, -+ /* 0x4 - Programmable control B */ -+ WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B, -+ /* 0x0 - BITS6:4 Bypass */ -+ WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS, -+ /* 0x1 - Fixed curve sRGB 2.4 */ -+ WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24, -+ /* 0x2 - Fixed curve xvYCC 2.22 */ -+ WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22, -+ /* 0x3 - Programmable control A */ -+ WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A, -+ /* 0x4 - Programmable control B */ -+ WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B -+}; -+ -+struct pwl_result_data { -+ struct fixed31_32 red; -+ struct fixed31_32 green; -+ struct fixed31_32 blue; -+ -+ struct fixed31_32 delta_red; -+ struct fixed31_32 delta_green; -+ struct fixed31_32 delta_blue; -+ -+ uint32_t red_reg; -+ uint32_t green_reg; -+ uint32_t blue_reg; -+ -+ uint32_t delta_red_reg; -+ uint32_t delta_green_reg; -+ uint32_t delta_blue_reg; -+}; -+ -+struct gamma_pixel { -+ struct fixed31_32 r; -+ struct fixed31_32 g; -+ struct fixed31_32 b; -+}; -+ -+struct gamma_curve { -+ uint32_t offset; -+ uint32_t segments_num; -+}; -+ -+struct curve_points { -+ struct fixed31_32 x; -+ struct fixed31_32 y; -+ struct fixed31_32 offset; -+ struct fixed31_32 slope; -+ -+ uint32_t custom_float_x; -+ uint32_t custom_float_y; -+ uint32_t custom_float_offset; -+ uint32_t custom_float_slope; -+}; -+ -+enum channel_name { -+ CHANNEL_NAME_RED, -+ CHANNEL_NAME_GREEN, -+ CHANNEL_NAME_BLUE -+}; -+ -+struct custom_float_format { -+ uint32_t mantissa_bits; -+ uint32_t exponenta_bits; -+ bool sign; -+}; -+ -+struct custom_float_value { -+ uint32_t mantissa; -+ uint32_t exponenta; -+ uint32_t value; -+ bool negative; -+}; -+ -+struct hw_x_point { -+ uint32_t custom_float_x; -+ uint32_t custom_float_x_adjusted; -+ struct fixed31_32 x; -+ struct fixed31_32 adjusted_x; -+ struct fixed31_32 regamma_y_red; -+ struct fixed31_32 regamma_y_green; -+ struct fixed31_32 regamma_y_blue; -+ -+}; -+ -+struct pwl_float_data_ex { -+ struct fixed31_32 r; -+ struct fixed31_32 g; -+ struct fixed31_32 b; -+ struct fixed31_32 delta_r; -+ struct fixed31_32 delta_g; -+ struct fixed31_32 delta_b; -+}; -+ -+enum hw_point_position { -+ /* hw point sits between left and right sw points */ -+ HW_POINT_POSITION_MIDDLE, -+ /* hw point lays left from left (smaller) sw point */ -+ HW_POINT_POSITION_LEFT, -+ /* hw point lays stays from right (bigger) sw point */ -+ HW_POINT_POSITION_RIGHT -+}; -+ -+struct gamma_point { -+ int32_t left_index; -+ int32_t right_index; -+ enum hw_point_position pos; -+ struct fixed31_32 coeff; -+}; -+ -+struct pixel_gamma_point { -+ struct gamma_point r; -+ struct gamma_point g; -+ struct gamma_point b; -+}; -+ -+struct gamma_coefficients { -+ struct fixed31_32 a0[3]; -+ struct fixed31_32 a1[3]; -+ struct fixed31_32 a2[3]; -+ struct fixed31_32 a3[3]; -+ struct fixed31_32 user_gamma[3]; -+ struct fixed31_32 user_contrast; -+ struct fixed31_32 user_brightness; -+}; -+ -+struct csc_adjustments { -+ struct fixed31_32 contrast; -+ struct fixed31_32 saturation; -+ struct fixed31_32 brightness; -+ struct fixed31_32 hue; -+}; -+ -+struct pwl_float_data { -+ struct fixed31_32 r; -+ struct fixed31_32 g; -+ struct fixed31_32 b; -+}; -+ -+ -+/* TODO: Use when we redefine the OPP interface */ -+enum opp_regamma { -+ OPP_REGAMMA_BYPASS = 0, -+ OPP_REGAMMA_SRGB, -+ OPP_REGAMMA_3_6, -+ OPP_REGAMMA_PQ, -+ OPP_REGAMMA_PQ_INTERIM, -+}; -+ -+struct output_pixel_processor { -+ struct dc_context *ctx; -+ uint32_t inst; -+}; -+ -+enum fmt_stereo_action { -+ FMT_STEREO_ACTION_ENABLE = 0, -+ FMT_STEREO_ACTION_DISABLE, -+ FMT_STEREO_ACTION_UPDATE_POLARITY -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h -new file mode 100644 -index 0000000..0e0ba47 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright 2015 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ */ -+ -+#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ -+#define DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ -+ -+#include "core_types.h" -+#include "core_status.h" -+#include "core_dc.h" -+ -+void build_scaling_params( -+ const struct dc_surface *surface, -+ struct core_stream *stream); -+ -+void build_scaling_params_for_context( -+ const struct dc *dc, -+ struct validate_context *context); -+ -+void unreference_clock_source( -+ struct resource_context *res_ctx, -+ struct clock_source *clock_source); -+ -+void reference_clock_source( -+ struct resource_context *res_ctx, -+ struct clock_source *clock_source); -+ -+bool is_same_timing( -+ const struct dc_crtc_timing *timing1, -+ const struct dc_crtc_timing *timing2); -+ -+struct clock_source *find_used_clk_src_for_sharing( -+ struct validate_context *context, -+ struct core_stream *stream); -+ -+bool logical_attach_surfaces_to_target( -+ struct dc_surface *surfaces[], -+ uint8_t surface_count, -+ struct dc_target *dc_target); -+ -+#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/dc/inc/transform.h b/drivers/gpu/drm/amd/dal/dc/inc/transform.h -new file mode 100644 -index 0000000..8e111ce ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/inc/transform.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_TRANSFORM_H__ -+#define __DAL_TRANSFORM_H__ -+ -+#include "include/scaler_types.h" -+#include "calcs/scaler_filter.h" -+#include "grph_object_id.h" -+ -+enum scaling_type { -+ SCALING_TYPE_NO_SCALING = 0, -+ SCALING_TYPE_UPSCALING, -+ SCALING_TYPE_DOWNSCALING -+}; -+ -+struct transform { -+ struct dc_context *ctx; -+ uint32_t inst; -+ struct scaler_filter *filter; -+}; -+ -+struct scaler_taps_and_ratio { -+ uint32_t h_tap; -+ uint32_t v_tap; -+ uint32_t lo_ratio; -+ uint32_t hi_ratio; -+}; -+ -+struct scaler_taps { -+ uint32_t h_tap; -+ uint32_t v_tap; -+}; -+ -+struct sclv_ratios_inits { -+ uint32_t chroma_enable; -+ uint32_t h_int_scale_ratio_luma; -+ uint32_t h_int_scale_ratio_chroma; -+ uint32_t v_int_scale_ratio_luma; -+ uint32_t v_int_scale_ratio_chroma; -+ struct init_int_and_frac h_init_luma; -+ struct init_int_and_frac h_init_chroma; -+ struct init_int_and_frac v_init_luma; -+ struct init_int_and_frac v_init_chroma; -+ struct init_int_and_frac h_init_lumabottom; -+ struct init_int_and_frac h_init_chromabottom; -+ struct init_int_and_frac v_init_lumabottom; -+ struct init_int_and_frac v_init_chromabottom; -+}; -+ -+enum lb_pixel_depth { -+ /* do not change the values because it is used as bit vector */ -+ LB_PIXEL_DEPTH_18BPP = 1, -+ LB_PIXEL_DEPTH_24BPP = 2, -+ LB_PIXEL_DEPTH_30BPP = 4, -+ LB_PIXEL_DEPTH_36BPP = 8 -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/Makefile b/drivers/gpu/drm/amd/dal/dc/irq/Makefile -new file mode 100644 -index 0000000..f1c5faf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq/Makefile -@@ -0,0 +1,21 @@ -+# -+# Makefile for the 'audio' sub-component of DAL. -+# It provides the control and status of HW adapter resources, -+# that are global for the ASIC and sharable between pipes. -+ -+IRQ = irq_service.o -+ -+AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ)) -+ -+AMD_DAL_FILES += $(AMD_DAL_IRQ) -+ -+############################################################################### -+# DCE 11x -+############################################################################### -+ifdef CONFIG_DRM_AMD_DAL_DCE11_0 -+IRQ_DCE11 = irq_service_dce110.o -+ -+AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11)) -+ -+AMD_DAL_FILES += $(AMD_DAL_IRQ_DCE11) -+endif -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c -new file mode 100644 -index 0000000..2a4f14c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c -@@ -0,0 +1,389 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#include "dal_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 = dal_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 = dal_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); -+ -+ dal_write_reg(irq_service->ctx, info->enable_reg, value); -+ -+ return true; -+} -+ -+static const struct irq_source_info_funcs hpd_irq_info_funcs = { -+ .set = NULL, -+ .ack = hpd_ack -+}; -+ -+static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { -+ .set = NULL, -+ .ack = NULL -+}; -+ -+static const struct irq_source_info_funcs pflip_irq_info_funcs = { -+ .set = NULL, -+ .ack = NULL -+}; -+ -+static const struct irq_source_info_funcs vblank_irq_info_funcs = { -+ .set = NULL, -+ .ack = NULL -+}; -+ -+#define hpd_int_entry(reg_num)\ -+ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ -+ .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ -+ .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ -+ .enable_value = {\ -+ DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ -+ ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ -+ },\ -+ .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ -+ .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ -+ .ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ -+ .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ -+ .funcs = &hpd_irq_info_funcs\ -+ } -+ -+#define hpd_rx_int_entry(reg_num)\ -+ [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ -+ .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ -+ .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ -+ .enable_value = {\ -+ DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ -+ ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ -+ .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ -+ .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ -+ .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ -+ .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ -+ .funcs = &hpd_rx_irq_info_funcs\ -+ } -+#define pflip_int_entry(reg_num)\ -+ [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ -+ .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ -+ .enable_mask =\ -+ GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ -+ .enable_value = {\ -+ GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ -+ ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ -+ .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ -+ .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ -+ .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ -+ .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ -+ .funcs = &pflip_irq_info_funcs\ -+ } -+ -+#define vsync_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_CRTC ## reg_num ## VSYNC] = dummy_irq_entry() -+ -+#define vupdate_int_entry(reg_num)\ -+ [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ -+ .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ -+ .enable_mask =\ -+ CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ -+ .enable_value = {\ -+ CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ -+ ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ -+ .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ -+ .ack_mask =\ -+ CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ -+ .ack_value =\ -+ CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ -+ .funcs = &vblank_irq_info_funcs\ -+ } -+ -+#define dummy_irq_entry() \ -+ {\ -+ .funcs = &dummy_irq_info_funcs\ -+ } -+ -+#define i2c_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() -+ -+#define azalia_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_AZALIA ## reg_num] = dummy_irq_entry() -+ -+#define dp_sink_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() -+ -+#define gpio_pad_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() -+ -+#define dc_underflow_int_entry(reg_num) \ -+ [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() -+ -+static bool dummy_set( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info, -+ bool enable) -+{ -+ dal_logger_write( -+ irq_service->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_IRQ_SERVICE, -+ "%s: called for non-implemented irq source\n", -+ __func__); -+ return false; -+} -+ -+static bool dummy_ack( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info) -+{ -+ dal_logger_write( -+ irq_service->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_IRQ_SERVICE, -+ "%s: called for non-implemented irq source\n", -+ __func__); -+ return false; -+} -+ -+static const struct irq_source_info_funcs dummy_irq_info_funcs = { -+ .set = dummy_set, -+ .ack = dummy_ack -+}; -+ -+static const struct irq_source_info -+irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { -+ [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), -+ hpd_int_entry(0), -+ hpd_int_entry(1), -+ hpd_int_entry(2), -+ hpd_int_entry(3), -+ hpd_int_entry(4), -+ hpd_int_entry(5), -+ hpd_rx_int_entry(0), -+ hpd_rx_int_entry(1), -+ hpd_rx_int_entry(2), -+ hpd_rx_int_entry(3), -+ hpd_rx_int_entry(4), -+ hpd_rx_int_entry(5), -+ i2c_int_entry(1), -+ i2c_int_entry(2), -+ i2c_int_entry(3), -+ i2c_int_entry(4), -+ i2c_int_entry(5), -+ i2c_int_entry(6), -+ azalia_int_entry(0), -+ azalia_int_entry(1), -+ azalia_int_entry(2), -+ azalia_int_entry(3), -+ azalia_int_entry(4), -+ azalia_int_entry(5), -+ dp_sink_int_entry(1), -+ dp_sink_int_entry(2), -+ dp_sink_int_entry(3), -+ dp_sink_int_entry(4), -+ dp_sink_int_entry(5), -+ dp_sink_int_entry(6), -+ vsync_int_entry(1), -+ vsync_int_entry(2), -+ vsync_int_entry(3), -+ vsync_int_entry(3), -+ vsync_int_entry(4), -+ vsync_int_entry(5), -+ [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), -+ pflip_int_entry(0), -+ pflip_int_entry(1), -+ pflip_int_entry(2), -+ pflip_int_entry(3), -+ pflip_int_entry(4), -+ pflip_int_entry(5), -+ [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), -+ gpio_pad_int_entry(0), -+ gpio_pad_int_entry(1), -+ gpio_pad_int_entry(2), -+ gpio_pad_int_entry(3), -+ gpio_pad_int_entry(4), -+ gpio_pad_int_entry(5), -+ gpio_pad_int_entry(6), -+ gpio_pad_int_entry(7), -+ gpio_pad_int_entry(8), -+ gpio_pad_int_entry(9), -+ gpio_pad_int_entry(10), -+ gpio_pad_int_entry(11), -+ gpio_pad_int_entry(12), -+ gpio_pad_int_entry(13), -+ gpio_pad_int_entry(14), -+ gpio_pad_int_entry(15), -+ gpio_pad_int_entry(16), -+ gpio_pad_int_entry(17), -+ gpio_pad_int_entry(18), -+ gpio_pad_int_entry(19), -+ gpio_pad_int_entry(20), -+ gpio_pad_int_entry(21), -+ gpio_pad_int_entry(22), -+ gpio_pad_int_entry(23), -+ gpio_pad_int_entry(24), -+ gpio_pad_int_entry(25), -+ gpio_pad_int_entry(26), -+ gpio_pad_int_entry(27), -+ gpio_pad_int_entry(28), -+ gpio_pad_int_entry(29), -+ gpio_pad_int_entry(30), -+ dc_underflow_int_entry(1), -+ dc_underflow_int_entry(2), -+ dc_underflow_int_entry(3), -+ dc_underflow_int_entry(4), -+ dc_underflow_int_entry(5), -+ dc_underflow_int_entry(6), -+ [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), -+ [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), -+ vupdate_int_entry(0), -+ vupdate_int_entry(1), -+ vupdate_int_entry(2), -+ vupdate_int_entry(3), -+ vupdate_int_entry(4), -+ vupdate_int_entry(5), -+}; -+ -+static enum dc_irq_source to_dal_irq_source( -+ struct irq_service *irq_service, -+ uint32_t src_id, -+ uint32_t ext_id) -+{ -+ switch (src_id) { -+ case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE1; -+ case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE2; -+ case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE3; -+ case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE4; -+ case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE5; -+ case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT: -+ return DC_IRQ_SOURCE_VUPDATE6; -+ case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP1; -+ case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP2; -+ case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP3; -+ case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP4; -+ case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP5; -+ case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP: -+ return DC_IRQ_SOURCE_PFLIP6; -+ -+ case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A: -+ /* generic src_id for all HPD and HPDRX interrupts */ -+ switch (ext_id) { -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A: -+ return DC_IRQ_SOURCE_HPD1; -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B: -+ return DC_IRQ_SOURCE_HPD2; -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C: -+ return DC_IRQ_SOURCE_HPD3; -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D: -+ return DC_IRQ_SOURCE_HPD4; -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E: -+ return DC_IRQ_SOURCE_HPD5; -+ case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F: -+ return DC_IRQ_SOURCE_HPD6; -+ case VISLANDS30_IV_EXTID_HPD_RX_A: -+ return DC_IRQ_SOURCE_HPD1RX; -+ case VISLANDS30_IV_EXTID_HPD_RX_B: -+ return DC_IRQ_SOURCE_HPD2RX; -+ case VISLANDS30_IV_EXTID_HPD_RX_C: -+ return DC_IRQ_SOURCE_HPD3RX; -+ case VISLANDS30_IV_EXTID_HPD_RX_D: -+ return DC_IRQ_SOURCE_HPD4RX; -+ case VISLANDS30_IV_EXTID_HPD_RX_E: -+ return DC_IRQ_SOURCE_HPD5RX; -+ case VISLANDS30_IV_EXTID_HPD_RX_F: -+ return DC_IRQ_SOURCE_HPD6RX; -+ default: -+ return DC_IRQ_SOURCE_INVALID; -+ } -+ break; -+ -+ default: -+ return DC_IRQ_SOURCE_INVALID; -+ } -+} -+ -+static const struct irq_service_funcs irq_service_funcs_dce110 = { -+ .to_dal_irq_source = to_dal_irq_source -+}; -+ -+bool construct( -+ struct irq_service *irq_service, -+ struct irq_service_init_data *init_data) -+{ -+ if (!dal_irq_service_construct(irq_service, init_data)) -+ return false; -+ -+ irq_service->info = irq_source_info_dce110; -+ irq_service->funcs = &irq_service_funcs_dce110; -+ -+ return true; -+} -+ -+struct irq_service *dal_irq_service_dce110_create( -+ struct irq_service_init_data *init_data) -+{ -+ struct irq_service *irq_service = dc_service_alloc(init_data->ctx, sizeof(*irq_service)); -+ -+ if (!irq_service) -+ return NULL; -+ -+ if (construct(irq_service, init_data)) -+ return irq_service; -+ -+ dc_service_free(init_data->ctx, irq_service); -+ return NULL; -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h -new file mode 100644 -index 0000000..d6c28e9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_SERVICE_DCE110_H__ -+#define __DAL_IRQ_SERVICE_DCE110_H__ -+ -+#include "../irq_service.h" -+ -+struct irq_service *dal_irq_service_dce110_create( -+ struct irq_service_init_data *init_data); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c -new file mode 100644 -index 0000000..0c7429c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.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 "dal_services.h" -+ -+#include "include/irq_service_interface.h" -+#include "include/logger_interface.h" -+ -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+#include "dce110/irq_service_dce110.h" -+#endif -+ -+#include "irq_service.h" -+ -+bool dal_irq_service_construct( -+ struct irq_service *irq_service, -+ struct irq_service_init_data *init_data) -+{ -+ if (!init_data || !init_data->ctx) -+ return false; -+ -+ irq_service->ctx = init_data->ctx; -+ return true; -+} -+ -+struct irq_service *dal_irq_service_create( -+ enum dce_version version, -+ struct irq_service_init_data *init_data) -+{ -+ switch (version) { -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ case DCE_VERSION_11_0: -+ return dal_irq_service_dce110_create(init_data); -+#endif -+ default: -+ return NULL; -+ } -+} -+ -+void dal_irq_service_destroy(struct irq_service **irq_service) -+{ -+ if (!irq_service || !*irq_service) { -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+ -+ dc_service_free((*irq_service)->ctx, *irq_service); -+ -+ *irq_service = NULL; -+} -+ -+const struct irq_source_info *find_irq_source_info( -+ struct irq_service *irq_service, -+ enum dc_irq_source source) -+{ -+ if (source > DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID) -+ return NULL; -+ -+ return &irq_service->info[source]; -+} -+ -+void dal_irq_service_set_generic( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info, -+ bool enable) -+{ -+ uint32_t addr = info->enable_reg; -+ uint32_t value = dal_read_reg(irq_service->ctx, addr); -+ -+ value = (value & ~info->enable_mask) | -+ (info->enable_value[enable ? 0 : 1] & info->enable_mask); -+ dal_write_reg(irq_service->ctx, addr, value); -+} -+ -+bool dal_irq_service_set( -+ struct irq_service *irq_service, -+ enum dc_irq_source source, -+ bool enable) -+{ -+ const struct irq_source_info *info = -+ find_irq_source_info(irq_service, source); -+ -+ if (!info) { -+ dal_logger_write( -+ irq_service->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_IRQ_SERVICE, -+ "%s: cannot find irq info table entry for %d\n", -+ __func__, -+ source); -+ return false; -+ } -+ -+ dal_irq_service_ack(irq_service, source); -+ -+ if (info->funcs->set) -+ return info->funcs->set(irq_service, info, enable); -+ -+ dal_irq_service_set_generic(irq_service, info, enable); -+ -+ return true; -+} -+ -+void dal_irq_service_ack_generic( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info) -+{ -+ uint32_t addr = info->ack_reg; -+ uint32_t value = dal_read_reg(irq_service->ctx, addr); -+ -+ value = (value & ~info->ack_mask) | -+ (info->ack_value & info->ack_mask); -+ dal_write_reg(irq_service->ctx, addr, value); -+} -+ -+bool dal_irq_service_ack( -+ struct irq_service *irq_service, -+ enum dc_irq_source source) -+{ -+ const struct irq_source_info *info = -+ find_irq_source_info(irq_service, source); -+ -+ if (!info) { -+ dal_logger_write( -+ irq_service->ctx->logger, -+ LOG_MAJOR_ERROR, -+ LOG_MINOR_COMPONENT_IRQ_SERVICE, -+ "%s: cannot find irq info table entry for %d\n", -+ __func__, -+ source); -+ return false; -+ } -+ -+ if (info->funcs->ack) -+ return info->funcs->ack(irq_service, info); -+ -+ dal_irq_service_ack_generic(irq_service, info); -+ -+ return true; -+} -+ -+enum dc_irq_source dal_irq_service_to_irq_source( -+ struct irq_service *irq_service, -+ uint32_t src_id, -+ uint32_t ext_id) -+{ -+ return irq_service->funcs->to_dal_irq_source( -+ irq_service, -+ src_id, -+ ext_id); -+} -diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h -new file mode 100644 -index 0000000..a2a2d69 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h -@@ -0,0 +1,85 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_SERVICE_H__ -+#define __DAL_IRQ_SERVICE_H__ -+ -+#include "include/irq_service_interface.h" -+ -+#include "irq_types.h" -+ -+struct irq_service; -+struct irq_source_info; -+ -+struct irq_source_info_funcs { -+ bool (*set)( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info, -+ bool enable); -+ bool (*ack)( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info); -+}; -+ -+struct irq_source_info { -+ uint32_t src_id; -+ uint32_t ext_id; -+ uint32_t enable_reg; -+ uint32_t enable_mask; -+ uint32_t enable_value[2]; -+ uint32_t ack_reg; -+ uint32_t ack_mask; -+ uint32_t ack_value; -+ uint32_t status_reg; -+ const struct irq_source_info_funcs *funcs; -+}; -+ -+struct irq_service_funcs { -+ enum dc_irq_source (*to_dal_irq_source)( -+ struct irq_service *irq_service, -+ uint32_t src_id, -+ uint32_t ext_id); -+}; -+ -+struct irq_service { -+ struct dc_context *ctx; -+ const struct irq_source_info *info; -+ const struct irq_service_funcs *funcs; -+}; -+ -+bool dal_irq_service_construct( -+ struct irq_service *irq_service, -+ struct irq_service_init_data *init_data); -+ -+void dal_irq_service_ack_generic( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info); -+ -+void dal_irq_service_set_generic( -+ struct irq_service *irq_service, -+ const struct irq_source_info *info, -+ bool enable); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/dc/irq_types.h b/drivers/gpu/drm/amd/dal/dc/irq_types.h -new file mode 100644 -index 0000000..051a1f6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/dc/irq_types.h -@@ -0,0 +1,199 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_TYPES_H__ -+#define __DAL_IRQ_TYPES_H__ -+ -+struct dc_context; -+ -+typedef void (*interrupt_handler)(void *); -+ -+typedef void *irq_handler_idx; -+#define DAL_INVALID_IRQ_HANDLER_IDX NULL -+ -+ -+/* The order of the IRQ sources is important and MUST match the one's -+of base driver */ -+enum dc_irq_source { -+ /* Use as mask to specify invalid irq source */ -+ DC_IRQ_SOURCE_INVALID = 0, -+ -+ DC_IRQ_SOURCE_HPD1, -+ DC_IRQ_SOURCE_HPD2, -+ DC_IRQ_SOURCE_HPD3, -+ DC_IRQ_SOURCE_HPD4, -+ DC_IRQ_SOURCE_HPD5, -+ DC_IRQ_SOURCE_HPD6, -+ -+ DC_IRQ_SOURCE_HPD1RX, -+ DC_IRQ_SOURCE_HPD2RX, -+ DC_IRQ_SOURCE_HPD3RX, -+ DC_IRQ_SOURCE_HPD4RX, -+ DC_IRQ_SOURCE_HPD5RX, -+ DC_IRQ_SOURCE_HPD6RX, -+ -+ DC_IRQ_SOURCE_I2C_DDC1, -+ DC_IRQ_SOURCE_I2C_DDC2, -+ DC_IRQ_SOURCE_I2C_DDC3, -+ DC_IRQ_SOURCE_I2C_DDC4, -+ DC_IRQ_SOURCE_I2C_DDC5, -+ DC_IRQ_SOURCE_I2C_DDC6, -+ -+ DC_IRQ_SOURCE_AZALIA0, -+ DC_IRQ_SOURCE_AZALIA1, -+ DC_IRQ_SOURCE_AZALIA2, -+ DC_IRQ_SOURCE_AZALIA3, -+ DC_IRQ_SOURCE_AZALIA4, -+ DC_IRQ_SOURCE_AZALIA5, -+ -+ DC_IRQ_SOURCE_DPSINK1, -+ DC_IRQ_SOURCE_DPSINK2, -+ DC_IRQ_SOURCE_DPSINK3, -+ DC_IRQ_SOURCE_DPSINK4, -+ DC_IRQ_SOURCE_DPSINK5, -+ DC_IRQ_SOURCE_DPSINK6, -+ -+ DC_IRQ_SOURCE_CRTC1VSYNC, -+ DC_IRQ_SOURCE_CRTC2VSYNC, -+ DC_IRQ_SOURCE_CRTC3VSYNC, -+ DC_IRQ_SOURCE_CRTC4VSYNC, -+ DC_IRQ_SOURCE_CRTC5VSYNC, -+ DC_IRQ_SOURCE_CRTC6VSYNC, -+ DC_IRQ_SOURCE_TIMER, -+ -+ DC_IRQ_SOURCE_PFLIP_FIRST, -+ DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST, -+ DC_IRQ_SOURCE_PFLIP2, -+ DC_IRQ_SOURCE_PFLIP3, -+ DC_IRQ_SOURCE_PFLIP4, -+ DC_IRQ_SOURCE_PFLIP5, -+ DC_IRQ_SOURCE_PFLIP6, -+ DC_IRQ_SOURCE_PFLIP_UNDERLAY0, -+ DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0, -+ -+ DC_IRQ_SOURCE_GPIOPAD0, -+ DC_IRQ_SOURCE_GPIOPAD1, -+ DC_IRQ_SOURCE_GPIOPAD2, -+ DC_IRQ_SOURCE_GPIOPAD3, -+ DC_IRQ_SOURCE_GPIOPAD4, -+ DC_IRQ_SOURCE_GPIOPAD5, -+ DC_IRQ_SOURCE_GPIOPAD6, -+ DC_IRQ_SOURCE_GPIOPAD7, -+ DC_IRQ_SOURCE_GPIOPAD8, -+ DC_IRQ_SOURCE_GPIOPAD9, -+ DC_IRQ_SOURCE_GPIOPAD10, -+ DC_IRQ_SOURCE_GPIOPAD11, -+ DC_IRQ_SOURCE_GPIOPAD12, -+ DC_IRQ_SOURCE_GPIOPAD13, -+ DC_IRQ_SOURCE_GPIOPAD14, -+ DC_IRQ_SOURCE_GPIOPAD15, -+ DC_IRQ_SOURCE_GPIOPAD16, -+ DC_IRQ_SOURCE_GPIOPAD17, -+ DC_IRQ_SOURCE_GPIOPAD18, -+ DC_IRQ_SOURCE_GPIOPAD19, -+ DC_IRQ_SOURCE_GPIOPAD20, -+ DC_IRQ_SOURCE_GPIOPAD21, -+ DC_IRQ_SOURCE_GPIOPAD22, -+ DC_IRQ_SOURCE_GPIOPAD23, -+ DC_IRQ_SOURCE_GPIOPAD24, -+ DC_IRQ_SOURCE_GPIOPAD25, -+ DC_IRQ_SOURCE_GPIOPAD26, -+ DC_IRQ_SOURCE_GPIOPAD27, -+ DC_IRQ_SOURCE_GPIOPAD28, -+ DC_IRQ_SOURCE_GPIOPAD29, -+ DC_IRQ_SOURCE_GPIOPAD30, -+ -+ DC_IRQ_SOURCE_DC1UNDERFLOW, -+ DC_IRQ_SOURCE_DC2UNDERFLOW, -+ DC_IRQ_SOURCE_DC3UNDERFLOW, -+ DC_IRQ_SOURCE_DC4UNDERFLOW, -+ DC_IRQ_SOURCE_DC5UNDERFLOW, -+ DC_IRQ_SOURCE_DC6UNDERFLOW, -+ -+ DC_IRQ_SOURCE_DMCU_SCP, -+ DC_IRQ_SOURCE_VBIOS_SW, -+ -+ DC_IRQ_SOURCE_VUPDATE1, -+ DC_IRQ_SOURCE_VUPDATE2, -+ DC_IRQ_SOURCE_VUPDATE3, -+ DC_IRQ_SOURCE_VUPDATE4, -+ DC_IRQ_SOURCE_VUPDATE5, -+ DC_IRQ_SOURCE_VUPDATE6, -+ -+ DAL_IRQ_SOURCES_NUMBER -+}; -+ -+enum irq_type -+{ -+ IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1, -+ IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1, -+}; -+ -+#define DAL_VALID_IRQ_SRC_NUM(src) \ -+ ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) -+ -+/* Number of Page Flip IRQ Sources. */ -+#define DAL_PFLIP_IRQ_SRC_NUM \ -+ (DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1) -+ -+/* the number of contexts may be expanded in the future based on needs */ -+enum dc_interrupt_context { -+ INTERRUPT_LOW_IRQ_CONTEXT = 0, -+ INTERRUPT_HIGH_IRQ_CONTEXT, -+ INTERRUPT_CONTEXT_NUMBER -+}; -+ -+enum dc_interrupt_porlarity { -+ INTERRUPT_POLARITY_DEFAULT = 0, -+ INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT, -+ INTERRUPT_POLARITY_HIGH, -+ INTERRUPT_POLARITY_BOTH -+}; -+ -+#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \ -+ (int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \ -+ (int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \ -+ (int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid" -+ -+struct dc_timer_interrupt_params { -+ uint64_t micro_sec_interval; -+ enum dc_interrupt_context int_context; -+}; -+ -+struct dc_interrupt_params { -+ /* The polarity *change* which will trigger an interrupt. -+ * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then -+ * 'current_polarity' must be initialised. */ -+ enum dc_interrupt_porlarity requested_polarity; -+ /* If 'requested_polarity == INTERRUPT_POLARITY_BOTH', -+ * 'current_polarity' should contain the current state, which means -+ * the interrupt will be triggered when state changes from what is, -+ * in 'current_polarity'. */ -+ enum dc_interrupt_porlarity current_polarity; -+ enum dc_irq_source irq_source; -+ enum dc_interrupt_context int_context; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h -new file mode 100644 -index 0000000..aa503a8 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h -@@ -0,0 +1,628 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ADAPTER_SERVICE_INTERFACE_H__ -+#define __DAL_ADAPTER_SERVICE_INTERFACE_H__ -+ -+#include "grph_object_ctrl_defs.h" -+#include "gpio_interface.h" -+#include "ddc_interface.h" -+#include "irq_interface.h" -+#include "bios_parser_interface.h" -+#include "adapter_service_types.h" -+#include "dal_types.h" -+#include "asic_capability_types.h" -+ -+/* forward declaration */ -+struct bios_parser; -+struct i2caux; -+struct adapter_service; -+ -+ -+/* -+ * enum adapter_feature_id -+ * -+ * Definition of all adapter features -+ * -+ * The enumeration defines the IDs of all the adapter features. The enum -+ * organizes all the features into several feature sets. The range of feature -+ * set N is from ((N-1)*32+1) to (N*32). Because there may be three value-type -+ * feature, boolean-type, unsigned char-type and unsinged int-type, the number -+ * of features should be 32, 4 and 1 in the feature set accordingly. -+ * -+ * In a boolean-type feature set N, the enumeration value of the feature should -+ * be ((N-1)*32+1), ((N-1)*32+2), ..., (N*32). -+ * -+ * In an unsigned char-type feature set N, the enumeration value of the -+ * feature should be ((N-1)*32+1), ((N-1)*32+8), ((N-1)*32+16) and (N*32). -+ * -+ * In an unsigned int-type feature set N, the enumeration value of the feature -+ * should be ((N-1)*32+1) -+ */ -+enum adapter_feature_id { -+ FEATURE_UNKNOWN = 0, -+ -+ /* Boolean set, up to 32 entries */ -+ FEATURE_ENABLE_HW_EDID_POLLING = 1, -+ FEATURE_SET_01_START = FEATURE_ENABLE_HW_EDID_POLLING, -+ FEATURE_DP_SINK_DETECT_POLL_DATA_PIN, -+ FEATURE_UNDERFLOW_INTERRUPT, -+ FEATURE_ALLOW_WATERMARK_ADJUSTMENT, -+ FEATURE_LIGHT_SLEEP, -+ FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE, -+ FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE, -+ FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE, -+ FEATURE_DETECT_REQUIRE_HPD_HIGH, -+ FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, /* 10th */ -+ FEATURE_MAXIMIZE_URGENCY_WATERMARKS, -+ FEATURE_MAXIMIZE_STUTTER_MARKS, -+ FEATURE_MAXIMIZE_NBP_MARKS, -+ FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, -+ FEATURE_USE_MAX_DISPLAY_CLK, -+ FEATURE_ALLOW_EDP_RESOURCE_SHARING, -+ FEATURE_SUPPORT_DP_YUV, -+ FEATURE_SUPPORT_DP_Y_ONLY, -+ FEATURE_DISABLE_DP_GTC_SYNC, -+ FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, /* 20th */ -+ FEATURE_ENABLE_DFS_BYPASS, -+ FEATURE_LB_HIGH_RESOLUTION, -+ FEATURE_DP_DISPLAY_FORCE_SS_ENABLE, -+ FEATURE_REPORT_CE_MODE_ONLY, -+ FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT, -+ FEATURE_DDC_READ_FORCE_REPEATED_START, -+ FEATURE_FORCE_TIMING_RESYNC, -+ FEATURE_TMDS_DISABLE_DITHERING, -+ FEATURE_HDMI_DISABLE_DITHERING, -+ FEATURE_DP_DISABLE_DITHERING, /* 30th */ -+ FEATURE_EMBEDDED_DISABLE_DITHERING, -+ FEATURE_DISABLE_AZ_CLOCK_GATING, /* 32th. This set is full */ -+ FEATURE_SET_01_END = FEATURE_SET_01_START + 31, -+ -+ /* Boolean set, up to 32 entries */ -+ FEATURE_WIRELESS_ENABLE = FEATURE_SET_01_END + 1, -+ FEATURE_SET_02_START = FEATURE_WIRELESS_ENABLE, -+ FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT, -+ FEATURE_WIRELESS_LIMIT_720P, -+ FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO, -+ FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS, -+ FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, -+ FEATURE_ALLOW_SELF_REFRESH, -+ FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE, -+ FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT, -+ FEATURE_FORCE_PSR, /* 10th */ -+ FEATURE_PREFER_3D_TIMING, -+ FEATURE_VARI_BRIGHT_ENABLE, -+ FEATURE_PSR_ENABLE, -+ FEATURE_EDID_STRESS_READ, -+ FEATURE_DP_FRAME_PACK_STEREO3D, -+ FEATURE_ALLOW_HDMI_WITHOUT_AUDIO, -+ FEATURE_RESTORE_USAGE_I2C_SW_ENGING, -+ FEATURE_ABM_2_0, -+ FEATURE_SUPPORT_MIRABILIS, -+ FEATURE_LOAD_DMCU_FIRMWARE, /* 20th */ -+ FEATURE_ENABLE_GPU_SCALING, -+ FEATURE_DONGLE_SINK_COUNT_CHECK, -+ FEATURE_INSTANT_UP_SCALE_DOWN_SCALE, -+ FEATURE_TILED_DISPLAY, -+ FEATURE_CHANGE_I2C_SPEED_CONTROL, -+ FEATURE_REPORT_SINGLE_SELECTED_TIMING, -+ FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE, -+ FEATURE_SUPPORT_EXTERNAL_PANEL_DRR, -+ FEATURE_SUPPORT_SMOOTH_BRIGHTNESS, -+ FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, /* 30th */ -+ FEATURE_POWER_GATING_LB_PORTION, /* 31nd. One more left. */ -+ FEATURE_SET_02_END = FEATURE_SET_02_START + 31, -+ -+ /* UInt set, 1 entry: DCP Bit Depth Reduction Mode */ -+ FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE = FEATURE_SET_02_END + 1, -+ FEATURE_SET_03_START = FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE, -+ FEATURE_SET_03_END = FEATURE_SET_03_START + 31, -+ -+ /* UInt set, 1 entry: DCP Dither Mode */ -+ FEATURE_DCP_DITHER_MODE = FEATURE_SET_03_END + 1, -+ FEATURE_SET_04_START = FEATURE_DCP_DITHER_MODE, -+ FEATURE_SET_04_END = FEATURE_SET_04_START + 31, -+ -+ /* UInt set, 1 entry: DCP Programming WA(workaround) */ -+ FEATURE_DCP_PROGRAMMING_WA = FEATURE_SET_04_END + 1, -+ FEATURE_SET_06_START = FEATURE_DCP_PROGRAMMING_WA, -+ FEATURE_SET_06_END = FEATURE_SET_06_START + 31, -+ -+ /* UInt set, 1 entry: Maximum co-functional non-DP displays */ -+ FEATURE_MAX_COFUNC_NON_DP_DISPLAYS = FEATURE_SET_06_END + 1, -+ FEATURE_SET_07_START = FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, -+ FEATURE_SET_07_END = FEATURE_SET_07_START + 31, -+ -+ /* UInt set, 1 entry: Number of supported HDMI connection */ -+ FEATURE_SUPPORTED_HDMI_CONNECTION_NUM = FEATURE_SET_07_END + 1, -+ FEATURE_SET_08_START = FEATURE_SUPPORTED_HDMI_CONNECTION_NUM, -+ FEATURE_SET_08_END = FEATURE_SET_08_START + 31, -+ -+ /* UInt set, 1 entry: Maximum number of controllers */ -+ FEATURE_MAX_CONTROLLER_NUM = FEATURE_SET_08_END + 1, -+ FEATURE_SET_09_START = FEATURE_MAX_CONTROLLER_NUM, -+ FEATURE_SET_09_END = FEATURE_SET_09_START + 31, -+ -+ /* UInt set, 1 entry: Type of DRR support */ -+ FEATURE_DRR_SUPPORT = FEATURE_SET_09_END + 1, -+ FEATURE_SET_10_START = FEATURE_DRR_SUPPORT, -+ FEATURE_SET_10_END = FEATURE_SET_10_START + 31, -+ -+ /* UInt set, 1 entry: Stutter mode support */ -+ FEATURE_STUTTER_MODE = FEATURE_SET_10_END + 1, -+ FEATURE_SET_11_START = FEATURE_STUTTER_MODE, -+ FEATURE_SET_11_END = FEATURE_SET_11_START + 31, -+ -+ /* UInt set, 1 entry: Measure PSR setup time */ -+ FEATURE_PSR_SETUP_TIME_TEST = FEATURE_SET_11_END + 1, -+ FEATURE_SET_12_START = FEATURE_PSR_SETUP_TIME_TEST, -+ FEATURE_SET_12_END = FEATURE_SET_12_START + 31, -+ -+ /* Boolean set, up to 32 entries */ -+ FEATURE_POWER_GATING_PIPE_IN_TILE = FEATURE_SET_12_END + 1, -+ FEATURE_SET_13_START = FEATURE_POWER_GATING_PIPE_IN_TILE, -+ FEATURE_USE_PPLIB, -+ FEATURE_DISABLE_LPT_SUPPORT, -+ FEATURE_DUMMY_FBC_BACKEND, -+ FEATURE_DISABLE_FBC_COMP_CLK_GATE, -+ FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL, -+ FEATURE_PIXEL_PERFECT_OUTPUT, -+ FEATURE_8BPP_SUPPORTED, -+ FEATURE_SET_13_END = FEATURE_SET_13_START + 31, -+ -+ /* UInt set, 1 entry: Display preferred view -+ * 0: no preferred view -+ * 1: native and preferred timing of embedded display will have high -+ * priority, so other displays will support it always -+ */ -+ FEATURE_DISPLAY_PREFERRED_VIEW = FEATURE_SET_13_END + 1, -+ FEATURE_SET_15_START = FEATURE_DISPLAY_PREFERRED_VIEW, -+ FEATURE_SET_15_END = FEATURE_SET_15_START + 31, -+ -+ /* UInt set, 1 entry: DAL optimization */ -+ FEATURE_OPTIMIZATION = FEATURE_SET_15_END + 1, -+ FEATURE_SET_16_START = FEATURE_OPTIMIZATION, -+ FEATURE_SET_16_END = FEATURE_SET_16_START + 31, -+ -+ /* UInt set, 1 entry: Performance measurement */ -+ FEATURE_PERF_MEASURE = FEATURE_SET_16_END + 1, -+ FEATURE_SET_17_START = FEATURE_PERF_MEASURE, -+ FEATURE_SET_17_END = FEATURE_SET_17_START + 31, -+ -+ /* UInt set, 1 entry: Minimum backlight value [0-255] */ -+ FEATURE_MIN_BACKLIGHT_LEVEL = FEATURE_SET_17_END + 1, -+ FEATURE_SET_18_START = FEATURE_MIN_BACKLIGHT_LEVEL, -+ FEATURE_SET_18_END = FEATURE_SET_18_START + 31, -+ -+ /* UInt set, 1 entry: Maximum backlight value [0-255] */ -+ FEATURE_MAX_BACKLIGHT_LEVEL = FEATURE_SET_18_END + 1, -+ FEATURE_SET_19_START = FEATURE_MAX_BACKLIGHT_LEVEL, -+ FEATURE_SET_19_END = FEATURE_SET_19_START + 31, -+ -+ /* UInt set, 1 entry: AMB setting -+ * -+ * Each byte will control the ABM configuration to use for a specific -+ * ABM level. -+ * -+ * HW team provided 12 different ABM min/max reduction pairs to choose -+ * between for each ABM level. -+ * -+ * ABM level Byte Setting -+ * 1 0 Default = 0 (setting 3), can be override to 1-12 -+ * 2 1 Default = 0 (setting 7), can be override to 1-12 -+ * 3 2 Default = 0 (setting 8), can be override to 1-12 -+ * 4 3 Default = 0 (setting 10), can be override to 1-12 -+ * -+ * For example, -+ * FEATURE_PREFERRED_ABM_CONFIG_SET = 0x0C060500, this represents: -+ * ABM level 1 use default setting (setting 3) -+ * ABM level 2 uses setting 5 -+ * ABM level 3 uses setting 6 -+ * ABM level 4 uses setting 12 -+ * Internal use only! -+ */ -+ FEATURE_PREFERRED_ABM_CONFIG_SET = FEATURE_SET_19_END + 1, -+ FEATURE_SET_20_START = FEATURE_PREFERRED_ABM_CONFIG_SET, -+ FEATURE_SET_20_END = FEATURE_SET_20_START + 31, -+ -+ /* UInt set, 1 entry: Change SW I2C speed */ -+ FEATURE_CHANGE_SW_I2C_SPEED = FEATURE_SET_20_END + 1, -+ FEATURE_SET_21_START = FEATURE_CHANGE_SW_I2C_SPEED, -+ FEATURE_SET_21_END = FEATURE_SET_21_START + 31, -+ -+ /* UInt set, 1 entry: Change HW I2C speed */ -+ FEATURE_CHANGE_HW_I2C_SPEED = FEATURE_SET_21_END + 1, -+ FEATURE_SET_22_START = FEATURE_CHANGE_HW_I2C_SPEED, -+ FEATURE_SET_22_END = FEATURE_SET_22_START + 31, -+ -+ /* UInt set, 1 entry: -+ * When PSR issue occurs, it is sometimes hard to debug since the -+ * failure occurs immediately at boot. Use this setting to skip or -+ * postpone PSR functionality and re-enable through DSAT. */ -+ FEATURE_DEFAULT_PSR_LEVEL = FEATURE_SET_22_END + 1, -+ FEATURE_SET_23_START = FEATURE_DEFAULT_PSR_LEVEL, -+ FEATURE_SET_23_END = FEATURE_SET_23_START + 31, -+ -+ /* UInt set, 1 entry: Allowed pixel clock range for LVDS */ -+ FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE = FEATURE_SET_23_END + 1, -+ FEATURE_SET_24_START = FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE, -+ FEATURE_SET_24_END = FEATURE_SET_24_START + 31, -+ -+ /* UInt set, 1 entry: Max number of clock sources */ -+ FEATURE_MAX_CLOCK_SOURCE_NUM = FEATURE_SET_24_END + 1, -+ FEATURE_SET_25_START = FEATURE_MAX_CLOCK_SOURCE_NUM, -+ FEATURE_SET_25_END = FEATURE_SET_25_START + 31, -+ -+ /* UInt set, 1 entry: Select the ABM configuration to use. -+ * -+ * This feature set is used to allow packaging option to be defined -+ * to allow OEM to select between the default ABM configuration or -+ * alternative predefined configurations that may be more aggressive. -+ * -+ * Note that this regkey is meant for external use to select the -+ * configuration OEM wants. Whereas the other PREFERRED_ABM_CONFIG_SET -+ * key is only used for internal use and allows full reconfiguration. -+ */ -+ FEATURE_ABM_CONFIG = FEATURE_SET_25_END + 1, -+ FEATURE_SET_26_START = FEATURE_ABM_CONFIG, -+ FEATURE_SET_26_END = FEATURE_SET_26_START + 31, -+ -+ /* UInt set, 1 entry: Select the default speed in which smooth -+ * brightness feature should converge towards target backlight level. -+ * -+ * For example, a setting of 500 means it takes 500ms to transition -+ * from current backlight level to the new requested backlight level. -+ */ -+ FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS = FEATURE_SET_26_END + 1, -+ FEATURE_SET_27_START = FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS, -+ FEATURE_SET_27_END = FEATURE_SET_27_START + 31, -+ -+ /* Set 28: UInt set, 1 entry: Allow runtime parameter to force specific -+ * Static Screen Event triggers for test purposes. */ -+ FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS = FEATURE_SET_27_END + 1, -+ FEATURE_SET_28_START = FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS, -+ FEATURE_SET_28_END = FEATURE_SET_28_START + 31, -+ -+ FEATURE_MAXIMUM -+}; -+ -+/* Adapter Service type of DRR support*/ -+enum as_drr_support { -+ AS_DRR_SUPPORT_DISABLED = 0x0, -+ AS_DRR_SUPPORT_ENABLED = 0x1, -+ AS_DRR_SUPPORT_MIN_FORCED_FPS = 0xA -+}; -+ -+/* Adapter service initialize data structure*/ -+struct as_init_data { -+ struct hw_asic_id hw_init_data; -+ struct bp_init_data bp_init_data; -+ struct dc_context *ctx; -+ struct bdf_info bdf_info; -+ const struct dal_override_parameters *display_param; -+}; -+ -+/* Create adapter service */ -+struct adapter_service *dal_adapter_service_create( -+ struct as_init_data *init_data); -+ -+/* Destroy adapter service and objects it contains */ -+void dal_adapter_service_destroy( -+ struct adapter_service **as); -+ -+/* Get the DCE version of current ASIC */ -+enum dce_version dal_adapter_service_get_dce_version( -+ const struct adapter_service *as); -+ -+/* Get firmware information from BIOS */ -+bool dal_adapter_service_get_firmware_info( -+ struct adapter_service *as, -+ struct firmware_info *info); -+ -+ -+/* functions to get a total number of objects of specific type */ -+uint8_t dal_adapter_service_get_connectors_num( -+ struct adapter_service *as); -+ -+/* Get number of controllers */ -+uint8_t dal_adapter_service_get_controllers_num( -+ struct adapter_service *as); -+ -+/* Get number of clock sources */ -+uint8_t dal_adapter_service_get_clock_sources_num( -+ struct adapter_service *as); -+ -+/* Get number of controllers */ -+uint8_t dal_adapter_service_get_func_controllers_num( -+ struct adapter_service *as); -+ -+/* Get number of stream engines */ -+uint8_t dal_adapter_service_get_stream_engines_num( -+ struct adapter_service *as); -+ -+/* functions to get object id based on object index */ -+struct graphics_object_id dal_adapter_service_get_connector_obj_id( -+ struct adapter_service *as, -+ uint8_t connector_index); -+ -+/* Get number of spread spectrum entries from BIOS */ -+uint32_t dal_adapter_service_get_ss_info_num( -+ struct adapter_service *as, -+ enum as_signal_type signal); -+ -+/* Get spread spectrum info from BIOS */ -+bool dal_adapter_service_get_ss_info( -+ struct adapter_service *as, -+ enum as_signal_type signal, -+ uint32_t idx, -+ struct spread_spectrum_info *info); -+ -+/* Check if DFS bypass is enabled */ -+bool dal_adapter_service_is_dfs_bypass_enabled(struct adapter_service *as); -+ -+/* Get memory controller latency */ -+uint32_t dal_adapter_service_get_mc_latency( -+ struct adapter_service *as); -+ -+/* Get the video RAM bit width set on the ASIC */ -+uint32_t dal_adapter_service_get_asic_vram_bit_width( -+ struct adapter_service *as); -+ -+/* Get the bug flags set on this ASIC */ -+struct asic_bugs dal_adapter_service_get_asic_bugs( -+ struct adapter_service *as); -+ -+/* Get efficiency of DRAM */ -+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency( -+ struct adapter_service *as); -+ -+/* Get multiplier for the memory type */ -+uint32_t dal_adapter_service_get_memory_type_multiplier( -+ struct adapter_service *as); -+ -+/* Get parameters for bandwidth tuning */ -+bool dal_adapter_service_get_bandwidth_tuning_params( -+ struct adapter_service *as, -+ union bandwidth_tuning_params *params); -+ -+/* Get integrated information on BIOS */ -+bool dal_adapter_service_get_integrated_info( -+ struct adapter_service *as, -+ struct integrated_info *info); -+ -+/* Return if a given feature is supported by the ASIC */ -+bool dal_adapter_service_is_feature_supported( -+ enum adapter_feature_id feature_id); -+ -+/* Get the cached value of a given feature */ -+bool dal_adapter_service_get_feature_value( -+ const enum adapter_feature_id feature_id, -+ void *data, -+ uint32_t size); -+ -+/* Get a copy of ASIC feature flags */ -+struct asic_feature_flags dal_adapter_service_get_feature_flags( -+ struct adapter_service *as); -+ -+/* Obtain DDC */ -+struct ddc *dal_adapter_service_obtain_ddc( -+ struct adapter_service *as, -+ struct graphics_object_id id); -+ -+/* Release DDC */ -+void dal_adapter_service_release_ddc( -+ struct adapter_service *as, -+ struct ddc *ddc); -+ -+/* Obtain HPD interrupt request */ -+struct irq *dal_adapter_service_obtain_hpd_irq( -+ struct adapter_service *as, -+ struct graphics_object_id id); -+ -+/* Release interrupt request */ -+void dal_adapter_service_release_irq( -+ struct adapter_service *as, -+ struct irq *irq); -+ -+/* Obtain GPIO */ -+struct gpio *dal_adapter_service_obtain_gpio( -+ struct adapter_service *as, -+ enum gpio_id id, -+ uint32_t en); -+ -+/* Obtain GPIO for stereo3D*/ -+struct gpio *dal_adapter_service_obtain_stereo_gpio(struct adapter_service *as); -+ -+/* Release GPIO */ -+void dal_adapter_service_release_gpio( -+ struct adapter_service *as, -+ struct gpio *gpio); -+ -+/* Get SW I2C speed */ -+uint32_t dal_adapter_service_get_sw_i2c_speed(struct adapter_service *as); -+ -+/* Get HW I2C speed */ -+uint32_t dal_adapter_service_get_hw_i2c_speed(struct adapter_service *as); -+ -+/* Get line buffer size */ -+uint32_t dal_adapter_service_get_line_buffer_size(struct adapter_service *as); -+ -+/* Get information on audio support */ -+union audio_support dal_adapter_service_get_audio_support( -+ struct adapter_service *as); -+ -+/* Get I2C information from BIOS */ -+bool dal_adapter_service_get_i2c_info( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ struct graphics_object_i2c_info *i2c_info); -+ -+/* Get bios parser handler */ -+struct bios_parser *dal_adapter_service_get_bios_parser( -+ struct adapter_service *as); -+ -+/* Get i2c aux handler */ -+struct i2caux *dal_adapter_service_get_i2caux( -+ struct adapter_service *as); -+ -+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags( -+ struct adapter_service *as); -+ -+bool dal_adapter_service_initialize_hw_data( -+ struct adapter_service *as); -+ -+struct graphics_object_id dal_adapter_service_enum_fake_path_resource( -+ struct adapter_service *as, -+ uint32_t index); -+ -+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object( -+ struct adapter_service *as, -+ uint32_t index); -+ -+struct graphics_object_id dal_adapter_service_enum_sync_output_object( -+ struct adapter_service *as, -+ uint32_t index); -+ -+struct graphics_object_id dal_adapter_service_enum_audio_object( -+ struct adapter_service *as, -+ uint32_t index); -+ -+void dal_adapter_service_update_audio_connectivity( -+ struct adapter_service *as, -+ uint32_t number_of_audio_capable_display_path); -+ -+bool dal_adapter_service_has_embedded_display_connector( -+ struct adapter_service *as); -+ -+bool dal_adapter_service_get_embedded_panel_info( -+ struct adapter_service *as, -+ struct embedded_panel_info *info); -+ -+bool dal_adapter_service_enum_embedded_panel_patch_mode( -+ struct adapter_service *as, -+ uint32_t index, -+ struct embedded_panel_patch_mode *mode); -+ -+bool dal_adapter_service_get_faked_edid_len( -+ struct adapter_service *as, -+ uint32_t *len); -+ -+bool dal_adapter_service_get_faked_edid_buf( -+ struct adapter_service *as, -+ uint8_t *buf, -+ uint32_t len); -+ -+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void); -+ -+uint32_t dal_adapter_service_get_single_selected_timing_signals(void); -+ -+bool dal_adapter_service_get_device_tag( -+ struct adapter_service *as, -+ struct graphics_object_id connector_object_id, -+ uint32_t device_tag_index, -+ struct connector_device_tag_info *info); -+ -+bool dal_adapter_service_is_device_id_supported( -+ struct adapter_service *as, -+ struct device_id id); -+ -+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as); -+ -+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as); -+ -+uint32_t dal_adapter_service_get_src_num( -+ struct adapter_service *as, -+ struct graphics_object_id id); -+ -+struct graphics_object_id dal_adapter_service_get_src_obj( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ uint32_t index); -+ -+/* Is this Fusion ASIC */ -+bool dal_adapter_service_is_fusion(struct adapter_service *as); -+ -+/* Is this ASIC support dynamic DFSbypass switch */ -+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as); -+ -+/* Reports whether driver settings allow requested optimization */ -+bool dal_adapter_service_should_optimize( -+ struct adapter_service *as, enum optimization_feature feature); -+ -+/* Determine if driver is in accelerated mode */ -+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as); -+ -+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info( -+ struct adapter_service *as, -+ struct graphics_object_i2c_info *info); -+ -+struct bdf_info dal_adapter_service_get_adapter_info( -+ struct adapter_service *as); -+ -+ -+/* Determine if this ASIC needs to wait on PLL lock bit */ -+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock( -+ struct adapter_service *as); -+ -+#define SIZEOF_BACKLIGHT_LUT 101 -+#define ABSOLUTE_BACKLIGHT_MAX 255 -+#define DEFAULT_MIN_BACKLIGHT 12 -+#define DEFAULT_MAX_BACKLIGHT 255 -+#define BACKLIGHT_CURVE_COEFFB 100 -+#define BACKLIGHT_CURVE_COEFFA_FACTOR 10000 -+#define BACKLIGHT_CURVE_COEFFB_FACTOR 100 -+ -+struct panel_backlight_levels { -+ uint32_t ac_level_percentage; -+ uint32_t dc_level_percentage; -+}; -+ -+bool dal_adapter_service_is_lid_open(struct adapter_service *as); -+ -+bool dal_adapter_service_get_panel_backlight_default_levels( -+ struct adapter_service *as, -+ struct panel_backlight_levels *levels); -+ -+bool dal_adapter_service_get_panel_backlight_boundaries( -+ struct adapter_service *as, -+ struct panel_backlight_boundaries *boundaries); -+ -+uint32_t dal_adapter_service_get_view_port_pixel_granularity( -+ struct adapter_service *as); -+ -+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector( -+ struct adapter_service *as); -+ -+uint32_t dal_adapter_service_get_num_of_underlays( -+ struct adapter_service *as); -+ -+bool dal_adapter_service_get_encoder_cap_info( -+ struct adapter_service *as, -+ struct graphics_object_id id, -+ struct graphics_object_encoder_cap_info *info); -+ -+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as); -+ -+#endif /* __DAL_ADAPTER_SERVICE_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_types.h b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h -new file mode 100644 -index 0000000..fb47ef3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h -@@ -0,0 +1,70 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ADAPTER_SERVICE_TYPES_H__ -+#define __DAL_ADAPTER_SERVICE_TYPES_H__ -+ -+enum as_signal_type { -+ AS_SIGNAL_TYPE_NONE = 0L, /* no signal */ -+ AS_SIGNAL_TYPE_DVI, -+ AS_SIGNAL_TYPE_HDMI, -+ AS_SIGNAL_TYPE_LVDS, -+ AS_SIGNAL_TYPE_DISPLAY_PORT, -+ AS_SIGNAL_TYPE_GPU_PLL, -+ AS_SIGNAL_TYPE_UNKNOWN -+}; -+ -+/* -+ * Struct used for algorithm of Bandwidth tuning parameters -+ * the sequence of the fields is binded with runtime parameter. -+ */ -+union bandwidth_tuning_params { -+ struct bandwidth_tuning_params_struct { -+ uint32_t read_delay_stutter_off_usec; -+ uint32_t ignore_hblank_time;/*bool*/ -+ uint32_t extra_reordering_latency_usec; -+ uint32_t extra_mc_latency_usec; -+ uint32_t data_return_bandwidth_eff;/*in %*/ -+ uint32_t dmif_request_bandwidth_eff;/*in %*/ -+ uint32_t sclock_latency_multiplier;/*in unit of 0.01*/ -+ uint32_t mclock_latency_multiplier;/*in unit of 0.01*/ -+ uint32_t fix_latency_multiplier;/*in unit of 0.01*/ -+ /*in unit represent in watermark*/ -+ uint32_t use_urgency_watermark_offset; -+ } tuning_info; -+ uint32_t arr_info[sizeof(struct bandwidth_tuning_params_struct) -+ / sizeof(uint32_t)]; -+}; -+ -+union audio_support { -+ struct { -+ uint32_t DP_AUDIO:1; -+ uint32_t HDMI_AUDIO_ON_DONGLE:1; -+ uint32_t HDMI_AUDIO_NATIVE:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/adjustment_interface.h b/drivers/gpu/drm/amd/dal/include/adjustment_interface.h -new file mode 100644 -index 0000000..64a9f9f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/adjustment_interface.h -@@ -0,0 +1,230 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ADJUSTMENT_INTERFACE_H__ -+#define __DAL_ADJUSTMENT_INTERFACE_H__ -+ -+#include "include/display_service_types.h" -+#include "include/adjustment_types.h" -+#include "include/overlay_types.h" -+#include "include/display_path_interface.h" -+ -+struct ds_underscan_desc; -+struct adj_container; -+struct info_frame; -+struct ds_dispatch; -+struct hw_adjustment_set; -+struct path_mode; -+struct hw_path_mode; -+ -+enum build_path_set_reason; -+ -+bool dal_ds_dispatch_is_adjustment_supported( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id); -+ -+enum ds_return dal_ds_dispatch_get_type( -+ struct ds_dispatch *adj, -+ enum adjustment_id adjust_id, -+ enum adjustment_data_type *type); -+ -+enum ds_return dal_ds_dispatch_get_property( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ enum adjustment_id adjust_id, -+ union adjustment_property *property); -+ -+enum ds_return dal_ds_dispatch_set_adjustment( -+ struct ds_dispatch *ds, -+ const uint32_t display_index, -+ enum adjustment_id adjust_id, -+ int32_t value); -+ -+enum ds_return dal_ds_dispatch_get_adjustment_current_value( -+ struct ds_dispatch *ds, -+ struct adj_container *container, -+ struct adjustment_info *info, -+ enum adjustment_id id, -+ bool fall_back_to_default); -+ -+enum ds_return dal_ds_dispatch_get_adjustment_value( -+ struct ds_dispatch *ds, -+ struct display_path *disp_path, -+ enum adjustment_id adj_id, -+ bool fall_back_to_default, -+ int32_t *value); -+ -+const struct raw_gamma_ramp *dal_ds_dispatch_get_current_gamma( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id); -+ -+const struct raw_gamma_ramp *dal_ds_dispatch_get_default_gamma( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id); -+ -+enum ds_return dal_ds_dispatch_set_current_gamma( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id, -+ const struct raw_gamma_ramp *gamma); -+ -+enum ds_return dal_ds_dispatch_set_gamma( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id, -+ const struct raw_gamma_ramp *gamma); -+ -+bool dal_ds_dispatch_get_underscan_info( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ struct ds_underscan_info *info); -+ -+bool dal_ds_dispatch_get_underscan_mode( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ struct ds_underscan_desc *desc); -+ -+bool dal_ds_dispatch_set_underscan_mode( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ struct ds_underscan_desc *desc); -+ -+bool dal_ds_dispatch_setup_overlay( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ struct overlay_data *data); -+ -+struct adj_container *dal_ds_dispatch_get_adj_container_for_path( -+ const struct ds_dispatch *ds, -+ uint32_t display_index); -+ -+void dal_ds_dispatch_set_applicable_adj( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ const struct adj_container *applicable); -+ -+enum ds_return dal_ds_dispatch_set_color_gamut( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ const struct ds_set_gamut_data *data); -+ -+enum ds_return dal_ds_dispatch_get_color_gamut( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ const struct ds_gamut_reference_data *ref, -+ struct ds_get_gamut_data *data); -+ -+enum ds_return dal_ds_dispatch_get_color_gamut_info( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ const struct ds_gamut_reference_data *ref, -+ struct ds_gamut_info *data); -+ -+enum ds_return dal_ds_dispatch_get_regamma_lut( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ struct ds_regamma_lut *data); -+ -+enum ds_return dal_ds_dispatch_set_regamma_lut( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ struct ds_regamma_lut *data); -+ -+enum ds_return dal_ds_dispatch_set_info_packets( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ const struct info_frame *info_frames); -+ -+enum ds_return dal_ds_dispatch_get_info_packets( -+ struct ds_dispatch *adj, -+ uint32_t display_index, -+ struct info_frame *info_frames); -+ -+bool dal_ds_dispatch_initialize_adjustment(struct ds_dispatch *ds); -+ -+void dal_ds_dispatch_cleanup_adjustment(struct ds_dispatch *ds); -+ -+bool dal_ds_dispatch_build_post_set_mode_adj( -+ struct ds_dispatch *ds, -+ const struct path_mode *mode, -+ struct display_path *display_path, -+ struct hw_adjustment_set *set); -+ -+bool dal_ds_dispatch_build_color_control_adj( -+ struct ds_dispatch *ds, -+ const struct path_mode *mode, -+ struct display_path *display_path, -+ struct hw_adjustment_set *set); -+ -+bool dal_ds_dispatch_build_include_adj( -+ struct ds_dispatch *ds, -+ const struct path_mode *mode, -+ struct display_path *display_path, -+ struct hw_path_mode *hw_mode, -+ struct hw_adjustment_set *set); -+ -+bool dal_ds_dispatch_apply_scaling( -+ struct ds_dispatch *ds, -+ const struct path_mode *mode, -+ struct adj_container *adj_container, -+ enum build_path_set_reason reason, -+ struct hw_path_mode *hw_mode); -+ -+void dal_ds_dispatch_update_adj_container_for_path_with_mode_info( -+ struct ds_dispatch *ds, -+ struct display_path *display_path, -+ const struct path_mode *path_mode); -+ -+enum ds_return dal_ds_dispatch_get_adjustment_info( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id adjust_id, -+ struct adjustment_info *adj_info); -+ -+bool dal_ds_dispatch_include_adjustment( -+ struct ds_dispatch *ds, -+ struct display_path *disp_path, -+ struct ds_adj_id_value adj, -+ struct hw_adjustment_set *set); -+ -+enum ds_return dal_ds_dispatch_set_gamma_adjustment( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum adjustment_id ad_id, -+ const struct raw_gamma_ramp *gamma); -+ -+void dal_ds_dispatch_update_adj_container_for_path_with_color_space( -+ struct ds_dispatch *ds, -+ uint32_t display_index, -+ enum ds_color_space color_space); -+ -+void dal_ds_dispatch_setup_default_regamma( -+ struct ds_dispatch *ds, -+ struct ds_regamma_lut *regamma); -+ -+#endif /* __DAL_ADJUSTMENT_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/adjustment_types.h b/drivers/gpu/drm/amd/dal/include/adjustment_types.h -new file mode 100644 -index 0000000..f6c0d61 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/adjustment_types.h -@@ -0,0 +1,420 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ADJUSTMENT_TYPES_H__ -+#define __DAL_ADJUSTMENT_TYPES_H__ -+ -+#include "dal_services.h" -+ -+/* make sure to update this when updating adj_global_info_array */ -+#define CURRENT_ADJUSTMENT_NUM 12 -+#define MAX_ADJUSTMENT_NUM (ADJ_ID_END - ADJ_ID_BEGIN) -+#define REGAMMA_VALUE 256 -+#define REGAMMA_RANGE (REGAMMA_VALUE*3) -+#define ADJUST_DIVIDER 100 -+#define GAMUT_DIVIDER 10000 -+ -+ -+enum adjustment_id { -+ -+ /*this useful type when i need to indicate unknown adjustment and code -+ look if not the specific type*/ -+ ADJ_ID_INVALID, -+ -+ ADJ_ID_CONTRAST, -+ ADJ_ID_BRIGHTNESS, -+ ADJ_ID_HUE, -+ ADJ_ID_SATURATION, -+ ADJ_ID_GAMMA_RAMP, -+ ADJ_ID_GAMMA_RAMP_REGAMMA_UPDATE, -+ ADJ_ID_TEMPERATURE, -+ ADJ_ID_NOMINAL_RANGE_RGB_LIMITED, -+ -+ ADJ_ID_LP_FILTER_DEFLICKER, -+ ADJ_ID_HP_FILTER_DEFLICKER, -+ ADJ_ID_SHARPNESS_GAIN, /*0 - 10*/ -+ -+ ADJ_ID_REDUCED_BLANKING, -+ ADJ_ID_COHERENT, -+ ADJ_ID_MULTIMEDIA_PASS_THROUGH, -+ -+ ADJ_ID_VERTICAL_POSITION, -+ ADJ_ID_HORIZONTA_LPOSITION, -+ ADJ_ID_VERTICAL_SIZE, -+ ADJ_ID_HORIZONTAL_SIZE, -+ ADJ_ID_VERTICAL_SYNC, -+ ADJ_ID_HORIZONTAL_SYNC, -+ ADJ_ID_OVERSCAN, -+ ADJ_ID_COMPOSITE_SYNC, -+ -+ ADJ_ID_BIT_DEPTH_REDUCTION,/*CWDDEDI_DISPLAY_ADJINFOTYPE_BITVECTOR*/ -+ ADJ_ID_UNDERSCAN,/*CWDDEDI_DISPLAY_ADJINFOTYPE_RANGE*/ -+ ADJ_ID_UNDERSCAN_TYPE,/*CWDDEDI_DISPLAY_ADJINFOTYPE_RANGE*/ -+ ADJ_ID_TEMPERATURE_SOURCE,/*CWDDEDI_DISPLAY_ADJINFOTYPE_BITVECTOR*/ -+ -+ ADJ_ID_OVERLAY_BRIGHTNESS, -+ ADJ_ID_OVERLAY_CONTRAST, -+ ADJ_ID_OVERLAY_SATURATION, -+ ADJ_ID_OVERLAY_HUE, -+ ADJ_ID_OVERLAY_GAMMA, -+ ADJ_ID_OVERLAY_ALPHA, -+ ADJ_ID_OVERLAY_ALPHA_PER_PIX, -+ ADJ_ID_OVERLAY_INV_GAMMA, -+ ADJ_ID_OVERLAY_TEMPERATURE,/*done ,but code is commented*/ -+ ADJ_ID_OVERLAY_NOMINAL_RANGE_RGB_LIMITED, -+ -+ -+ ADJ_ID_UNDERSCAN_TV_INTERNAL,/*internal usage only for HDMI*/ -+ /*custom TV modes*/ -+ ADJ_ID_DRIVER_REQUESTED_GAMMA,/*used to get current gamma*/ -+ ADJ_ID_GAMUT_SOURCE_GRPH,/*logical adjustment visible for DS and CDB*/ -+ ADJ_ID_GAMUT_SOURCE_OVL,/*logical adjustment visible for DS and CDB*/ -+ ADJ_ID_GAMUT_DESTINATION,/*logical adjustment visible for DS and CDB*/ -+ ADJ_ID_REGAMMA,/*logical adjustment visible for DS and CDB*/ -+ ADJ_ID_ITC_ENABLE,/*ITC flag enable by default*/ -+ ADJ_ID_CNC_CONTENT,/*display image content*/ -+ /*internal adjustment, in order to provide backward compatibility -+ gamut with color temperature*/ -+ -+ /* Backlight Adjustment Group*/ -+ ADJ_ID_BACKLIGHT, -+ ADJ_ID_BACKLIGHT_OPTIMIZATION, -+ -+ /* flag the first and last*/ -+ ADJ_ID_BEGIN = ADJ_ID_CONTRAST, -+ ADJ_ID_END = ADJ_ID_BACKLIGHT_OPTIMIZATION, -+}; -+ -+enum adjustment_data_type { -+ ADJ_RANGED, -+ ADJ_BITVECTOR, -+ ADJ_LUT /* not handled currently */ -+}; -+ -+union adjustment_property { -+ uint32_t u32all; -+ struct { -+ /*per mode adjustment*/ -+ uint32_t SAVED_WITHMODE:1; -+ /*per edid adjustment*/ -+ uint32_t SAVED_WITHEDID:1; -+ /*adjustment not visible to HWSS*/ -+ uint32_t CALCULATE:1; -+ /*explisit adjustment applied by HWSS*/ -+ uint32_t INC_IN_SET_MODE:1; -+ /*adjustment requires set mode to be applied*/ -+ uint32_t SETMODE_REQ:1; -+ /*adjustment is applied at the end of set mode*/ -+ uint32_t POST_SET:1; -+/*when adjustment is applied its value should be stored -+in place and not wait for flush call*/ -+ uint32_t SAVE_IN_PLACE:1; -+ /*adjustment is always apply*/ -+ uint32_t FORCE_SET:1; -+ /*this adjustment is specific to individual display path.*/ -+ uint32_t SAVED_WITH_DISPLAY_IDX:1; -+ uint32_t RESERVED_23:23; -+ } bits; -+}; -+ -+enum adjustment_state { -+ ADJUSTMENT_STATE_INVALID, -+ ADJUSTMENT_STATE_VALID, -+ ADJUSTMENT_STATE_REQUESTED, -+ ADJUSTMENT_STATE_COMMITTED_TO_HW, -+}; -+ -+/* AdjustmentInfo structure - it keeps either ranged data or discrete*/ -+struct adjustment_info { -+ enum adjustment_data_type adj_data_type; -+ union adjustment_property adj_prop; -+ enum adjustment_state adj_state; -+ enum adjustment_id adj_id; -+ -+ union data { -+ struct ranged { -+ int32_t min; -+ int32_t max; -+ int32_t def; -+ int32_t step; -+ int32_t cur; -+ } ranged; -+ struct bit_vector { -+ int32_t system_supported; -+ int32_t current_supported; -+ int32_t default_val; -+ } bit_vector; -+ } adj_data; -+}; -+ -+/* adjustment category -+this should be a MASK struct with the bitfileds!!! -+since it could be crt and cv and dfp!!! -+the only fit is for overlay!!!*/ -+enum adjustment_category { -+ CAT_ALL, -+ CAT_CRT, -+ CAT_DFP, -+ CAT_LCD, -+ CAT_OVERLAY, -+ CAT_INVALID -+}; -+ -+enum raw_gamma_ramp_type { -+ GAMMA_RAMP_TYPE_UNINITIALIZED, -+ GAMMA_RAMP_TYPE_DEFAULT, -+ GAMMA_RAMP_TYPE_RGB256, -+ GAMMA_RAMP_TYPE_FIXED_POINT -+}; -+ -+struct raw_gamma_ramp_rgb { -+ uint32_t red; -+ uint32_t green; -+ uint32_t blue; -+}; -+ -+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 -+struct raw_gamma_ramp { -+ enum raw_gamma_ramp_type type; -+ struct raw_gamma_ramp_rgb rgb_256[NUM_OF_RAW_GAMMA_RAMP_RGB_256]; -+ uint32_t size; -+}; -+ -+struct ds_underscan_info { -+ uint32_t default_width; -+ uint32_t default_height; -+ uint32_t max_width; -+ uint32_t max_height; -+ uint32_t min_width; -+ uint32_t min_height; -+ uint32_t h_step; -+ uint32_t v_step; -+ uint32_t default_x_pos; -+ uint32_t default_y_pos; -+}; -+ -+struct ds_overscan { -+ uint32_t left; -+ uint32_t right; -+ uint32_t top; -+ uint32_t bottom; -+}; -+ -+enum ds_color_space { -+ DS_COLOR_SPACE_UNKNOWN = 0, -+ DS_COLOR_SPACE_SRGB_FULLRANGE = 1, -+ DS_COLOR_SPACE_SRGB_LIMITEDRANGE, -+ DS_COLOR_SPACE_YPBPR601, -+ DS_COLOR_SPACE_YPBPR709, -+ DS_COLOR_SPACE_YCBCR601, -+ DS_COLOR_SPACE_YCBCR709, -+ DS_COLOR_SPACE_NMVPU_SUPERAA, -+ DS_COLOR_SPACE_YCBCR601_YONLY, -+ DS_COLOR_SPACE_YCBCR709_YONLY/*same as YCbCr, but Y in Full range*/ -+}; -+ -+enum ds_underscan_options { -+ DS_UNDERSCAN_OPTION_DEFAULT = 0, -+ DS_UNDERSCAN_OPTION_USECEA861D -+}; -+ -+enum dpms_state { -+ DPMS_NONE = 0, -+ DPMS_ON, -+ DPMS_OFF, -+}; -+ -+enum ds_gamut_reference { -+ DS_GAMUT_REFERENCE_DESTINATION = 0, -+ DS_GAMUT_REFERENCE_SOURCE, -+}; -+ -+enum ds_gamut_content { -+ DS_GAMUT_CONTENT_GRAPHICS = 0, -+ DS_GAMUT_CONTENT_VIDEO, -+}; -+ -+struct ds_gamut_reference_data { -+ enum ds_gamut_reference gamut_ref; -+ enum ds_gamut_content gamut_content; -+}; -+ -+union ds_custom_gamut_type { -+ uint32_t u32all; -+ struct { -+ uint32_t CUSTOM_WHITE_POINT:1; -+ uint32_t CUSTOM_GAMUT_SPACE:1; -+ uint32_t reserved:30; -+ } bits; -+}; -+ -+union ds_gamut_spaces { -+ uint32_t u32all; -+ struct { -+ uint32_t GAMUT_SPACE_CCIR709:1; -+ uint32_t GAMUT_SPACE_CCIR601:1; -+ uint32_t GAMUT_SPACE_ADOBERGB:1; -+ uint32_t GAMUT_SPACE_CIERGB:1; -+ uint32_t GAMUT_SPACE_CUSTOM:1; -+ uint32_t reserved:27; -+ } bits; -+}; -+ -+union ds_gamut_white_point { -+ uint32_t u32all; -+ struct { -+ uint32_t GAMUT_WHITE_POINT_5000:1; -+ uint32_t GAMUT_WHITE_POINT_6500:1; -+ uint32_t GAMUT_WHITE_POINT_7500:1; -+ uint32_t GAMUT_WHITE_POINT_9300:1; -+ uint32_t GAMUT_WHITE_POINT_CUSTOM:1; -+ uint32_t reserved:27; -+ } bits; -+}; -+ -+struct ds_gamut_space_coordinates { -+ int32_t red_x; -+ int32_t red_y; -+ int32_t green_x; -+ int32_t green_y; -+ int32_t blue_x; -+ int32_t blue_y; -+ -+}; -+ -+struct ds_white_point_coordinates { -+ int32_t white_x; -+ int32_t white_y; -+}; -+ -+struct ds_gamut_data { -+ union ds_custom_gamut_type feature; -+ union { -+ uint32_t predefined; -+ struct ds_white_point_coordinates custom; -+ -+ } white_point; -+ -+ union { -+ uint32_t predefined; -+ struct ds_gamut_space_coordinates custom; -+ -+ } gamut; -+}; -+ -+struct ds_set_gamut_data { -+ struct ds_gamut_reference_data ref; -+ struct ds_gamut_data gamut; -+ -+}; -+ -+struct ds_get_gamut_data { -+ struct ds_gamut_data gamut; -+}; -+ -+struct ds_gamut_info { -+/*mask of supported predefined gamuts ,started from DI_GAMUT_SPACE_CCIR709 ...*/ -+ union ds_gamut_spaces gamut_space; -+/*mask of supported predefined white points,started from DI_WHITE_POINT_5000K */ -+ union ds_gamut_white_point white_point; -+ -+}; -+ -+union ds_regamma_flags { -+ uint32_t u32all; -+ struct { -+ /*custom/user gamam array is in use*/ -+ uint32_t GAMMA_RAMP_ARRAY:1; -+ /*gamma from edid is in use*/ -+ uint32_t GAMMA_FROM_EDID:1; -+ /*gamma from edid is in use , but only for Display Id 1.2*/ -+ uint32_t GAMMA_FROM_EDID_EX:1; -+ /*user custom gamma is in use*/ -+ uint32_t GAMMA_FROM_USER:1; -+ /*coeff. A0-A3 from user is in use*/ -+ uint32_t COEFF_FROM_USER:1; -+ /*coeff. A0-A3 from edid is in use only for Display Id 1.2*/ -+ uint32_t COEFF_FROM_EDID:1; -+ /*which ROM to choose for graphics*/ -+ uint32_t GRAPHICS_DEGAMMA_SRGB:1; -+ /*which ROM to choose for video overlay*/ -+ uint32_t OVERLAY_DEGAMMA_SRGB:1; -+ /*apply degamma removal in driver*/ -+ uint32_t APPLY_DEGAMMA:1; -+ -+ uint32_t reserved:23; -+ } bits; -+}; -+ -+struct ds_regamma_ramp { -+ uint16_t gamma[256 * 3]; /* gamma ramp packed as RGB */ -+ -+}; -+ -+struct ds_regamma_coefficients_ex { -+ int32_t gamma[3];/*2400 use divider 1 000*/ -+ int32_t coeff_a0[3];/*31308 divider 10 000 000,0-red, 1-green, 2-blue*/ -+ int32_t coeff_a1[3];/*12920 use divider 1 000*/ -+ int32_t coeff_a2[3];/*55 use divider 1 000*/ -+ int32_t coeff_a3[3];/*55 use divider 1 000*/ -+}; -+ -+struct ds_regamma_lut { -+ union ds_regamma_flags flags; -+ union { -+ struct ds_regamma_ramp gamma; -+ struct ds_regamma_coefficients_ex coeff; -+ }; -+}; -+ -+enum ds_backlight_optimization { -+ DS_BACKLIGHT_OPTIMIZATION_DISABLE = 0, -+ DS_BACKLIGHT_OPTIMIZATION_DESKTOP, -+ DS_BACKLIGHT_OPTIMIZATION_DYNAMIC, -+ DS_BACKLIGHT_OPTIMIZATION_DIMMED -+}; -+ -+struct ds_adj_id_value { -+ enum adjustment_id adj_id; -+ enum adjustment_data_type adj_type; -+ union adjustment_property adj_prop; -+ int32_t value; -+}; -+ -+struct gamut_data { -+ union ds_custom_gamut_type option; -+ union { -+ union ds_gamut_white_point predefined; -+ struct ds_white_point_coordinates custom; -+ -+ } white_point; -+ -+ union { -+ union ds_gamut_spaces predefined; -+ struct ds_gamut_space_coordinates custom; -+ -+ } gamut; -+}; -+#endif /* __DAL_ADJUSTMENT_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h -new file mode 100644 -index 0000000..bdeaaf9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h -@@ -0,0 +1,58 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of enc software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and enc permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__ -+#define __DAL_ASIC_CAPABILITY_INTERFACE_H__ -+ -+/* Include */ -+#include "include/asic_capability_types.h" -+ -+/* Forward declaration */ -+struct hw_asic_id; -+ -+ -+/* ASIC capability */ -+struct asic_capability { -+ struct dc_context *ctx; -+ struct asic_caps caps; -+ struct asic_stereo_3d_caps stereo_3d_caps; -+ struct asic_bugs bugs; -+ struct dal_asic_runtime_flags runtime_flags; -+ uint32_t data[ASIC_DATA_MAX_NUMBER]; -+}; -+ -+ -+/** -+ * Interfaces -+ */ -+ -+/* Create and initialize ASIC capability */ -+struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init, -+ struct dc_context *ctx); -+ -+/* Destroy ASIC capability and free memory space */ -+void dal_asic_capability_destroy(struct asic_capability **cap); -+ -+#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_types.h b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h -new file mode 100644 -index 0000000..1cb9776 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h -@@ -0,0 +1,134 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__ -+#define __DAL_ASIC_CAPABILITY_TYPES_H__ -+ -+/* -+ * ASIC Capabilities -+ */ -+struct asic_caps { -+ bool CONSUMER_SINGLE_SELECTED_TIMING:1; -+ bool UNDERSCAN_ADJUST:1; -+ bool DELTA_SIGMA_SUPPORT:1; -+ bool PANEL_SELF_REFRESH_SUPPORTED:1; -+ bool IS_FUSION:1; -+ bool DP_MST_SUPPORTED:1; -+ bool UNDERSCAN_FOR_HDMI_ONLY:1; -+ bool DVI_CLOCK_SHARE_CAPABILITY:1; -+ bool SUPPORT_CEA861E_FINAL:1; -+ bool MIRABILIS_SUPPORTED:1; -+ bool MIRABILIS_ENABLED_BY_DEFAULT:1; -+ bool DEVICE_TAG_REMAP_SUPPORTED:1; -+ bool HEADLESS_NO_OPM_SUPPORTED:1; -+ bool WIRELESS_LIMIT_TO_720P:1; -+ bool WIRELESS_FULL_TIMING_ADJUSTMENT:1; -+ bool WIRELESS_TIMING_ADJUSTMENT:1; -+ bool WIRELESS_COMPRESSED_AUDIO:1; -+ bool VCE_SUPPORTED:1; -+ bool HPD_CHECK_FOR_EDID:1; -+ bool NO_VCC_OFF_HPD_POLLING:1; -+ bool NEED_MC_TUNING:1; -+ bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1; -+ bool DFSBYPASS_DYNAMIC_SUPPORT:1; -+ bool SUPPORT_8BPP:1; -+}; -+ -+ -+/* -+ * ASIC Stereo 3D Caps -+ */ -+struct asic_stereo_3d_caps { -+ bool SUPPORTED:1; -+ bool DISPLAY_BASED_ON_WS:1; -+ bool HDMI_FRAME_PACK:1; -+ bool INTERLACE_FRAME_PACK:1; -+ bool DISPLAYPORT_FRAME_PACK:1; -+ bool DISPLAYPORT_FRAME_ALT:1; -+ bool INTERLEAVE:1; -+}; -+ -+ -+/* -+ * ASIC Bugs -+ */ -+struct asic_bugs { -+ bool MST_SYMBOL_MISALIGNMENT:1; -+ bool PSR_2X_LANE_GANGING:1; -+ bool LB_WA_IS_SUPPORTED:1; -+ bool ROM_REGISTER_ACCESS:1; -+ bool PSR_WA_OVERSCAN_CRC_ERROR:1; -+}; -+ -+ -+/* -+ * ASIC Data -+ */ -+enum asic_data { -+ ASIC_DATA_FIRST = 0, -+ ASIC_DATA_CONTROLLERS_NUM = ASIC_DATA_FIRST, -+ ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM, -+ ASIC_DATA_DCE_VERSION, -+ ASIC_DATA_DCE_VERSION_MINOR, -+ ASIC_DATA_VRAM_TYPE, -+ ASIC_DATA_VRAM_BITWIDTH, -+ ASIC_DATA_FEATURE_FLAGS, -+ ASIC_DATA_LINEBUFFER_NUM, -+ ASIC_DATA_LINEBUFFER_SIZE, -+ ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY, -+ ASIC_DATA_MC_LATENCY, -+ ASIC_DATA_MC_LATENCY_SLOW, -+ ASIC_DATA_CLOCKSOURCES_NUM, -+ ASIC_DATA_MEMORYTYPE_MULTIPLIER, -+ ASIC_DATA_STUTTERMODE, -+ ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR, -+ ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS, -+ ASIC_DATA_REVISION_ID, -+ ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE, -+ ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY, -+ ASIC_DATA_DIGFE_NUM, -+ ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM, -+ ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN, -+ ASIC_DATA_NUM_OF_VIDEO_PLANES, -+ ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ, -+ ASIC_DATA_MAX_NUMBER /* end of enum */ -+}; -+ -+ -+/* -+ * ASIC Feature Flags -+ */ -+struct asic_feature_flags { -+ union { -+ uint32_t raw; -+ struct { -+ uint32_t LEGACY_CLIENT:1; -+ uint32_t PACKED_PIXEL_FORMAT:1; -+ uint32_t WORKSTATION_STEREO:1; -+ uint32_t WORKSTATION:1; -+ } bits; -+ }; -+}; -+ -+#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/audio_interface.h b/drivers/gpu/drm/amd/dal/include/audio_interface.h -new file mode 100644 -index 0000000..bf21762 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/audio_interface.h -@@ -0,0 +1,184 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_AUDIO_INTERFACE_H__ -+#define __DAL_AUDIO_INTERFACE_H__ -+ -+#include "audio_types.h" -+#include "adapter_service_interface.h" -+#include "signal_types.h" -+#include "link_service_types.h" -+ -+/* forward declaration */ -+struct audio; -+struct dal_adapter_service; -+ -+/***** audio initialization data *****/ -+/* -+ * by audio, it means audio endpoint id. ASIC may have many endpoints. -+ * upper sw layer will create one audio object instance for each endpoints. -+ * ASIC support internal audio only. So enum number is used to differ -+ * each endpoint -+ */ -+struct audio_init_data { -+ struct adapter_service *as; -+ struct graphics_object_id audio_stream_id; -+ struct dc_context *ctx; -+}; -+ -+enum audio_result { -+ AUDIO_RESULT_OK, -+ AUDIO_RESULT_ERROR, -+}; -+ -+/****** audio object create, destroy ******/ -+struct audio *dal_audio_create( -+ const struct audio_init_data *init_data); -+ -+void dal_audio_destroy( -+ struct audio **audio); -+ -+/****** graphics object interface ******/ -+const struct graphics_object_id dal_audio_get_graphics_object_id( -+ const struct audio *audio); -+ -+/* Enumerate Graphics Object supported Input/Output Signal Types */ -+uint32_t dal_audio_enumerate_input_signals( -+ struct audio *audio); -+ -+uint32_t dal_audio_enumerate_output_signals( -+ struct audio *audio); -+ -+/* Check if signal supported by GraphicsObject */ -+bool dal_audio_is_input_signal_supported( -+ struct audio *audio, -+ enum signal_type signal); -+ -+bool dal_audio_is_output_signal_supported( -+ struct audio *audio, -+ enum signal_type signal); -+ -+ -+/***** programming interface *****/ -+ -+/* perform power up sequence (boot up, resume, recovery) */ -+enum audio_result dal_audio_power_up( -+ struct audio *audio); -+ -+/* perform power down (shut down, stand by) */ -+enum audio_result dal_audio_power_down( -+ struct audio *audio); -+ -+/* setup audio */ -+enum audio_result dal_audio_setup( -+ struct audio *audio, -+ struct audio_output *output, -+ struct audio_info *info); -+ -+/* enable audio */ -+enum audio_result dal_audio_enable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+/* disable audio */ -+enum audio_result dal_audio_disable_output( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+/* enable azalia audio endpoint */ -+enum audio_result dal_audio_enable_azalia_audio_jack_presence( -+ struct audio *audio, -+ enum engine_id engine_id); -+ -+/* disable azalia audio endpoint */ -+enum audio_result dal_audio_disable_azalia_audio_jack_presence( -+ struct audio *audio, -+ enum engine_id engine_id); -+ -+/* unmute audio */ -+enum audio_result dal_audio_unmute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+/* mute audio */ -+enum audio_result dal_audio_mute( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal); -+ -+ -+/***** information interface *****/ -+ -+struct audio_feature_support dal_audio_get_supported_features( -+ struct audio *audio); -+ -+/* get audio bandwidth information */ -+void dal_audio_check_audio_bandwidth( -+ struct audio *audio, -+ const struct audio_crtc_info *info, -+ uint32_t channel_count, -+ enum signal_type signal, -+ union audio_sample_rates *sample_rates); -+ -+/* Enable multi channel split */ -+void dal_audio_enable_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ enum signal_type signal, -+ const struct audio_channel_associate_info *audio_mapping, -+ bool enable); -+ -+/* get current multi channel split. */ -+enum audio_result dal_audio_get_channel_splitting_mapping( -+ struct audio *audio, -+ enum engine_id engine_id, -+ struct audio_channel_associate_info *audio_mapping); -+ -+/* set payload value for the unsolicited response */ -+void dal_audio_set_unsolicited_response_payload( -+ struct audio *audio, -+ enum audio_payload payload); -+ -+/*Assign GTC group and enable GTC value embedding*/ -+void dal_audio_enable_gtc_embedding_with_group( -+ struct audio *audio, -+ uint32_t group_num, -+ uint32_t audio_latency); -+ -+/* Disable GTC value embedding */ -+void dal_audio_disable_gtc_embedding( -+ struct audio *audio); -+ -+/* Update audio wall clock source */ -+void dal_audio_setup_audio_wall_dto( -+ struct audio *audio, -+ enum signal_type signal, -+ const struct audio_crtc_info *crtc_info, -+ const struct audio_pll_info *pll_info); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/audio_types.h b/drivers/gpu/drm/amd/dal/include/audio_types.h -new file mode 100644 -index 0000000..e9c2ab3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/audio_types.h -@@ -0,0 +1,275 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __AUDIO_TYPES_H__ -+#define __AUDIO_TYPES_H__ -+ -+#include "grph_object_defs.h" -+#include "signal_types.h" -+ -+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 -+#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18 -+#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF -+ -+ -+struct audio_pll_hw_settings { -+ uint32_t feed_back_divider; -+ uint32_t step_size_integer; -+ uint32_t step_size_fraction; -+ uint32_t step_range; -+}; -+ -+struct audio_clock_info { -+ /* pixel clock frequency*/ -+ uint32_t pixel_clock_in_10khz; -+ /* N - 32KHz audio */ -+ uint32_t n_32khz; -+ /* CTS - 32KHz audio*/ -+ uint32_t cts_32khz; -+ uint32_t n_44khz; -+ uint32_t cts_44khz; -+ uint32_t n_48khz; -+ uint32_t cts_48khz; -+}; -+ -+struct azalia_clock_info { -+ uint32_t pixel_clock_in_10khz; -+ uint32_t audio_dto_phase; -+ uint32_t audio_dto_module; -+ uint32_t audio_dto_wall_clock_ratio; -+}; -+ -+enum audio_dto_source { -+ DTO_SOURCE_UNKNOWN = 0, -+ DTO_SOURCE_ID0, -+ DTO_SOURCE_ID1, -+ DTO_SOURCE_ID2, -+ DTO_SOURCE_ID3, -+ DTO_SOURCE_ID4, -+ DTO_SOURCE_ID5 -+}; -+ -+union audio_sample_rates { -+ struct sample_rates { -+ uint8_t RATE_32:1; -+ uint8_t RATE_44_1:1; -+ uint8_t RATE_48:1; -+ uint8_t RATE_88_2:1; -+ uint8_t RATE_96:1; -+ uint8_t RATE_176_4:1; -+ uint8_t RATE_192:1; -+ } rate; -+ -+ uint8_t all; -+}; -+ -+enum audio_format_code { -+ AUDIO_FORMAT_CODE_FIRST = 1, -+ AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST, -+ -+ AUDIO_FORMAT_CODE_AC3, -+ /*Layers 1 & 2 */ -+ AUDIO_FORMAT_CODE_MPEG1, -+ /*MPEG1 Layer 3 */ -+ AUDIO_FORMAT_CODE_MP3, -+ /*multichannel */ -+ AUDIO_FORMAT_CODE_MPEG2, -+ AUDIO_FORMAT_CODE_AAC, -+ AUDIO_FORMAT_CODE_DTS, -+ AUDIO_FORMAT_CODE_ATRAC, -+ AUDIO_FORMAT_CODE_1BITAUDIO, -+ AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS, -+ AUDIO_FORMAT_CODE_DTS_HD, -+ AUDIO_FORMAT_CODE_MAT_MLP, -+ AUDIO_FORMAT_CODE_DST, -+ AUDIO_FORMAT_CODE_WMAPRO, -+ AUDIO_FORMAT_CODE_LAST, -+ AUDIO_FORMAT_CODE_COUNT = -+ AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST -+}; -+ -+struct audio_mode { -+ /* ucData[0] [6:3] */ -+ enum audio_format_code format_code; -+ /* ucData[0] [2:0] */ -+ uint8_t channel_count; -+ /* ucData[1] */ -+ union audio_sample_rates sample_rates; -+ union { -+ /* for LPCM */ -+ uint8_t sample_size; -+ /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */ -+ uint8_t max_bit_rate; -+ /* for Audio Formats 9-15 */ -+ uint8_t vendor_specific; -+ }; -+}; -+ -+struct audio_info_flags { -+ -+ union { -+ -+ 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; -+ } speaker_flags; -+ -+ struct audio_speaker_info { -+ uint32_t ALLSPEAKERS:7; -+ uint32_t SUPPORT_AI:1; -+ } info; -+ -+ uint8_t all; -+ }; -+}; -+ -+ -+/*struct audio_info_flags { -+ struct audio_speaker_flags { -+ uint32_t FL_FR:1; -+ uint32_t LFE:1; -+ uint32_t FC:1; -+ uint32_t RL_RR:1; -+ uint32_t RC:1; -+ uint32_t FLC_FRC:1; -+ uint32_t RLC_RRC:1; -+ uint32_t SUPPORT_AI:1; -+ }; -+ -+ struct audio_speaker_info { -+ uint32_t ALLSPEAKERS:7; -+ uint32_t SUPPORT_AI:1; -+ }; -+ -+ union { -+ struct audio_speaker_flags speaker_flags; -+ struct audio_speaker_info info; -+ }; -+}; -+*/ -+ -+union audio_cea_channels { -+ uint8_t all; -+ struct audio_cea_channels_bits { -+ uint32_t FL:1; -+ uint32_t FR:1; -+ uint32_t LFE:1; -+ uint32_t FC:1; -+ uint32_t RL_RC:1; -+ uint32_t RR:1; -+ uint32_t RC_RLC_FLC:1; -+ uint32_t RRC_FRC:1; -+ } channels; -+}; -+ -+struct audio_info { -+ struct audio_info_flags flags; -+ uint32_t video_latency; -+ uint32_t audio_latency; -+ uint32_t display_index; -+ uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; -+ uint32_t manufacture_id; -+ uint32_t product_id; -+ /* PortID used for ContainerID when defined */ -+ uint32_t port_id[2]; -+ uint32_t mode_count; -+ /* this field must be last in this struct */ -+ struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT]; -+}; -+ -+struct audio_crtc_info { -+ uint32_t h_total; -+ uint32_t h_active; -+ uint32_t v_active; -+ uint32_t pixel_repetition; -+ uint32_t requested_pixel_clock; /* in KHz */ -+ uint32_t calculated_pixel_clock; /* in KHz */ -+ uint32_t refresh_rate; -+ enum dc_color_depth color_depth; -+ bool interlaced; -+}; -+ -+/* PLL information required for AZALIA DTO calculation */ -+ -+struct audio_pll_info { -+ uint32_t dp_dto_source_clock_in_khz; -+ uint32_t feed_back_divider; -+ enum audio_dto_source dto_source; -+ bool ss_enabled; -+ uint32_t ss_percentage; -+ uint32_t ss_percentage_divider; -+}; -+ -+struct audio_channel_associate_info { -+ union { -+ struct { -+ uint32_t ALL_CHANNEL_FL:4; -+ uint32_t ALL_CHANNEL_FR:4; -+ uint32_t ALL_CHANNEL_FC:4; -+ uint32_t ALL_CHANNEL_Sub:4; -+ uint32_t ALL_CHANNEL_SL:4; -+ uint32_t ALL_CHANNEL_SR:4; -+ uint32_t ALL_CHANNEL_BL:4; -+ uint32_t ALL_CHANNEL_BR:4; -+ } bits; -+ uint32_t u32all; -+ }; -+}; -+ -+struct audio_output { -+ /* Front DIG id. */ -+ enum engine_id engine_id; -+ /* encoder output signal */ -+ enum signal_type signal; -+ /* video timing */ -+ struct audio_crtc_info crtc_info; -+ /* PLL for audio */ -+ struct audio_pll_info pll_info; -+}; -+ -+struct audio_feature_support { -+ /* supported engines*/ -+ uint32_t ENGINE_DIGA:1; -+ uint32_t ENGINE_DIGB:1; -+ uint32_t ENGINE_DIGC:1; -+ uint32_t ENGINE_DIGD:1; -+ uint32_t ENGINE_DIGE:1; -+ uint32_t ENGINE_DIGF:1; -+ uint32_t ENGINE_DIGG:1; -+ uint32_t ENGINE_DVO:1; -+ uint32_t MULTISTREAM_AUDIO:1; -+}; -+ -+enum audio_payload { -+ CHANNEL_SPLIT_MAPPINGCHANG = 0x9, -+}; -+ -+#endif /* __AUDIO_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h -new file mode 100644 -index 0000000..6269164 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h -@@ -0,0 +1,294 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "bios_parser_types.h" -+#include "adapter_service_types.h" -+#include "gpio_types.h" -+ -+struct adapter_service; -+struct bios_parser; -+ -+struct bp_gpio_cntl_info { -+ uint32_t id; -+ enum gpio_pin_output_state state; -+}; -+ -+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 -+}; -+ -+struct bp_init_data { -+ struct dc_context *ctx; -+ uint8_t *bios; -+}; -+ -+struct bios_parser *dal_bios_parser_create( -+ struct bp_init_data *init, -+ struct adapter_service *as); -+void dal_bios_parser_destroy( -+ struct bios_parser **bp); -+void dal_bios_parser_power_down( -+ struct bios_parser *bp); -+void dal_bios_parser_power_up( -+ struct bios_parser *bp); -+ -+uint8_t dal_bios_parser_get_encoders_number( -+ struct bios_parser *bp); -+uint8_t dal_bios_parser_get_connectors_number( -+ struct bios_parser *bp); -+uint32_t dal_bios_parser_get_oem_ddc_lines_number( -+ struct bios_parser *bp); -+struct graphics_object_id dal_bios_parser_get_encoder_id( -+ struct bios_parser *bp, -+ uint32_t i); -+struct graphics_object_id dal_bios_parser_get_connector_id( -+ struct bios_parser *bp, -+ uint8_t connector_index); -+uint32_t dal_bios_parser_get_src_number( -+ struct bios_parser *bp, -+ struct graphics_object_id id); -+uint32_t dal_bios_parser_get_dst_number( -+ struct bios_parser *bp, -+ struct graphics_object_id id); -+uint32_t dal_bios_parser_get_gpio_record( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct bp_gpio_cntl_info *gpio_record, -+ uint32_t record_size); -+enum bp_result dal_bios_parser_get_src_obj( -+ struct bios_parser *bp, -+ struct graphics_object_id object_id, uint32_t index, -+ struct graphics_object_id *src_object_id); -+enum bp_result dal_bios_parser_get_dst_obj( -+ struct bios_parser *bp, -+ struct graphics_object_id object_id, uint32_t index, -+ struct graphics_object_id *dest_object_id); -+enum bp_result dal_bios_parser_get_i2c_info( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct graphics_object_i2c_info *info); -+enum bp_result dal_bios_parser_get_oem_ddc_info( -+ struct bios_parser *bp, -+ uint32_t index, -+ struct graphics_object_i2c_info *info); -+enum bp_result dal_bios_parser_get_voltage_ddc_info( -+ struct bios_parser *bp, -+ uint32_t index, -+ struct graphics_object_i2c_info *info); -+enum bp_result dal_bios_parser_get_thermal_ddc_info( -+ struct bios_parser *bp, -+ uint32_t i2c_channel_id, -+ struct graphics_object_i2c_info *info); -+enum bp_result dal_bios_parser_get_hpd_info( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct graphics_object_hpd_info *info); -+enum bp_result dal_bios_parser_get_device_tag( -+ struct bios_parser *bp, -+ struct graphics_object_id connector_object_id, -+ uint32_t device_tag_index, -+ struct connector_device_tag_info *info); -+enum bp_result dal_bios_parser_get_firmware_info( -+ struct bios_parser *bp, -+ struct firmware_info *info); -+enum bp_result dal_bios_parser_get_spread_spectrum_info( -+ struct bios_parser *bp, -+ enum as_signal_type signal, -+ uint32_t index, -+ struct spread_spectrum_info *ss_info); -+uint32_t dal_bios_parser_get_ss_entry_number( -+ struct bios_parser *bp, -+ enum as_signal_type signal); -+enum bp_result dal_bios_parser_get_embedded_panel_info( -+ struct bios_parser *bp, -+ struct embedded_panel_info *info); -+enum bp_result dal_bios_parser_enum_embedded_panel_patch_mode( -+ struct bios_parser *bp, -+ uint32_t index, -+ struct embedded_panel_patch_mode *mode); -+enum bp_result dal_bios_parser_get_gpio_pin_info( -+ struct bios_parser *bp, -+ uint32_t gpio_id, -+ struct gpio_pin_info *info); -+enum bp_result dal_bios_parser_get_embedded_panel_info( -+ struct bios_parser *bp, -+ struct embedded_panel_info *info); -+enum bp_result dal_bios_parser_get_gpio_pin_info( -+ struct bios_parser *bp, -+ uint32_t gpio_id, -+ struct gpio_pin_info *info); -+enum bp_result dal_bios_parser_get_faked_edid_len( -+ struct bios_parser *bp, -+ uint32_t *len); -+enum bp_result dal_bios_parser_get_faked_edid_buf( -+ struct bios_parser *bp, -+ uint8_t *buff, -+ uint32_t len); -+enum bp_result dal_bios_parser_get_encoder_cap_info( -+ struct bios_parser *bp, -+ struct graphics_object_id object_id, -+ struct bp_encoder_cap_info *info); -+enum bp_result dal_bios_parser_get_din_connector_info( -+ struct bios_parser *bp, -+ struct graphics_object_id id, -+ struct din_connector_info *info); -+ -+bool dal_bios_parser_is_lid_open( -+ struct bios_parser *bp); -+bool dal_bios_parser_is_lid_status_changed( -+ struct bios_parser *bp); -+bool dal_bios_parser_is_display_config_changed( -+ struct bios_parser *bp); -+bool dal_bios_parser_is_accelerated_mode( -+ struct bios_parser *bp); -+void dal_bios_parser_set_scratch_lcd_scale( -+ struct bios_parser *bp, -+ enum lcd_scale scale); -+enum lcd_scale dal_bios_parser_get_scratch_lcd_scale( -+ struct bios_parser *bp); -+void dal_bios_parser_get_bios_event_info( -+ struct bios_parser *bp, -+ struct bios_event_info *info); -+void dal_bios_parser_update_requested_backlight_level( -+ struct bios_parser *bp, -+ uint32_t backlight_8bit); -+uint32_t dal_bios_parser_get_requested_backlight_level( -+ struct bios_parser *bp); -+void dal_bios_parser_take_backlight_control( -+ struct bios_parser *bp, -+ bool cntl); -+bool dal_bios_parser_is_active_display( -+ struct bios_parser *bp, -+ enum signal_type signal, -+ const struct connector_device_tag_info *device_tag); -+enum controller_id dal_bios_parser_get_embedded_display_controller_id( -+ struct bios_parser *bp); -+uint32_t dal_bios_parser_get_embedded_display_refresh_rate( -+ struct bios_parser *bp); -+void dal_bios_parser_set_scratch_connected( -+ struct bios_parser *bp, -+ struct graphics_object_id connector_id, -+ bool connected, -+ const struct connector_device_tag_info *device_tag); -+void dal_bios_parser_prepare_scratch_active_and_requested( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ enum signal_type signal, -+ const struct connector_device_tag_info *device_tag); -+void dal_bios_parser_set_scratch_active_and_requested( -+ struct bios_parser *bp); -+void dal_bios_parser_set_scratch_critical_state( -+ struct bios_parser *bp, -+ bool state); -+void dal_bios_parser_set_scratch_acc_mode_change( -+ struct bios_parser *bp); -+ -+bool dal_bios_parser_is_device_id_supported( -+ struct bios_parser *bp, -+ struct device_id id); -+ -+/* COMMANDS */ -+ -+enum bp_result dal_bios_parser_encoder_control( -+ struct bios_parser *bp, -+ struct bp_encoder_control *cntl); -+enum bp_result dal_bios_parser_transmitter_control( -+ struct bios_parser *bp, -+ struct bp_transmitter_control *cntl); -+enum bp_result dal_bios_parser_crt_control( -+ struct bios_parser *bp, -+ enum engine_id engine_id, -+ bool enable, -+ uint32_t pixel_clock); -+enum bp_result dal_bios_parser_dvo_encoder_control( -+ struct bios_parser *bp, -+ struct bp_dvo_encoder_control *cntl); -+enum bp_result dal_bios_parser_enable_crtc( -+ struct bios_parser *bp, -+ enum controller_id id, -+ bool enable); -+enum bp_result dal_bios_parser_adjust_pixel_clock( -+ struct bios_parser *bp, -+ struct bp_adjust_pixel_clock_parameters *bp_params); -+enum bp_result dal_bios_parser_set_pixel_clock( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params); -+enum bp_result dal_bios_parser_enable_spread_spectrum_on_ppll( -+ struct bios_parser *bp, -+ struct bp_spread_spectrum_parameters *bp_params, -+ bool enable); -+enum bp_result dal_bios_parser_program_crtc_timing( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_timing_parameters *bp_params); -+enum bp_result dal_bios_parser_blank_crtc( -+ struct bios_parser *bp, -+ struct bp_blank_crtc_parameters *bp_params, -+ bool blank); -+enum bp_result dal_bios_parser_set_overscan( -+ struct bios_parser *bp, -+ struct bp_hw_crtc_overscan_parameters *bp_params); -+enum bp_result dal_bios_parser_crtc_source_select( -+ struct bios_parser *bp, -+ struct bp_crtc_source_select *bp_params); -+enum bp_result dal_bios_parser_program_display_engine_pll( -+ struct bios_parser *bp, -+ struct bp_pixel_clock_parameters *bp_params); -+enum bp_result dal_bios_parser_get_divider_for_target_display_clock( -+ struct bios_parser *bp, -+ struct bp_display_clock_parameters *bp_params); -+enum signal_type dal_bios_parser_dac_load_detect( -+ struct bios_parser *bp, -+ struct graphics_object_id encoder, -+ struct graphics_object_id connector, -+ enum signal_type display_signal); -+enum bp_result dal_bios_parser_enable_memory_requests( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ bool enable); -+enum bp_result dal_bios_parser_external_encoder_control( -+ struct bios_parser *bp, -+ struct bp_external_encoder_control *cntl); -+enum bp_result dal_bios_parser_enable_disp_power_gating( -+ struct bios_parser *bp, -+ enum controller_id controller_id, -+ enum bp_pipe_control_action action); -+ -+void dal_bios_parser_post_init(struct bios_parser *bp); -+ -+/* Parse integrated BIOS info */ -+struct integrated_info *dal_bios_parser_create_integrated_info( -+ struct bios_parser *bp); -+ -+/* Destroy provided integrated info */ -+void dal_bios_parser_destroy_integrated_info(struct dc_context *ctx, struct integrated_info **info); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h -new file mode 100644 -index 0000000..da7d5f2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h -@@ -0,0 +1,305 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_BIOS_PARSER_TYPES_H__ -+#define __DAL_BIOS_PARSER_TYPES_H__ -+ -+#include "include/signal_types.h" -+#include "include/grph_object_ctrl_defs.h" -+#include "link_service_types.h" -+ -+enum bp_encoder_control_action { -+ /* direct VBIOS translation! Just to simplify the translation */ -+ ENCODER_CONTROL_DISABLE = 0, -+ ENCODER_CONTROL_ENABLE, -+ ENCODER_CONTROL_SETUP, -+ ENCODER_CONTROL_INIT -+}; -+ -+enum bp_transmitter_control_action { -+ /* direct VBIOS translation! Just to simplify the translation */ -+ TRANSMITTER_CONTROL_DISABLE = 0, -+ TRANSMITTER_CONTROL_ENABLE, -+ TRANSMITTER_CONTROL_BACKLIGHT_OFF, -+ TRANSMITTER_CONTROL_BACKLIGHT_ON, -+ TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS, -+ TRANSMITTER_CONTROL_LCD_SETF_TEST_START, -+ TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP, -+ TRANSMITTER_CONTROL_INIT, -+ TRANSMITTER_CONTROL_DEACTIVATE, -+ TRANSMITTER_CONTROL_ACTIAVATE, -+ TRANSMITTER_CONTROL_SETUP, -+ TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS, -+ /* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only -+ * (power up the panel) -+ */ -+ TRANSMITTER_CONTROL_POWER_ON, -+ /* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only -+ * (power down the panel) -+ */ -+ TRANSMITTER_CONTROL_POWER_OFF -+}; -+ -+enum bp_external_encoder_control_action { -+ EXTERNAL_ENCODER_CONTROL_DISABLE = 0, -+ EXTERNAL_ENCODER_CONTROL_ENABLE = 1, -+ EXTERNAL_ENCODER_CONTROL_INIT = 0x7, -+ EXTERNAL_ENCODER_CONTROL_SETUP = 0xf, -+ EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10, -+ EXTERNAL_ENCODER_CONTROL_BLANK = 0x11, -+ EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12 -+}; -+ -+enum bp_pipe_control_action { -+ ASIC_PIPE_DISABLE = 0, -+ ASIC_PIPE_ENABLE, -+ ASIC_PIPE_INIT -+}; -+ -+struct bp_encoder_control { -+ enum bp_encoder_control_action action; -+ enum engine_id engine_id; -+ enum transmitter transmitter; -+ enum signal_type signal; -+ enum lane_count lanes_number; -+ enum dc_color_depth color_depth; -+ bool enable_dp_audio; -+ uint32_t pixel_clock; /* khz */ -+}; -+ -+struct bp_external_encoder_control { -+ enum bp_external_encoder_control_action action; -+ enum engine_id engine_id; -+ enum link_rate link_rate; -+ enum lane_count lanes_number; -+ enum signal_type signal; -+ enum dc_color_depth color_depth; -+ bool coherent; -+ struct graphics_object_id encoder_id; -+ struct graphics_object_id connector_obj_id; -+ uint32_t pixel_clock; /* in KHz */ -+}; -+ -+struct bp_crtc_source_select { -+ enum engine_id engine_id; -+ enum controller_id controller_id; -+ /* from GPU Tx aka asic_signal */ -+ enum signal_type signal; -+ /* sink_signal may differ from asicSignal if Translator encoder */ -+ enum signal_type sink_signal; -+ enum display_output_bit_depth display_output_bit_depth; -+ bool enable_dp_audio; -+}; -+ -+struct bp_transmitter_control { -+ enum bp_transmitter_control_action action; -+ enum engine_id engine_id; -+ enum transmitter transmitter; /* PhyId */ -+ enum lane_count lanes_number; -+ enum clock_source_id pll_id; /* needed for DCE 4.0 */ -+ enum signal_type signal; -+ enum dc_color_depth color_depth; /* not used for DCE6.0 */ -+ enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */ -+ struct graphics_object_id connector_obj_id; -+ /* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should -+ * be pixel clock * deep_color_ratio (in KHz) -+ */ -+ uint32_t pixel_clock; -+ uint32_t lane_select; -+ uint32_t lane_settings; -+ bool coherent; -+ bool multi_path; -+ bool single_pll_mode; -+}; -+ -+enum dvo_encoder_memory_rate { -+ DVO_ENCODER_MEMORY_RATE_DDR, -+ DVO_ENCODER_MEMORY_RATE_SDR -+}; -+ -+enum dvo_encoder_interface_width { -+ DVO_ENCODER_INTERFACE_WIDTH_LOW12BIT, -+ DVO_ENCODER_INTERFACE_WIDTH_HIGH12BIT, -+ DVO_ENCODER_INTERFACE_WIDTH_FULL24BIT -+}; -+ -+struct bp_dvo_encoder_control { -+ enum bp_encoder_control_action action; -+ enum dvo_encoder_memory_rate memory_rate; -+ enum dvo_encoder_interface_width interface_width; -+ uint32_t pixel_clock; /* in KHz */ -+}; -+ -+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: required by V3, display pll configure parameter defined as -+ * following DISPPLL_CONFIG_XXXX */ -+ enum disp_pll_config display_pll_config; -+ /* 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; -+ union { -+ /* Input: If DVO, need passing link rate and output 12bit low or -+ * 24bit to VBIOS Exec table */ -+ uint32_t dvo_config; -+ /* Input: If non DVO, not defined yet */ -+ uint32_t non_dvo_undefined; -+ }; -+ /* 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 */ -+ /* If DVO, need passing link rate and output 12bit low or -+ * 24bit to VBIOS Exec table */ -+ uint32_t dvo_config; -+ /* VBIOS returns a fixed display clock when DFS-bypass feature -+ * is enabled (KHz) */ -+ uint32_t dfs_bypass_display_clock; -+ 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; -+ } 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; -+}; -+ -+struct spread_spectrum_flags { -+ /* 1 = Center Spread; 0 = down spread */ -+ uint32_t CENTER_SPREAD:1; -+ /* 1 = external; 0 = internal */ -+ uint32_t EXTERNAL_SS:1; -+ /* 1 = delta-sigma type parameter; 0 = ver1 */ -+ uint32_t DS_TYPE:1; -+}; -+ -+struct bp_spread_spectrum_parameters { -+ enum clock_source_id pll_id; -+ uint32_t percentage; -+ uint32_t ds_frac_amount; -+ -+ union { -+ struct { -+ uint32_t step; -+ uint32_t delay; -+ uint32_t range; /* In Hz unit */ -+ } ver1; -+ struct { -+ uint32_t feedback_amount; -+ uint32_t nfrac_amount; -+ uint32_t ds_frac_size; -+ } ds; -+ }; -+ -+ struct spread_spectrum_flags flags; -+}; -+ -+struct bp_encoder_cap_info { -+ uint32_t DP_HBR2_CAP:1; -+ uint32_t DP_HBR2_EN:1; -+ uint32_t RESERVED:30; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/bit_set.h b/drivers/gpu/drm/amd/dal/include/bit_set.h -new file mode 100644 -index 0000000..3cd8d32 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/bit_set.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_BIT_SET_H__ -+#define __DAL_BIT_SET_H__ -+ -+struct bit_set_iterator_32 { -+ uint32_t value; -+}; -+ -+static inline uint32_t least_significant_bit(uint32_t bs32_container) -+{ -+ return bs32_container & (0 - bs32_container); -+} -+/* iterates over bit_set_iterator by means of least significant bit purge*/ -+static inline uint32_t get_next_significant_bit( -+ struct bit_set_iterator_32 *bs32) -+{ -+ uint32_t lsb = least_significant_bit(bs32->value); -+ -+ bs32->value &= ~lsb; -+ return lsb; -+} -+ -+static inline void bit_set_iterator_reset_to_mask( -+ struct bit_set_iterator_32 *bs32, -+ uint32_t mask) -+{ -+ bs32->value = mask; -+} -+ -+static inline void bit_set_iterator_construct( -+ struct bit_set_iterator_32 *bs32, -+ uint32_t mask) -+{ -+ bit_set_iterator_reset_to_mask(bs32, mask); -+} -+ -+#endif /* __DAL_BIT_SET_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/clock_source_interface.h b/drivers/gpu/drm/amd/dal/include/clock_source_interface.h -new file mode 100644 -index 0000000..bea4c2b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/clock_source_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_CLOCK_SOURCE_INTERFACE__ -+#define __DAL_CLOCK_SOURCE_INTERFACE__ -+ -+#include "include/clock_source_types.h" -+ -+struct clock_source; -+struct clock_source_init_data { -+ struct adapter_service *as; -+ struct graphics_object_id clk_src_id; -+ struct dc_context *ctx; -+}; -+ -+struct clock_source *dal_clock_source_create(struct clock_source_init_data *); -+ -+void dal_clock_source_destroy(struct clock_source **clk_src); -+ -+enum clock_source_id dal_clock_source_get_id( -+ const struct clock_source *clk_src); -+ -+bool dal_clock_source_is_clk_src_with_fixed_freq( -+ const struct clock_source *clk_src); -+ -+const struct graphics_object_id dal_clock_source_get_graphics_object_id( -+ const struct clock_source *clk_src); -+ -+enum clock_sharing_level dal_clock_souce_get_clk_sharing_lvl( -+ const struct clock_source *clk_src); -+ -+uint32_t dal_clock_source_get_pix_clk_dividers( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+ -+bool dal_clock_source_program_pix_clk( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ struct pll_settings *pll_settings); -+ -+bool dal_clock_source_adjust_pxl_clk_by_ref_pixel_rate( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ uint32_t pix_clk_hz); -+ -+bool dal_clock_source_adjust_pxl_clk_by_pix_amount( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params, -+ int32_t pix_num); -+ -+uint32_t dal_clock_source_retreive_pix_rate_hz( -+ struct clock_source *clk_src, -+ struct pixel_clk_params *pix_clk_params); -+ -+bool dal_clock_source_power_down_pll(struct clock_source *clk_src, -+ enum controller_id); -+ -+bool dal_clock_source_is_clk_in_reset(struct clock_source *clk_src); -+ -+bool dal_clock_source_is_gen_lock_capable(struct clock_source *clk_src); -+ -+bool dal_clock_source_is_output_signal_supported( -+ const struct clock_source *clk_src, -+ enum signal_type signal_type); -+ -+#endif /*__DAL_CLOCK_SOURCE_INTERFACE__*/ -diff --git a/drivers/gpu/drm/amd/dal/include/clock_source_types.h b/drivers/gpu/drm/amd/dal/include/clock_source_types.h -new file mode 100644 -index 0000000..3883216 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/clock_source_types.h -@@ -0,0 +1,118 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_CLOCK_SOURCE_TYPES_H__ -+#define __DAL_CLOCK_SOURCE_TYPES_H__ -+ -+#include "include/signal_types.h" -+#include "include/grph_object_ctrl_defs.h" -+ -+/** -+ * ClockSharingLevel -+ * Enumeration for clock sharing support. -+ * Level <x> means sharing supported on all levels below and including <x> -+ */ -+enum clock_sharing_level { -+ CLOCK_SHARING_LEVEL_NOT_SHAREABLE = 0, -+ CLOCK_SHARING_LEVEL_DP_MST_SHAREABLE, -+ CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE -+}; -+ -+/** -+ * 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 */ -+}; -+ -+/** -+ * 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; -+}; -+ -+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*/ -+ -+ uint32_t dvo_cfg; -+/*> If DVO, need passing link rate -+ * and output 12bit low or 24bit to VBIOS Exec table*/ -+ -+ enum disp_pll_config disp_pll_cfg; -+ 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; -+}; -+ -+#define MAX_PLL_CALC_ERROR 0xFFFFFFFF -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/connector_interface.h b/drivers/gpu/drm/amd/dal/include/connector_interface.h -new file mode 100644 -index 0000000..e09af7e ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/connector_interface.h -@@ -0,0 +1,82 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_CONNECTOR_INTERFACE_H__ -+#define __DAL_CONNECTOR_INTERFACE_H__ -+ -+#include "adapter_service_interface.h" -+#include "signal_types.h" -+ -+/* forward declaration */ -+struct connector; -+ -+struct connector_signals { -+ const enum signal_type *signal; -+ uint32_t number_of_signals; -+}; -+ -+struct connector_feature_support { -+ bool HPD_FILTERING:1; -+ bool HW_DDC_POLLING:1; -+ enum hpd_source_id hpd_line; -+ enum channel_id ddc_line; -+}; -+ -+void dal_connector_get_features( -+ const struct connector *con, -+ struct connector_feature_support *cfs); -+ -+struct connector *dal_connector_create( -+ struct dc_context *ctx, -+ struct adapter_service *as, -+ struct graphics_object_id go_id); -+ -+void dal_connector_destroy(struct connector **connector); -+ -+void dal_connector_destroy(struct connector **connector); -+ -+const struct graphics_object_id dal_connector_get_graphics_object_id( -+ const struct connector *connector); -+ -+uint32_t dal_connector_enumerate_output_signals( -+ const struct connector *connector); -+uint32_t dal_connector_enumerate_input_signals( -+ const struct connector *connector); -+ -+struct connector_signals dal_connector_get_default_signals( -+ const struct connector *connector); -+ -+bool dal_connector_program_hpd_filter( -+ const struct connector *connector, -+ const uint32_t delay_on_connect_in_ms, -+ const uint32_t delay_on_disconnect_in_ms); -+ -+bool dal_connector_enable_ddc_polling( -+ const struct connector *connector, -+ const bool is_poll_for_connect); -+ -+bool dal_connector_disable_ddc_polling(const struct connector *connector); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h -new file mode 100644 -index 0000000..fa04f80 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dal_asic_id.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_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)) -+ -+/* DCE11 */ -+#define CZ_CARRIZO_A0 0x01 -+ -+#define STONEY_A0 0x61 -+#define CZ_UNKNOWN 0xFF -+ -+#define ASIC_REV_IS_STONEY(rev) \ -+ ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) -+ -+/* -+ * ASIC chip ID -+ */ -+/* DCE80 */ -+#define DEVICE_ID_KALINDI_9834 0x9834 -+#define DEVICE_ID_TEMASH_9839 0x9839 -+#define DEVICE_ID_TEMASH_983D 0x983D -+ -+ -+/* Asic Family IDs for different asic family. */ -+#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */ -+#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */ -+#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ -+#define FAMILY_CZ 135 /* Carrizo */ -+ -+#define FAMILY_UNKNOWN 0xFF -+ -+#endif /* __DAL_ASIC_ID_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dal_register_logger.h b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h -new file mode 100644 -index 0000000..176d811 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_REGISTER_LOGGER__ -+#define __DAL_REGISTER_LOGGER__ -+ -+/**************** -+ * API functions -+ ***************/ -+ -+/* dal_reg_logger_push - begin Register Logging */ -+void dal_reg_logger_push(const char *caller_func); -+/* dal_reg_logger_pop - stop Register Logging */ -+void dal_reg_logger_pop(void); -+ -+ -+/* for internal use of the Logger only */ -+void dal_reg_logger_rw_count_increment(void); -+bool dal_reg_logger_should_dump_register(void); -+ -+#endif /* __DAL_REGISTER_LOGGER__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dal_types.h b/drivers/gpu/drm/amd/dal/include/dal_types.h -new file mode 100644 -index 0000000..d3c91b9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dal_types.h -@@ -0,0 +1,292 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "dcs_types.h" -+struct dal_logger; -+ -+enum dce_version { -+ DCE_VERSION_UNKNOWN = (-1), -+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) -+ DCE_VERSION_11_0, -+#endif -+ DCE_VERSION_MAX -+}; -+ -+/* -+ * ASIC Runtime Flags -+ */ -+struct dal_asic_runtime_flags { -+ union { -+ uint32_t raw; -+ struct { -+ uint32_t EMULATE_REPLUG_ON_CAP_CHANGE:1; -+ uint32_t SUPPORT_XRBIAS:1; -+ uint32_t SKIP_POWER_DOWN_ON_RESUME:1; -+ uint32_t FULL_DETECT_ON_RESUME:1; -+ uint32_t GSL_FRAMELOCK:1; -+ uint32_t NO_LOW_BPP_MODES:1; -+ uint32_t BLOCK_ON_INITIAL_DETECTION:1; -+ uint32_t OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT:1; -+ uint32_t DRIVER_CONTROLLED_BRIGHTNESS:1; -+ uint32_t MODIFIABLE_FRAME_DURATION:1; -+ uint32_t MIRACAST_SUPPORTED:1; -+ uint32_t CONNECTED_STANDBY_SUPPORTED:1; -+ uint32_t GNB_WAKEUP_SUPPORTED:1; -+ } bits; -+ } flags; -+}; -+ -+struct hw_asic_id { -+ uint32_t chip_id; -+ uint32_t chip_family; -+ uint32_t pci_revision_id; -+ uint32_t hw_internal_rev; -+ uint32_t vram_type; -+ uint32_t vram_width; -+ uint32_t feature_flags; -+ struct dal_asic_runtime_flags runtime_flags; -+ uint32_t fake_paths_num; -+ void *atombios_base_address; -+}; -+ -+/* this is pci information. BDF stands for BUS,DEVICE,FUNCTION*/ -+ -+struct bdf_info { -+ uint16_t BUS_NUMBER:8; -+ uint16_t DEVICE_NUMBER:5; -+ uint16_t FUNCTION_NUMBER:3; -+}; -+ -+#define DAL_PARAM_INVALID_INT 0x80000000 -+ -+/* shift values for bool override parameter mask -+ * bmask is for this struct,if we touch this feature -+ * bval indicates every bit fields for this struct too,1 is enable this feature -+ * amdgpu.disp_bval=1594, amdgpu.disp_bmask=1594 , -+ * finally will show log like this: -+ * Overridden FEATURE_LIGHT_SLEEP is enabled now -+ * Overridden FEATURE_USE_MAX_DISPLAY_CLK is enabled now -+ * Overridden FEATURE_ENABLE_DFS_BYPASS is enabled now -+ * Overridden FEATURE_POWER_GATING_PIPE_IN_TILE is enabled now -+ * Overridden FEATURE_USE_PPLIB is enabled now -+ * Overridden FEATURE_DISABLE_LPT_SUPPORT is enabled now -+ * Overridden FEATURE_DUMMY_FBC_BACKEND is enabled now */ -+enum bool_param_shift { -+ DAL_PARAM_MAXIMIZE_STUTTER_MARKS = 0, -+ DAL_PARAM_LIGHT_SLEEP, -+ DAL_PARAM_MAXIMIZE_URGENCY_WATERMARKS, -+ DAL_PARAM_USE_MAX_DISPLAY_CLK, -+ DAL_PARAM_ENABLE_DFS_BYPASS, -+ DAL_PARAM_POWER_GATING_PIPE_IN_TILE, -+ DAL_PARAM_POWER_GATING_LB_PORTION, -+ DAL_PARAM_PSR_ENABLE, -+ DAL_PARAM_VARI_BRIGHT_ENABLE, -+ DAL_PARAM_USE_PPLIB, -+ DAL_PARAM_DISABLE_LPT_SUPPORT, -+ DAL_PARAM_DUMMY_FBC_BACKEND, -+ DAL_PARAM_ENABLE_GPU_SCALING, -+ DAL_BOOL_PARAM_MAX -+}; -+ -+/* array index for integer override parameters*/ -+enum int_param_array_index { -+ DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS = 0, -+ DAL_PARAM_DRR_SUPPORT, -+ DAL_INT_PARAM_MAX -+}; -+ -+struct dal_override_parameters { -+ uint32_t bool_param_enable_mask; -+ uint32_t bool_param_values; -+ uint32_t int_param_values[DAL_INT_PARAM_MAX]; -+}; -+ -+ -+struct dal_init_data { -+ struct hw_asic_id asic_id; -+ struct view_port_alignment vp_alignment; -+ struct bdf_info bdf_info; -+ struct dal_override_parameters display_param; -+ void *driver; /* ctx */ -+ void *cgs_device; -+}; -+ -+struct dal_dc_init_data { -+ struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ -+ struct adapter_service *adapter_srv; -+}; -+ -+struct dal_dev_c_lut { -+ uint8_t red; -+ uint8_t green; -+ uint8_t blue; -+ uint8_t reserved; -+}; -+ -+struct dal_dev_gamma_lut { -+ uint16_t red; -+ uint16_t green; -+ uint16_t blue; -+}; -+ -+struct dc_context { -+ struct dc *dc; -+ -+ void *driver_context; /* e.g. amdgpu_device */ -+ -+ struct dal_logger *logger; -+ void *cgs_device; -+}; -+ -+/* Wireless display structs */ -+ -+union dal_remote_display_cea_mode_bitmap { -+ struct { -+ uint32_t CEA_640X480_60P:1;/*0*/ -+ uint32_t CEA_720X480_60P:1;/*1*/ -+ uint32_t CEA_720X480_60I:1;/*2*/ -+ uint32_t CEA_720X576_50P:1;/*3*/ -+ uint32_t CEA_720X576_50I:1;/*4*/ -+ uint32_t CEA_1280X720_30P:1;/*5*/ -+ uint32_t CEA_1280X720_60P:1;/*6*/ -+ uint32_t CEA_1920X1080_30P:1;/*7*/ -+ uint32_t CEA_1920X1080_60P:1;/*8*/ -+ uint32_t CEA_1920X1080_60I:1;/*9*/ -+ uint32_t CEA_1280X720_25P:1;/*10*/ -+ uint32_t CEA_1280X728_50P:1;/*11*/ -+ uint32_t CEA_1920X1080_25P:1;/*12*/ -+ uint32_t CEA_1920X1080_50P:1;/*13*/ -+ uint32_t CEA_1920X1080_50I:1;/*14*/ -+ uint32_t CEA_1280X1024_24P:1;/*15*/ -+ uint32_t CEA_1920X1080_24P:1;/*16*/ -+ uint32_t RESERVED:15;/*[17-31]*/ -+ } flags; -+ uint32_t raw; -+}; -+ -+union dal_remote_display_vesa_mode_bitmap { -+ struct { -+ uint32_t VESA_800X600_30P:1;/*0*/ -+ uint32_t VESA_800X600_60P:1;/*1*/ -+ uint32_t VESA_1024X768_30P:1;/*2*/ -+ uint32_t VESA_1024X768_60P:1;/*3*/ -+ uint32_t VESA_1152X864_30P:1;/*4*/ -+ uint32_t VESA_1152X864_60P:1;/*5*/ -+ uint32_t VESA_1280X768_30P:1;/*6*/ -+ uint32_t VESA_1280X768_60P:1;/*7*/ -+ uint32_t VESA_1280X800_30P:1;/*8*/ -+ uint32_t VESA_1280X800_60P:1;/*9*/ -+ uint32_t VESA_1360X768_30P:1;/*10*/ -+ uint32_t VESA_1360X768_60P:1;/*11*/ -+ uint32_t VESA_1366X768_30P:1;/*12*/ -+ uint32_t VESA_1366X768_60P:1;/*13*/ -+ uint32_t VESA_1280X1024_30P:1;/*14*/ -+ uint32_t VESA_1280X1024_60P:1;/*15*/ -+ uint32_t VESA_1400X1050_30P:1;/*16*/ -+ uint32_t VESA_1400X1050_60P:1;/*17*/ -+ uint32_t VESA_1440X900_30P:1;/*18*/ -+ uint32_t VESA_1440X900_60P:1;/*19*/ -+ uint32_t VESA_1600X900_30P:1;/*20*/ -+ uint32_t VESA_1600X900_60P:1;/*21*/ -+ uint32_t VESA_1600X1200_30P:1;/*22*/ -+ uint32_t VESA_1600X1200_60P:1;/*23*/ -+ uint32_t VESA_1680X1024_30P:1;/*24*/ -+ uint32_t VESA_1680X1024_60P:1;/*25*/ -+ uint32_t VESA_1680X1050_30P:1;/*26*/ -+ uint32_t VESA_1680X1050_60P:1;/*27*/ -+ uint32_t VESA_1920X1200_30P:1;/*28*/ -+ uint32_t VESA_1920X1200_60P:1;/*29*/ -+ uint32_t RESERVED:2;/*[30-31]*/ -+ } flags; -+ uint32_t raw; -+}; -+ -+union dal_remote_display_hh_mode_bitmap { -+ struct { -+ uint32_t HH_800X480_30P:1;/*0*/ -+ uint32_t HH_800X480_60P:1;/*1*/ -+ uint32_t HH_854X480_30P:1;/*2*/ -+ uint32_t HH_854X480_60P:1;/*3*/ -+ uint32_t HH_864X480_30P:1;/*4*/ -+ uint32_t HH_864X480_60P:1;/*5*/ -+ uint32_t HH_640X360_30P:1;/*6*/ -+ uint32_t HH_640X360_60P:1;/*7*/ -+ uint32_t HH_960X540_30P:1;/*8*/ -+ uint32_t HH_960X540_60P:1;/*9*/ -+ uint32_t HH_848X480_30P:1;/*10*/ -+ uint32_t HH_848X480_60P:1;/*11*/ -+ uint32_t RESERVED:20;/*[12-31]*/ -+ } flags; -+ uint32_t raw; -+}; -+ -+union dal_remote_display_stereo_3d_mode_bitmap { -+ struct { -+ uint32_t STEREO_1920X1080_24P_TOP_AND_BOTTOM:1;/*0*/ -+ uint32_t STEREO_1280X720_60P_TOP_AND_BOTTOM:1;/*1*/ -+ uint32_t STEREO_1280X720_50P_TOP_AND_BOTTOM:1;/*2*/ -+ uint32_t STEREO_1920X1080_24X2P_FRAME_ALTERNATE:1;/*3*/ -+ uint32_t STEREO_1280X720_60X2P_FRAME_ALTERNATE:1;/*4*/ -+ uint32_t STEREO_1280X720_30X2P_FRAME_ALTERNATE:1;/*5*/ -+ uint32_t STEREO_1280X720_50X2P_FRAME_ALTERNATE:1;/*6*/ -+ uint32_t STEREO_1280X720_25X2P_FRAME_ALTERNATE:1;/*7*/ -+ uint32_t STEREO_1920X1080_24P_FRAME_PACKING:1;/* 8*/ -+ uint32_t STEREO_1280X720_60P_FRAME_PACKING:1;/* 9*/ -+ uint32_t STEREO_1280X720_30P_FRAME_PACKING:1;/*10*/ -+ uint32_t STEREO_1280X720_50P_FRAME_PACKING:1;/*11*/ -+ uint32_t STEREO_1280X720_25P_FRAME_PACKING:1;/*12*/ -+ uint32_t RESERVED:19; /*[13-31]*/ -+ } flags; -+ uint32_t raw; -+}; -+ -+union dal_remote_display_audio_bitmap { -+ struct { -+ uint32_t LPCM_44100HZ_16BITS_2_CHANNELS:1;/*0*/ -+ uint32_t LPCM_48000HZ_16BITS_2_CHANNELS:1;/*1*/ -+ uint32_t AAC_48000HZ_16BITS_2_CHANNELS:1;/*2*/ -+ uint32_t AAC_48000HZ_16BITS_4_CHANNELS:1;/*3*/ -+ uint32_t AAC_48000HZ_16BITS_6_CHANNELS:1;/*4*/ -+ uint32_t AAC_48000HZ_16BITS_8_CHANNELS:1;/*5*/ -+ uint32_t AC3_48000HZ_16BITS_2_CHANNELS:1;/*6*/ -+ uint32_t AC3_48000HZ_16BITS_4_CHANNELS:1;/*7*/ -+ uint32_t AC3_48000HZ_16BITS_6_CHANNELS:1;/*8*/ -+ uint32_t RESERVED:23;/*[9-31]*/ -+ } flags; -+ uint32_t raw; -+}; -+ -+struct dal_remote_display_receiver_capability { -+ union dal_remote_display_cea_mode_bitmap cea_mode; -+ union dal_remote_display_vesa_mode_bitmap vesa_mode; -+ union dal_remote_display_hh_mode_bitmap hh_mode; -+ union dal_remote_display_stereo_3d_mode_bitmap stereo_3d_mode; -+ union dal_remote_display_audio_bitmap audio; -+}; -+ -+#endif /* __DAL_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h -new file mode 100644 -index 0000000..b7fb9ff ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h -@@ -0,0 +1,77 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DC_CLOCK_GENERATOR_INTERFACE_H__ -+#define __DC_CLOCK_GENERATOR_INTERFACE_H__ -+ -+#include "grph_object_ctrl_defs.h" -+#include "set_mode_types.h" -+ -+/* Parameter for programming the DCCP_DISP_SLOW_SELECT*/ -+struct dccg_mapping_params { -+ uint32_t controllers_num; -+ enum controller_id *controllers; -+}; -+ -+/* Parameters related to HW DeSpread of DP Reference Clock*/ -+struct dccg_dp_ref_clk_ds_params { -+ struct { -+ /* Flag for Enabled SS on DP Reference Clock*/ -+ bool SS_ENABLED:1; -+ /* Flag for HW De Spread enabled -+ * (if enabled SS on DP Reference Clock)*/ -+ bool DS_ENABLED:1; -+ /* Flag for HW De Spread Calculations enabled for DS_DTO_INCR -+ * and DS_DTO_MODULO (if 0 SW programs DS_DTO_INCR and -+ * DS_DTO_MODULO)*/ -+ bool DS_CALCULATIONS:1; -+ } flags; -+ /*DP Reference clock SS percentage -+ * (if enabled downspread on DP Reference Clock)*/ -+ uint32_t ss_percentage; -+ /*DP Reference clock SS percentage Divider (1000 or 100)*/ -+ uint32_t ss_percentage_divider; -+}; -+ -+struct dc_clock_generator; -+ -+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc); -+void dal_dc_clock_generator_set_display_pipe_mapping( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_mapping_params *params); -+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params( -+ struct dc_clock_generator *dc_clk_gen, -+ struct dccg_dp_ref_clk_ds_params *params); -+bool dal_dc_clock_generator_enable_gtc_counter( -+ struct dc_clock_generator *dc_clk_gen, -+ uint32_t dprefclk); -+void dal_dc_clock_generator_disable_gtc_counter( -+ struct dc_clock_generator *dc_clk_gen); -+void dal_dc_clock_generator_set_gtc_group_offset( -+ struct dc_clock_generator *dc_clk_gen, -+ enum gtc_group group_num, -+ uint32_t offset); -+ -+#endif /* __DC_CLOCK_GENERATOR_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dcs_interface.h b/drivers/gpu/drm/amd/dal/include/dcs_interface.h -new file mode 100644 -index 0000000..b3474cf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dcs_interface.h -@@ -0,0 +1,351 @@ -+/* Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_DCS_INTERFACE_H__ -+#define __DAL_DCS_INTERFACE_H__ -+ -+#include "dcs_types.h" -+#include "grph_object_id.h" -+ -+struct dal_context; -+struct dcs; -+struct ddc_service; -+enum ddc_transaction_type; -+enum ddc_result; -+struct display_sink_capability; -+enum dc_timing_3d_format; -+ -+struct dcs_cea_audio_mode_list; -+struct dcs_customized_mode_list; -+ -+struct dcs_init_data { -+ struct dal_context *dal; -+ struct adapter_service *as; -+ struct timing_service *ts; -+ enum dcs_interface_type interface_type; -+ struct graphics_object_id grph_obj_id; -+}; -+ -+struct dcs_cea_audio_mode_list *dal_dcs_cea_audio_mode_list_create( -+ uint32_t list_size); -+ -+void dal_dcs_cea_audio_mode_list_destroy( -+ struct dcs_cea_audio_mode_list **list); -+ -+bool dal_dcs_cea_audio_mode_list_append( -+ struct dcs_cea_audio_mode_list *list, -+ struct cea_audio_mode *cea_audio_mode); -+uint32_t dal_dcs_cea_audio_mode_list_get_count( -+ const struct dcs_cea_audio_mode_list *list); -+void dal_dcs_cea_audio_mode_list_clear( -+ struct dcs_cea_audio_mode_list *list); -+ -+struct cea_audio_mode *dal_dcs_cea_audio_mode_list_at_index( -+ const struct dcs_cea_audio_mode_list *list, -+ uint32_t index); -+ -+struct dcs *dal_dcs_create(const struct dcs_init_data *init_data); -+ -+void dal_dcs_destroy(struct dcs **dcs); -+ -+enum edid_retrieve_status dal_dcs_retrieve_raw_edid(struct dcs *dcs); -+ -+uint32_t dal_dcs_get_edid_raw_data_size(struct dcs *dcs); -+ -+enum edid_retrieve_status dal_dcs_override_raw_edid( -+ struct dcs *dcs, -+ uint32_t len, -+ uint8_t *data); -+ -+const uint8_t *dal_dcs_get_edid_raw_data( -+ struct dcs *dcs, -+ uint32_t *buff_size); -+ -+enum edid_retrieve_status dal_dcs_update_edid_from_last_retrieved( -+ struct dcs *dcs); -+ -+/*Update DDC Service. returns the old DdcService being replaced*/ -+struct ddc_service *dal_dcs_update_ddc( -+ struct dcs *dcs, -+ struct ddc_service *ddc); -+ -+void dal_dcs_set_transaction_type( -+ struct dcs *dcs, -+ enum ddc_transaction_type type); -+ -+/*updates the ModeTimingList of given path with -+ModeTiming reported by this DCS*/ -+void dal_dcs_update_ts_timing_list_on_display( -+ struct dcs *dcs, -+ uint32_t display_index); -+ -+/* DDC query on generic slave address*/ -+bool dal_dcs_query_ddc_data( -+ struct dcs *dcs, -+ uint32_t address, -+ uint8_t *write_buf, -+ uint32_t write_buff_size, -+ uint8_t *read_buff, -+ uint32_t read_buff_size); -+ -+bool dal_dcs_get_vendor_product_id_info( -+ struct dcs *dcs, -+ struct vendor_product_id_info *info); -+ -+bool dal_dcs_get_display_name(struct dcs *dcs, uint8_t *name, uint32_t size); -+ -+bool dal_dcs_get_display_characteristics( -+ struct dcs *dcs, -+ struct display_characteristics *characteristics); -+ -+bool dal_dcs_get_screen_info( -+ struct dcs *dcs, -+ struct edid_screen_info *info); -+ -+enum dcs_edid_connector_type dal_dcs_get_connector_type(struct dcs *dcs); -+ -+bool dal_dcs_get_display_pixel_encoding( -+ struct dcs *dcs, -+ struct display_pixel_encoding_support *pe); -+ -+enum display_dongle_type dal_dcs_get_dongle_type(struct dcs *dcs); -+ -+void dal_dcs_query_sink_capability( -+ struct dcs *dcs, -+ struct display_sink_capability *sink_cap, -+ bool hpd_sense_bit); -+ -+void dal_dcs_reset_sink_capability(struct dcs *dcs); -+ -+bool dal_dcs_get_sink_capability( -+ struct dcs *dcs, -+ struct display_sink_capability *sink_cap); -+ -+bool dal_dcs_emulate_sink_capability( -+ struct dcs *dcs, -+ struct display_sink_capability *sink_cap); -+ -+bool dal_dcs_get_display_color_depth( -+ struct dcs *dcs, -+ struct display_color_depth_support *color_depth); -+ -+bool dal_dcs_get_display_pixel_encoding( -+ struct dcs *dcs, -+ struct display_pixel_encoding_support *pixel_encoding); -+ -+bool dal_dcs_get_cea861_support( -+ struct dcs *dcs, -+ struct cea861_support *cea861_support); -+ -+bool dal_dcs_get_cea_vendor_specific_data_block( -+ struct dcs *dcs, -+ struct cea_vendor_specific_data_block *vendor_block); -+ -+bool dal_dcs_get_cea_speaker_allocation_data_block( -+ struct dcs *dcs, -+ enum signal_type signal, -+ union cea_speaker_allocation_data_block *spkr_data); -+ -+bool dal_dcs_get_cea_colorimetry_data_block( -+ struct dcs *dcs, -+ struct cea_colorimetry_data_block *colorimetry_data_block); -+ -+bool dal_dcs_get_cea_video_capability_data_block( -+ struct dcs *dcs, -+ union cea_video_capability_data_block *video_capability_data_block); -+ -+uint32_t dal_dcs_get_extensions_num(struct dcs *dcs); -+ -+const struct dcs_cea_audio_mode_list *dal_dcs_get_cea_audio_modes( -+ struct dcs *dcs, -+ enum signal_type signal); -+ -+bool dal_dcs_is_audio_supported(struct dcs *dcs); -+ -+bool dal_dcs_validate_customized_mode( -+ struct dcs *dcs, -+ const struct dcs_customized_mode *customized_mode); -+ -+bool dal_dcs_add_customized_mode( -+ struct dcs *dcs, -+ struct dcs_customized_mode *customized_mode); -+ -+bool dal_dcs_delete_customized_mode(struct dcs *dcs, uint32_t index); -+ -+const struct dcs_customized_mode_list *dal_dcs_get_customized_modes( -+ struct dcs *dcs); -+ -+bool dal_dcs_delete_mode_timing_override( -+ struct dcs *dcs, -+ struct dcs_override_mode_timing *dcs_mode_timing); -+ -+bool dal_dcs_set_mode_timing_override( -+ struct dcs *dcs, -+ uint32_t display_index, -+ struct dcs_override_mode_timing *dcs_mode_timing); -+ -+bool dal_dcs_get_timing_override_for_mode( -+ struct dcs *dcs, -+ uint32_t display_index, -+ struct dc_mode_info *mode_info, -+ struct dcs_override_mode_timing_list *dcs_mode_timing_list); -+ -+uint32_t dal_dcs_get_num_mode_timing_overrides(struct dcs *dcs); -+ -+bool dal_dcs_get_timing_override_list( -+ struct dcs *dcs, -+ uint32_t display_index, -+ struct dcs_override_mode_timing_list *dcs_mode_timing_list, -+ uint32_t size); -+ -+bool dal_dcs_get_supported_force_hdtv_mode( -+ struct dcs *dcs, -+ union hdtv_mode_support *hdtv_mode); -+ -+bool dal_dcs_get_user_force_hdtv_mode( -+ struct dcs *dcs, -+ union hdtv_mode_support *hdtv_mode); -+ -+bool dal_dcs_set_user_force_hdtv_mode( -+ struct dcs *dcs, -+ const union hdtv_mode_support *hdtv_mode); -+ -+bool dal_dcs_get_fid9204_allow_ce_mode_only_option( -+ struct dcs *dcs, -+ bool is_hdmi, -+ bool *enable); -+ -+bool dal_dcs_set_fid9204_allow_ce_mode_only_option( -+ struct dcs *dcs, -+ bool is_hdmi, -+ bool enable); -+ -+bool dal_dcs_get_panel_misc_info( -+ struct dcs *dcs, -+ union panel_misc_info *panel_info); -+ -+enum ddc_result dal_dcs_dpcd_read( -+ struct dcs *dcs, -+ uint32_t address, -+ uint8_t *buffer, -+ uint32_t length); -+ -+enum ddc_result dal_dcs_dpcd_write( -+ struct dcs *dcs, -+ uint32_t address, -+ const uint8_t *buffer, -+ uint32_t length); -+ -+bool dal_dcs_get_range_limit( -+ struct dcs *dcs, -+ struct display_range_limits *limit); -+ -+bool dal_dcs_set_range_limit_override( -+ struct dcs *dcs, -+ struct display_range_limits *limit); -+ -+bool dal_dcs_get_user_select_limit( -+ struct dcs *dcs, -+ struct monitor_user_select_limits *limit); -+ -+bool dal_dcs_set_user_select_limit( -+ struct dcs *dcs, -+ struct monitor_user_select_limits *limit); -+ -+bool dal_dcs_get_dongle_mode_support( -+ struct dcs *dcs, -+ union hdtv_mode_support *hdtv_mode); -+ -+bool dal_dcs_get_timing_limits( -+ struct dcs *dcs, -+ struct timing_limits *timing_limits); -+ -+bool dal_dcs_get_drr_config( -+ struct dcs *dcs, -+ struct drr_config *config); -+ -+bool dal_dcs_force_dp_audio(struct dcs *dcs, bool force_audio_on); -+ -+bool dal_dcs_is_dp_audio_forced(struct dcs *dcs); -+ -+const struct monitor_patch_info *dal_dcs_get_monitor_patch_info( -+ struct dcs *dcs, -+ enum monitor_patch_type patch_type); -+ -+bool dal_dcs_set_monitor_patch_info( -+ struct dcs *dcs, -+ struct monitor_patch_info *patch_info); -+ -+union dcs_monitor_patch_flags dal_dcs_get_monitor_patch_flags(struct dcs *dcs); -+ -+enum dcs_packed_pixel_format dal_dcs_get_enabled_packed_pixel_format( -+ struct dcs *dcs); -+ -+enum dcs_packed_pixel_format dal_dcs_get_monitor_packed_pixel_format( -+ struct dcs *dcs); -+ -+bool dal_dcs_report_single_selected_timing(struct dcs *dcs); -+ -+bool dal_dcs_can_tile_scale(struct dcs *dcs); -+ -+void dal_dcs_set_single_selected_timing_restriction( -+ struct dcs *dcs, -+ bool value); -+ -+const struct dcs_edid_supported_max_bw *dal_dcs_get_edid_supported_max_bw( -+ struct dcs *dcs); -+ -+bool dal_dcs_is_non_continous_frequency(struct dcs *dcs); -+ -+struct dcs_stereo_3d_features dal_dcs_get_stereo_3d_features( -+ struct dcs *dcs, -+ enum dc_timing_3d_format format); -+ -+union stereo_3d_support dal_dcs_get_stereo_3d_support(struct dcs *dcs); -+ -+void dal_dcs_override_stereo_3d_support( -+ struct dcs *dcs, -+ union stereo_3d_support support); -+ -+void dal_dcs_set_remote_display_receiver_capabilities( -+ struct dcs *dcs, -+ const struct dal_remote_display_receiver_capability *cap); -+ -+void dal_dcs_clear_remote_display_receiver_capabilities(struct dcs *dcs); -+ -+bool dal_dcs_get_display_tile_info( -+ struct dcs *dcs, -+ struct dcs_display_tile *display_tile, -+ bool first_display); -+ -+bool dal_dcs_get_container_id(struct dcs *dcs, -+ struct dcs_container_id *container_id); -+ -+bool dal_dcs_set_container_id(struct dcs *dcs, -+ struct dcs_container_id *container_id); -+ -+void dal_dcs_invalidate_container_id(struct dcs *dcs); -+ -+union dcs_monitor_patch_flags dal_dcs_get_monitor_patch_flags(struct dcs *dcs); -+ -+#endif /* __DAL_DCS_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dcs_types.h b/drivers/gpu/drm/amd/dal/include/dcs_types.h -new file mode 100644 -index 0000000..8c65057 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dcs_types.h -@@ -0,0 +1,742 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DCS_TYPES_H__ -+#define __DAL_DCS_TYPES_H__ -+ -+#include "signal_types.h" -+ -+#include "dc_types.h" -+ -+#define NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS 10 -+#define MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT 21 -+#define MAX_NUMBER_OF_HDMI_VSDB_VICS 7 -+ -+struct drr_config { -+ /* minimum frame per second for dynamic -+ * refresh rate feature; 0 if drr support not found*/ -+ uint32_t min_fps_in_microhz; -+ bool force_lock_on_event; -+ bool lock_to_master_vsync; -+ -+ struct { -+ uint8_t FORCED_BY_REGKEY_OR_ESCAPE:1; -+ uint8_t FORCED_BY_VBIOS:1; -+ uint8_t SUPPORTED_BY_EDID:1; -+ } support_method; -+}; -+ -+struct timing_limits { -+ uint32_t min_pixel_clock_in_khz; -+ uint32_t max_pixel_clock_in_khz; -+}; -+ -+struct vendor_product_id_info { -+ uint32_t manufacturer_id; -+ uint32_t product_id; -+ uint32_t serial_id; -+ uint32_t manufacture_week; -+ uint32_t manufacture_year; -+}; -+ -+struct display_range_limits { -+ uint32_t min_v_rate_hz; -+ uint32_t max_v_rate_hz; -+ uint32_t min_h_rate_khz; -+ uint32_t max_h_rateIn_khz; -+ uint32_t max_pix_clk_khz; -+ bool use_override; -+}; -+ -+struct monitor_user_select_limits { -+ bool use_ati_override; -+ uint32_t max_h_res; -+ uint32_t max_v_res; -+ uint32_t max_refresh_rate; -+}; -+ -+enum edid_screen_aspect_ratio { -+ EDID_SCREEN_AR_UNKNOWN = 0, -+ EDID_SCREEN_AR_PROJECTOR, -+ EDID_SCREEN_AR_16X9, -+ EDID_SCREEN_AR_16X10, -+ EDID_SCREEN_AR_4X3, -+ EDID_SCREEN_AR_5X4, -+ EDID_SCREEN_AR_9X16, -+ EDID_SCREEN_AR_10X16, -+ EDID_SCREEN_AR_3X4, -+ EDID_SCREEN_AR_4X5 -+}; -+ -+struct edid_screen_info { -+ enum edid_screen_aspect_ratio aspect_ratio; -+ uint32_t width; -+ uint32_t height; -+}; -+ -+struct display_characteristics { -+ uint8_t gamma; -+ uint8_t color_characteristics[NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS]; -+}; -+ -+union cv_smart_dongle_modes { -+ uint8_t all; -+ struct cv_smart_dongle_switches { -+ uint8_t MODE_1080I:1; -+ uint8_t MODE_720P:1; -+ uint8_t MODE_540P:1; -+ uint8_t MODE_480P:1; -+ uint8_t MODE_480I:1; -+ uint8_t MODE_16_9:1; -+ } switches; -+}; -+ -+struct cea_audio_mode { -+ uint8_t format_code; /* ucData[0] [6:3]*/ -+ uint8_t channel_count; /* ucData[0] [2:0]*/ -+ uint8_t sample_rate; /* ucData[1]*/ -+ union { -+ uint8_t sample_size; /* for LPCM*/ -+ /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/ -+ uint8_t max_bit_rate; -+ uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/ -+ }; -+}; -+ -+union cea_speaker_allocation_data_block { -+ struct { -+ uint32_t FL_FR:1; -+ uint32_t LFE:1; -+ uint32_t FC:1; -+ uint32_t RL_RR:1; -+ uint32_t RC:1; -+ uint32_t FLC_FRC:1; -+ uint32_t RLC_RRC:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+struct cea_colorimetry_data_block { -+ struct { -+ uint32_t XV_YCC601:1; -+ uint32_t XV_YCC709:1; -+ uint32_t S_YCC601:1; -+ uint32_t ADOBE_YCC601:1; -+ uint32_t ADOBE_RGB:1; -+ -+ } flag; -+ struct { -+ uint32_t MD0:1; -+ uint32_t MD1:1; -+ uint32_t MD2:1; -+ uint32_t MD3:1; -+ } metadata_flag; -+}; -+ -+union cea_video_capability_data_block { -+ struct { -+ uint8_t S_CE0:1; -+ uint8_t S_CE1:1; -+ uint8_t S_IT0:1; -+ uint8_t S_IT1:1; -+ uint8_t S_PT0:1; -+ uint8_t S_PT1:1; -+ uint8_t QS:1; -+ uint8_t QY:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+enum stereo_3d_multi_presence { -+ STEREO_3D_MULTI_NOT_PRESENT = 0, -+ STEREO_3D_MULTI_ALL_FORMATS, -+ STEREO_3D_MULTI_MASKED_FORMATS, -+ STEREO_3D_MULTI_RESERVED -+}; -+ -+enum cea_hdmi_vic { -+ CEA_HDMI_VIC_RESERVED = 0, -+ CEA_HDMI_VIC_4KX2K_30, -+ CEA_HDMI_VIC_4KX2K_25, -+ CEA_HDMI_VIC_4KX2K_24, -+ CEA_HDMI_VIC_4KX2K_24_SMPTE -+}; -+ -+struct cea_hdmi_vsdb_extended_caps { -+ uint32_t reserved; -+ uint32_t image_size; -+ enum stereo_3d_multi_presence stereo_3d_multi_present; -+ bool stereo_3d_present; -+ uint32_t hdmi_3d_len; -+ uint32_t hdmi_vic_len; -+}; -+ -+struct cea_vendor_specific_data_block { -+ -+ uint32_t ieee_id; -+ -+ struct commonent_phy { -+ uint32_t PHY_ADDR_A:4; -+ uint32_t PHY_ADDR_B:4; -+ uint32_t PHY_ADDR_C:4; -+ uint32_t PHY_ADDR_D:4; -+ } commonent_phy_addr; -+ -+ struct byte6 { -+ uint32_t SUPPORTS_AI:1; -+ uint32_t DC_48BIT:1; -+ uint32_t DC_36BIT:1; -+ uint32_t DC_30BIT:1; -+ uint32_t DC_Y444:1; -+ uint32_t DVI_DUAL:1; -+ uint32_t RESERVED:2; -+ } byte6;/* link capabilities*/ -+ bool byte6_valid; -+ -+ uint32_t max_tmds_clk_mhz; -+ -+ struct byte8 { -+ uint32_t LATENCY_FIELDS_PRESENT:1; -+ uint32_t ILATENCY_FIELDS_PRESENT:1; -+ uint32_t HDMI_VIDEO_PRESENT:1; -+ uint32_t RESERVED:1; -+ uint32_t CNC3_GAME:1; -+ uint32_t CNC2_CINEMA:1; -+ uint32_t CNC1_PHOTO:1; -+ uint32_t CNC0_GRAPHICS:1; -+ } byte8; -+ /*bit 6-7: latency flags to indicate valid latency fields*/ -+ /*bit 5: support of additional video format capabilities*/ -+ /* bit 0-3: flags indicating which content type is supported*/ -+ uint32_t video_latency; -+ uint32_t audio_latency; -+ uint32_t i_video_latency; -+ uint32_t i_audio_latency; -+ -+ struct cea_hdmi_vsdb_extended_caps hdmi_vsdb_extended_caps; -+ -+ enum stereo_3d_multi_presence stereo_3d_multi_present; -+ -+ struct { -+ bool FRAME_PACKING:1; -+ bool SIDE_BY_SIDE_HALF:1; -+ bool TOP_AND_BOTTOM:1; -+ } stereo_3d_all_support; -+ uint16_t stereo_3d_mask; -+ -+ enum cea_hdmi_vic hdmi_vic[MAX_NUMBER_OF_HDMI_VSDB_VICS]; -+ struct stereo_3d_extended_support { -+ struct { -+ bool FRAME_PACKING:1; -+ bool SIDE_BY_SIDE_HALF:1; -+ bool TOP_AND_BOTTOM:1; -+ } format; -+ uint32_t vic_index; -+ uint32_t value; -+ uint32_t size; -+ } stereo_3d_extended_support[MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT]; -+}; -+ -+struct cea861_support { -+ -+ uint32_t revision; -+ union { -+ struct { -+ uint32_t NATIVE_COUNT:4; -+ uint32_t BASE_AUDIO:1; -+ uint32_t YCRCB444:1; -+ uint32_t YCRCB422:1; -+ uint32_t UNDER_SCAN:1; -+ } features; -+ uint8_t raw_features; -+ }; -+}; -+ -+struct dcs_customized_mode { -+ struct { -+ uint32_t READ_ONLY:1; -+ uint32_t ADD_BY_DRIVER:1; -+ uint32_t INTERLACED:1; -+ uint32_t BASE_MODE:1; -+ } flags; -+ struct dc_mode_info base_mode_info; -+ struct dc_mode_info customized_mode_info; -+}; -+ -+struct dcs_override_mode_timing { -+ /* possible timing standards, bit vector of TimingStandard*/ -+ uint32_t possible_timing_standards; -+ /* indicate driver default timing is used , no override*/ -+ bool use_driver_default_timing; -+ struct dc_mode_timing mode_timing; -+}; -+ -+struct dcs_override_mode_timing_list { -+ uint32_t max_num_overrides; -+ uint32_t num_overrides; -+ struct dcs_override_mode_timing mode_timings[1]; -+}; -+ -+/* "interface type" is different from Signal Type because -+ * an "interface type" can be driven by more than one Signal Type. -+ * For example, INTERFACE_TYPE_DVI can be driven by -+ * Single or Dual link DVI signal. */ -+enum dcs_interface_type { -+ INTERFACE_TYPE_VGA = 0, -+ INTERFACE_TYPE_DVI, -+ INTERFACE_TYPE_CV, -+ INTERFACE_TYPE_TV, -+ INTERFACE_TYPE_LVDS, -+ INTERFACE_TYPE_DP, -+ INTERFACE_TYPE_WIRELESS, -+ INTERFACE_TYPE_CF, -+ INTERFACE_TYPE_EDP -+}; -+ -+ -+union panel_misc_info { -+ struct { -+ uint32_t H_CUT_OFF:1; -+ uint32_t H_SYNC_POLARITY:1;/*0=Active High, 1=Active Low*/ -+ uint32_t V_SYNC_POLARITY:1; /*0=Active High, 1=Active Low*/ -+ uint32_t V_CUT_OFF:1; -+ uint32_t H_REPLICATION_BY_2:1; -+ uint32_t V_REPLICATION_BY_2:1; -+ uint32_t COMPOSITE_SYNC:1; -+ uint32_t INTERLACE:1; -+ uint32_t DOUBLE_CLOCK:1; -+ uint32_t RGB888:1; -+ uint32_t GREY_LEVEL:2; -+ uint32_t SPATIAL:1; -+ uint32_t TEMPORAL:1; -+ uint32_t API_ENABLED:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+union hdtv_mode_support { -+ struct { -+ uint32_t HDTV_SUPPORT_480I:1; -+ uint32_t HDTV_SUPPORT_480P:1; -+ uint32_t HDTV_SUPPORT_576I25:1; -+ uint32_t HDTV_SUPPORT_576P50:1; -+ uint32_t HDTV_SUPPORT_720P:1; -+ uint32_t HDTV_SUPPORT_720P50:1; -+ uint32_t HDTV_SUPPORT_1080I:1; -+ uint32_t HDTV_SUPPORT_1080I25:1; -+ uint32_t HDTV_SUPPORT_1080P:1; -+ uint32_t HDTV_SUPPORT_1080P50:1; -+ uint32_t HDTV_SUPPORT_1080P24:1; -+ uint32_t HDTV_SUPPORT_1080P25:1; -+ uint32_t HDTV_SUPPORT_1080P30:1; -+ uint32_t HDTV_SUPPORT_16X9:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+enum edid_retrieve_status { -+ EDID_RETRIEVE_SUCCESS = 0, -+ EDID_RETRIEVE_FAIL, -+ EDID_RETRIEVE_SAME_EDID, -+ EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS -+}; -+ -+#define DCS_DECODE_EDID_RETRIEVE_STATUS(status) \ -+ (status == EDID_RETRIEVE_SUCCESS) ? "EDID_RETRIEVE_SUCCESS" : \ -+ (status == EDID_RETRIEVE_FAIL) ? "EDID_RETRIEVE_FAIL" : \ -+ (status == EDID_RETRIEVE_SAME_EDID) ? "EDID_RETRIEVE_SAME_EDID" : \ -+ (status == EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS) ? \ -+ "EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS" : "Unknown" -+ -+ -+#ifndef TV_SIGNALFORMAT_DEFINED -+#define TV_SIGNALFORMAT_DEFINED -+enum tv_signal_format { -+ TV_SIGNAL_FORMAT_UNKNOWN, -+ TV_SIGNAL_FORMAT_NTSC, -+ TV_SIGNAL_FORMAT_NTSC_J, -+ TV_SIGNAL_FORMAT_PAL, -+ TV_SIGNAL_FORMAT_PAL_M, -+ TV_SIGNAL_FORMAT_PAL_CN, -+ TV_SIGNAL_FORMAT_SECAM -+}; -+#endif -+ -+enum tv_signal_format_result { -+ TV_SIGNAL_FORMAT_RESULT_OK, -+ TV_SIGNAL_FORMAT_SET_MODE_REQ, -+ TV_SIGNAL_FORMAT_REBOOT_REQ, -+ TV_SIGNAL_FORMAT_ERROR -+}; -+ -+enum pixel_encoding_mask { -+ PIXEL_ENCODING_MASK_YCBCR444 = 0x01, -+ PIXEL_ENCODING_MASK_YCBCR422 = 0x02, -+ PIXEL_ENCODING_MASK_RGB = 0x04, -+}; -+ -+struct display_pixel_encoding_support { -+ uint32_t mask; -+}; -+ -+enum color_depth_index { -+ COLOR_DEPTH_INDEX_UNKNOWN, -+ COLOR_DEPTH_INDEX_666 = 0x01, -+ COLOR_DEPTH_INDEX_888 = 0x02, -+ COLOR_DEPTH_INDEX_101010 = 0x04, -+ COLOR_DEPTH_INDEX_121212 = 0x08, -+ COLOR_DEPTH_INDEX_141414 = 0x10, -+ COLOR_DEPTH_INDEX_161616 = 0x20, -+ COLOR_DEPTH_INDEX_LAST = 0x40, -+}; -+ -+struct display_color_depth_support { -+ uint32_t mask; -+ bool deep_color_native_res_only; -+}; -+ -+struct display_color_and_pixel_support { -+ struct display_color_depth_support color_depth_support; -+ struct display_pixel_encoding_support pixel_encoding_support; -+ bool deep_color_y444_support; -+}; -+ -+enum dcs_packed_pixel_format { -+ DCS_PACKED_PIXEL_FORMAT_NOT_PACKED = 0, -+ DCS_PACKED_PIXEL_FORMAT_SPLIT_G70_B54_R70_B10 = 1, -+ DCS_PACKED_PIXEL_FORMAT_R70_G76 = 2, -+ DCS_PACKED_PIXEL_FORMAT_SPLIT_B70_G10_R70_G76 = 3, -+ DCS_PACKED_PIXEL_FORMAT_G70_B54_R70_B10 = 4, -+ DCS_PACKED_PIXEL_FORMAT_G70_B54 = 5, -+ DCS_PACKED_PIXEL_FORMAT_B70_R30_G70_R74 = 6, -+ DCS_PACKED_PIXEL_FORMAT_B70_G70_R70 = 7, -+ DCS_PACKED_PIXEL_FORMAT_B70_R32_G70_R76 = 8, -+}; -+ -+enum monitor_manufacturer_id { -+ MONITOR_MANUFACTURER_ID_0 = 0x0000, -+ MONITOR_MANUFACTURER_ID_1 = 0x3834, -+ MONITOR_MANUFACTURER_ID_2 = 0x4d24, -+ MONITOR_MANUFACTURER_ID_3 = 0x293E, -+ MONITOR_MANUFACTURER_ID_4 = 0x635a, -+ MONITOR_MANUFACTURER_ID_5 = 0x1006, -+ MONITOR_MANUFACTURER_ID_6 = 0xc32a, -+ MONITOR_MANUFACTURER_ID_7 = 0x4d24, -+ MONITOR_MANUFACTURER_ID_8 = 0x110e, -+ MONITOR_MANUFACTURER_ID_9 = 0xaf0d, -+ MONITOR_MANUFACTURER_ID_10 = 0x6D1E, -+ MONITOR_MANUFACTURER_ID_11 = 0xA338, -+ MONITOR_MANUFACTURER_ID_12 = 0xC315, -+ MONITOR_MANUFACTURER_ID_13 = 0xD94D, -+ MONITOR_MANUFACTURER_ID_14 = 0x104D, -+ MONITOR_MANUFACTURER_ID_15 = 0x855C, -+ MONITOR_MANUFACTURER_ID_16 = 0x4251, -+ MONITOR_MANUFACTURER_ID_17 = 0xA934, -+ MONITOR_MANUFACTURER_ID_18 = 0x0C41, -+ /* TODO: Update when EDID is available */ -+ MONITOR_MANUFACTURER_ID_19 = 0xDEAD, -+ MONITOR_MANUFACTURER_ID_20 = 0x6904, -+ MONITOR_MANUFACTURER_ID_21 = 0xAC10, -+ MONITOR_MANUFACTURER_ID_22 = 0x2D4C, -+ MONITOR_MANUFACTURER_ID_23 = 0x144E, -+ MONITOR_MANUFACTURER_ID_24 = 0x6c50, -+ MONITOR_MANUFACTURER_ID_26 = 0x0c41, -+ MONITOR_MANUFACTURER_ID_27 = 0x143E, -+ MONITOR_MANUFACTURER_ID_25 = 0xffff, -+ MONITOR_MANUFACTURER_ID_28 = 0x3421, -+ MONITOR_MANUFACTURER_ID_29 = 0x2D19, -+ MONITOR_MANUFACTURER_ID_30 = 0x8B52, -+ MONITOR_MANUFACTURER_ID_31 = 0x7204, -+ MONITOR_MANUFACTURER_ID_32 = 0xF022, -+ MONITOR_MANUFACTURER_ID_33 = 0x0E11, -+ MONITOR_MANUFACTURER_ID_34 = 0xD241, -+ MONITOR_MANUFACTURER_ID_35 = 0xAE30, -+ MONITOR_MANUFACTURER_ID_36 = 0xF91E, -+ MONITOR_MANUFACTURER_ID_37 = 0xAB4C, -+}; -+ -+enum monitor_product_id { -+ MONITOR_PRODUCT_ID_0 = 0x0000, -+ MONITOR_PRODUCT_ID_1 = 0x0BCC, -+ MONITOR_PRODUCT_ID_2 = 0x251F, -+ MONITOR_PRODUCT_ID_3 = 0x5241, -+ MONITOR_PRODUCT_ID_4 = 0x6919, -+ MONITOR_PRODUCT_ID_5 = 0xee18, -+ MONITOR_PRODUCT_ID_6 = 0xf008, -+ MONITOR_PRODUCT_ID_7 = 0x2f0c, -+ MONITOR_PRODUCT_ID_7_2 = 0x3411, -+ MONITOR_PRODUCT_ID_9 = 0x4208, -+ MONITOR_PRODUCT_ID_10 = 0xE51D, -+ MONITOR_PRODUCT_ID_11 = 0x7E22, -+ MONITOR_PRODUCT_ID_12 = 0x0E23, -+ MONITOR_PRODUCT_ID_13 = 0x9d08, -+ MONITOR_PRODUCT_ID_14 = 0x9236, -+ MONITOR_PRODUCT_ID_15 = 0x9227, -+ MONITOR_PRODUCT_ID_16 = 0x0220, -+ MONITOR_PRODUCT_ID_17 = 0x4920, -+ MONITOR_PRODUCT_ID_18 = 0x251f, -+ MONITOR_PRODUCT_ID_19 = 0x1395, -+ MONITOR_PRODUCT_ID_20 = 0xc04e, -+ MONITOR_PRODUCT_ID_21 = 0x5787, -+ MONITOR_PRODUCT_ID_22 = 0x5A71, -+ MONITOR_PRODUCT_ID_23 = 0x6622, -+ MONITOR_PRODUCT_ID_24 = 0x20C1, -+ MONITOR_PRODUCT_ID_25 = 0x2110, -+ MONITOR_PRODUCT_ID_26 = 0x2006, -+ MONITOR_PRODUCT_ID_27 = 0x1827, -+ MONITOR_PRODUCT_ID_28 = 0x0EA0, -+ MONITOR_PRODUCT_ID_29 = 0x03D0, -+ MONITOR_PRODUCT_ID_30 = 0x01D2, -+ MONITOR_PRODUCT_ID_31 = 0x2801, -+ MONITOR_PRODUCT_ID_32 = 0x0FB3, -+ MONITOR_PRODUCT_ID_33 = 0x0FB1, -+ MONITOR_PRODUCT_ID_34 = 0xA045, -+ MONITOR_PRODUCT_ID_35 = 0x0001, -+ MONITOR_PRODUCT_ID_36 = 0xA296, -+ MONITOR_PRODUCT_ID_38 = 0x21DC, -+ MONITOR_PRODUCT_ID_37 = 0x21EA, -+ MONITOR_PRODUCT_ID_39 = 0x4093, -+ MONITOR_PRODUCT_ID_40 = 0x4094, -+ MONITOR_PRODUCT_ID_41 = 0x4094, -+ MONITOR_PRODUCT_ID_42 = 0x32A2, -+ MONITOR_PRODUCT_ID_43 = 0xE009, -+ MONITOR_PRODUCT_ID_44 = 0xA010, -+ MONITOR_PRODUCT_ID_45 = 0x405C, -+ MONITOR_PRODUCT_ID_46 = 0xF017, -+ MONITOR_PRODUCT_ID_47 = 0xD026, -+ MONITOR_PRODUCT_ID_48 = 0x4036, -+ MONITOR_PRODUCT_ID_49 = 0x4065, -+ MONITOR_PRODUCT_ID_50 = 0xA02A, -+ MONITOR_PRODUCT_ID_51 = 0xA02C, -+ MONITOR_PRODUCT_ID_46_HDMI = 0xF016, -+ MONITOR_PRODUCT_ID_53 = 0xF048, -+ MONITOR_PRODUCT_ID_54 = 0xA0A2, -+ MONITOR_PRODUCT_ID_55 = 0x4083, -+ MONITOR_PRODUCT_ID_56 = 0x0E74, -+ MONITOR_PRODUCT_ID_57 = 0x2771, -+ MONITOR_PRODUCT_ID_58 = 0x0814, -+ MONITOR_PRODUCT_ID_59 = 0xffff, -+ MONITOR_PRODUCT_ID_60 = 0x3339, -+ MONITOR_PRODUCT_ID_61 = 0x01F5, -+ MONITOR_PRODUCT_ID_62 = 0x02A5, -+ MONITOR_PRODUCT_ID_63 = 0x06AC, -+ MONITOR_PRODUCT_ID_64 = 0x04D5, -+ MONITOR_PRODUCT_ID_65 = 0x079D, -+ MONITOR_PRODUCT_ID_66 = 0x079F, -+ MONITOR_PRODUCT_ID_67 = 0x0797, -+ MONITOR_PRODUCT_ID_68 = 0x0B80, -+ MONITOR_PRODUCT_ID_69 = 0x7D06, -+ MONITOR_PRODUCT_ID_70 = 0x0131, -+ MONITOR_PRODUCT_ID_71 = 0x8545, -+ MONITOR_PRODUCT_ID_72 = 0x0002, -+ MONITOR_PRODUCT_ID_73 = 0x0125, -+ MONITOR_PRODUCT_ID_74 = 0x00D0, -+ MONITOR_PRODUCT_ID_75 = 0x26F7, -+ MONITOR_PRODUCT_ID_76 = 0x26F9, -+ MONITOR_PRODUCT_ID_77 = 0x2807, -+ MONITOR_PRODUCT_ID_78 = 0x26F3, -+ MONITOR_PRODUCT_ID_79 = 0x2676, -+ MONITOR_PRODUCT_ID_80 = 0x0A72, -+ MONITOR_PRODUCT_ID_81 = 0x2693, -+ MONITOR_PRODUCT_ID_82 = 0x2615, -+ MONITOR_PRODUCT_ID_83 = 0x2613, -+ MONITOR_PRODUCT_ID_84 = 0x262D, -+ MONITOR_PRODUCT_ID_85 = 0x264B, -+ MONITOR_PRODUCT_ID_86 = 0x2869, -+ MONITOR_PRODUCT_ID_87 = 0x286C, -+ MONITOR_PRODUCT_ID_88 = 0x288F, -+ MONITOR_PRODUCT_ID_89 = 0x2954, -+ MONITOR_PRODUCT_ID_90 = 0x6522, -+ MONITOR_PRODUCT_ID_91 = 0x0FAE, -+ MONITOR_PRODUCT_ID_92 = 0x0A0C, -+ MONITOR_PRODUCT_ID_93 = 0x00BF, -+ MONITOR_PRODUCT_ID_94 = 0x0, -+}; -+ -+enum monitor_patch_type { -+ MONITOR_PATCH_TYPE_NONE, -+ MONITOR_PATCH_TYPE_ERROR_CHECKSUM, -+ MONITOR_PATCH_TYPE_HDTV_WITH_PURE_DFP_EDID, -+ MONITOR_PATCH_TYPE_DO_NOT_USE_DETAILED_TIMING, -+ MONITOR_PATCH_TYPE_DO_NOT_USE_RANGE_LIMITATION, -+ MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECK_SUM, -+ MONITOR_PATCH_TYPE_TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE, -+ MONITOR_PATCH_TYPE_RESTRICT_VESA_MODE_TIMING, -+ MONITOR_PATCH_TYPE_DO_NOT_USE_EDID_MAX_PIX_CLK, -+ MONITOR_PATCH_TYPE_VENDOR_0, -+ MONITOR_PATCH_TYPE_RANDOM_CRT, -+ MONITOR_PATCH_TYPE_VENDOR_1, -+ MONITOR_PATCH_TYPE_LIMIT_PANEL_SUPPORT_RGB_ONLY, -+ MONITOR_PATCH_TYPE_PACKED_PIXEL_FORMAT, -+ MONITOR_PATCH_TYPE_LARGE_PANEL, -+ MONITOR_PATCH_TYPE_STEREO_SUPPORT, -+ /* 0 (default) - mean patch will not be applied, however it can be -+ * explicitly set to 1 -+ */ -+ MONITOR_PATCH_TYPE_DUAL_EDID_PANEL, -+ MONITOR_PATCH_TYPE_IGNORE_19X12_STD_TIMING, -+ MONITOR_PATCH_TYPE_MULTIPLE_PACKED_TYPE, -+ MONITOR_PATCH_TYPE_RESET_TX_ON_DISPLAY_POWER_ON, -+ MONITOR_PATCH_TYPE_VENDOR_2, -+ MONITOR_PATCH_TYPE_RESTRICT_PROT_DUAL_LINK_DVI, -+ MONITOR_PATCH_TYPE_FORCE_LINK_RATE, -+ MONITOR_PATCH_TYPE_DELAY_AFTER_DP_RECEIVER_POWER_UP, -+ MONITOR_PATCH_TYPE_KEEP_DP_RECEIVER_POWERED, -+ MONITOR_PATCH_TYPE_DELAY_BEFORE_READ_EDID, -+ MONITOR_PATCH_TYPE_DELAY_AFTER_PIXEL_FORMAT_CHANGE, -+ MONITOR_PATCH_TYPE_INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX, -+ MONITOR_PATCH_TYPE_NO_DEFAULT_TIMINGS, -+ MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC16, -+ MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC31, -+ MONITOR_PATCH_TYPE_DELAY_BEFORE_UNMUTE, -+ MONITOR_PATCH_TYPE_RETRY_LINK_TRAINING_ON_FAILURE, -+ MONITOR_PATCH_TYPE_ALLOW_AUX_WHEN_HPD_LOW, -+ MONITOR_PATCH_TYPE_TILED_DISPLAY, -+ MONITOR_PATCH_TYPE_DISABLE_PSR_ENTRY_ABORT, -+ MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECKSUM, -+ MONITOR_PATCH_TYPE_ALLOW_ONLY_CE_MODE, -+ MONITOR_PATCH_TYPE_VID_STREAM_DIFFER_TO_SYNC, -+ MONITOR_PATCH_TYPE_EXTRA_DELAY_ON_DISCONNECT, -+ MONITOR_PATCH_TYPE_DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS, -+ MONITOR_PATCH_TYPE_SINGLE_MODE_PACKED_PIXEL -+}; -+ -+/* Single entry in the monitor table */ -+struct monitor_patch_info { -+ enum monitor_manufacturer_id manufacturer_id; -+ enum monitor_product_id product_id; -+ enum monitor_patch_type type; -+ uint32_t param; -+}; -+ -+union dcs_monitor_patch_flags { -+ struct { -+ bool ERROR_CHECKSUM:1; -+ bool HDTV_WITH_PURE_DFP_EDID:1; -+ bool DO_NOT_USE_DETAILED_TIMING:1; -+ bool DO_NOT_USE_RANGE_LIMITATION:1; -+ bool EDID_EXTENTION_ERROR_CHECKSUM:1; -+ bool TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE:1; -+ bool RESTRICT_VESA_MODE_TIMING:1; -+ bool DO_NOT_USE_EDID_MAX_PIX_CLK:1; -+ bool VENDOR_0:1; -+ bool RANDOM_CRT:1;/* 10 bits used including this one-*/ -+ bool VENDOR_1:1; -+ bool LIMIT_PANEL_SUPPORT_RGB_ONLY:1; -+ bool PACKED_PIXEL_FORMAT:1; -+ bool LARGE_PANEL:1; -+ bool STEREO_SUPPORT:1; -+ bool DUAL_EDID_PANEL:1; -+ bool IGNORE_19X12_STD_TIMING:1; -+ bool MULTIPLE_PACKED_TYPE:1; -+ bool RESET_TX_ON_DISPLAY_POWER_ON:1; -+ bool ALLOW_ONLY_CE_MODE:1;/* 20 bits used including this one*/ -+ bool RESTRICT_PROT_DUAL_LINK_DVI:1; -+ bool FORCE_LINK_RATE:1; -+ bool DELAY_AFTER_DP_RECEIVER_POWER_UP:1; -+ bool KEEP_DP_RECEIVER_POWERED:1; -+ bool DELAY_BEFORE_READ_EDID:1; -+ bool DELAY_AFTER_PIXEL_FORMAT_CHANGE:1; -+ bool INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX:1; -+ bool NO_DEFAULT_TIMINGS:1; -+ bool ADD_CEA861_DETAILED_TIMING_VIC16:1; -+ bool ADD_CEA861_DETAILED_TIMING_VIC31:1; /* 30 bits*/ -+ bool DELAY_BEFORE_UNMUTE:1; -+ bool RETRY_LINK_TRAINING_ON_FAILURE:1; -+ bool ALLOW_AUX_WHEN_HPD_LOW:1; -+ bool TILED_DISPLAY:1; -+ bool DISABLE_PSR_ENTRY_ABORT:1; -+ bool INTERMITTENT_EDID_ERROR:1;/* 36 bits total*/ -+ bool VID_STREAM_DIFFER_TO_SYNC:1;/* 37 bits total*/ -+ bool EXTRA_DELAY_ON_DISCONNECT:1;/* 38 bits total*/ -+ bool DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS:1;/* 39 bits total*/ -+ } flags; -+ uint64_t raw; -+}; -+ -+struct dcs_edid_supported_max_bw { -+ uint32_t pix_clock_khz; -+ uint32_t bits_per_pixel; -+}; -+ -+struct dcs_stereo_3d_features { -+ struct { -+/* 3D Format supported by monitor (implies supported by driver)*/ -+ uint32_t SUPPORTED:1; -+/* 3D Format supported on all timings -+(no need to check every timing for 3D support)*/ -+ uint32_t ALL_TIMINGS:1; -+/* 3D Format supported in clone mode*/ -+ uint32_t CLONE_MODE:1; -+/* Scaling allowed when driving 3D Format*/ -+ uint32_t SCALING:1; -+/* Left and right images packed by SW within single frame*/ -+ uint32_t SINGLE_FRAME_SW_PACKED:1; -+ } flags; -+}; -+ -+struct dcs_container_id { -+ /*128bit GUID in binary form*/ -+ uint8_t guid[16]; -+ /* 8 byte port ID -> ELD.PortID*/ -+ uint32_t port_id[2]; -+ /* 2 byte manufacturer name -> ELD.ManufacturerName*/ -+ uint16_t manufacturer_name; -+ /* 2 byte product code -> ELD.ProductCode*/ -+ uint16_t product_code; -+}; -+ -+struct dcs_display_tile { -+/*unique Id of Tiled Display. 0 - means display is not part in Tiled Display*/ -+ uint64_t id; -+ uint32_t rows;/* size of Tiled Display in tiles*/ -+ uint32_t cols;/* size of Tiled Display in tiles*/ -+ uint32_t width;/* size of current Tile in pixels*/ -+ uint32_t height;/* size of current Tile in pixels*/ -+ uint32_t row;/* location of current Tile*/ -+ uint32_t col;/* location of current Tile*/ -+ struct { -+ /*in pixels*/ -+ uint32_t left; -+ uint32_t right; -+ uint32_t top; -+ uint32_t bottom; -+ } bezel;/* bezel information of current tile*/ -+ -+ struct { -+ uint32_t SEPARATE_ENCLOSURE:1; -+ uint32_t BEZEL_INFO_PRESENT:1; -+ uint32_t CAN_SCALE:1; -+ } flags; -+ -+ struct { -+ uint32_t manufacturer_id; -+ uint32_t product_id; -+ uint32_t serial_id; -+ } topology_id; -+}; -+ -+#endif /* __DAL_DCS_TYPES_H__ */ -+ -diff --git a/drivers/gpu/drm/amd/dal/include/ddc_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_interface.h -new file mode 100644 -index 0000000..22fd31f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/ddc_interface.h -@@ -0,0 +1,74 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DDC_INTERFACE_H__ -+#define __DAL_DDC_INTERFACE_H__ -+ -+#include "gpio_types.h" -+ -+struct ddc; -+ -+enum gpio_result dal_ddc_open( -+ struct ddc *ddc, -+ enum gpio_mode mode, -+ enum gpio_ddc_config_type config_type); -+ -+enum gpio_result dal_ddc_get_clock( -+ const struct ddc *ddc, -+ uint32_t *value); -+ -+enum gpio_result dal_ddc_set_clock( -+ const struct ddc *ddc, -+ uint32_t value); -+ -+enum gpio_result dal_ddc_get_data( -+ const struct ddc *ddc, -+ uint32_t *value); -+ -+enum gpio_result dal_ddc_set_data( -+ const struct ddc *ddc, -+ uint32_t value); -+ -+enum gpio_result dal_ddc_change_mode( -+ struct ddc *ddc, -+ enum gpio_mode mode); -+ -+bool dal_ddc_is_hw_supported( -+ const struct ddc *ddc); -+ -+enum gpio_ddc_line dal_ddc_get_line( -+ const struct ddc *ddc); -+ -+bool dal_ddc_check_line_aborted( -+ const struct ddc *ddc); -+ -+enum gpio_result dal_ddc_set_config( -+ struct ddc *ddc, -+ enum gpio_ddc_config_type config_type); -+ -+void dal_ddc_close( -+ struct ddc *ddc); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h -new file mode 100644 -index 0000000..ca3e6ce ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h -@@ -0,0 +1,100 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+#ifndef __DAL_DDC_SERVICE_INTERFACE_H__ -+#define __DAL_DDC_SERVICE_INTERFACE_H__ -+ -+#include "ddc_service_types.h" -+ -+struct ddc_service; -+struct adapter_service; -+struct graphics_object_id; -+enum ddc_result; -+struct av_sync_data; -+struct dp_receiver_id_info; -+ -+struct ddc_service_init_data { -+ struct adapter_service *as; -+ struct graphics_object_id id; -+ struct dc_context *ctx; -+}; -+struct ddc_service *dal_ddc_service_create( -+ struct ddc_service_init_data *ddc_init_data); -+ -+void dal_ddc_service_destroy(struct ddc_service **ddc); -+ -+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc); -+ -+void dal_ddc_service_set_transaction_type( -+ struct ddc_service *ddc, -+ enum ddc_transaction_type type); -+ -+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); -+ -+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); -+ -+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); -+ -+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); -+ -+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( -+ struct ddc_service *ddc, -+ struct display_sink_capability *sink_cap); -+ -+bool dal_ddc_service_query_ddc_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ uint8_t *write_buf, -+ uint32_t write_size, -+ uint8_t *read_buf, -+ uint32_t read_size); -+ -+bool dal_ddc_service_get_dp_receiver_id_info( -+ struct ddc_service *ddc, -+ struct dp_receiver_id_info *info); -+ -+enum ddc_result dal_ddc_service_read_dpcd_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t len); -+ -+enum ddc_result dal_ddc_service_write_dpcd_data( -+ struct ddc_service *ddc, -+ uint32_t address, -+ const uint8_t *data, -+ uint32_t len); -+ -+void dal_ddc_service_write_scdc_data( -+ struct ddc_service *ddc_service, -+ uint32_t pix_clk, -+ bool lte_340_scramble); -+ -+void dal_ddc_service_read_scdc_data( -+ struct ddc_service *ddc_service); -+ -+void ddc_service_set_dongle_type(struct ddc_service *ddc, -+ enum display_dongle_type dongle_type); -+ -+#endif /* __DAL_DDC_SERVICE_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h -new file mode 100644 -index 0000000..47ad2ed ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h -@@ -0,0 +1,220 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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__ -+ -+#include "include/hw_sequencer_types.h" -+ -+#define DP_BRANCH_DEVICE_ID_1 0x0010FA -+#define DP_BRANCH_DEVICE_ID_2 0x0022B9 -+#define DP_SINK_DEVICE_ID_1 0x4CE000 -+#define DP_BRANCH_DEVICE_ID_3 0x00001A -+#define DP_BRANCH_DEVICE_ID_4 0x0080e1 -+#define DP_BRANCH_DEVICE_ID_5 0x006037 -+#define DP_SINK_DEVICE_ID_2 0x001CF8 -+ -+ -+enum ddc_result { -+ DDC_RESULT_UNKNOWN = 0, -+ DDC_RESULT_SUCESSFULL, -+ DDC_RESULT_FAILED_CHANNEL_BUSY, -+ DDC_RESULT_FAILED_TIMEOUT, -+ DDC_RESULT_FAILED_PROTOCOL_ERROR, -+ DDC_RESULT_FAILED_NACK, -+ DDC_RESULT_FAILED_INCOMPLETE, -+ DDC_RESULT_FAILED_OPERATION, -+ DDC_RESULT_FAILED_INVALID_OPERATION, -+ DDC_RESULT_FAILED_BUFFER_OVERFLOW -+}; -+ -+enum ddc_service_type { -+ DDC_SERVICE_TYPE_CONNECTOR, -+ DDC_SERVICE_TYPE_DISPLAY_PORT_MST, -+}; -+ -+enum ddc_transaction_type { -+ DDC_TRANSACTION_TYPE_NONE = 0, -+ DDC_TRANSACTION_TYPE_I2C, -+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX, -+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER, -+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER -+}; -+ -+enum display_dongle_type { -+ DISPLAY_DONGLE_NONE = 0, -+ /* Active converter types*/ -+ DISPLAY_DONGLE_DP_VGA_CONVERTER, -+ DISPLAY_DONGLE_DP_DVI_CONVERTER, -+ DISPLAY_DONGLE_DP_HDMI_CONVERTER, -+ /* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/ -+ DISPLAY_DONGLE_DP_DVI_DONGLE, -+ DISPLAY_DONGLE_DP_HDMI_DONGLE, -+ /* Other types of dongle*/ -+ DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE, -+}; -+ -+enum dcs_dpcd_revision { -+ DCS_DPCD_REV_10 = 0x10, -+ DCS_DPCD_REV_11 = 0x11, -+ DCS_DPCD_REV_12 = 0x12 -+}; -+ -+/** -+ * display sink capability -+ */ -+struct display_sink_capability { -+ /* dongle type (DP converter, CV smart dongle) */ -+ enum display_dongle_type dongle_type; -+ -+ /********************************************************** -+ capabilities going INTO SINK DEVICE (stream capabilities) -+ **********************************************************/ -+ /* Dongle's downstream count. */ -+ uint32_t downstrm_sink_count; -+ /* Is dongle's downstream count info field (downstrm_sink_count) -+ * valid. */ -+ bool downstrm_sink_count_valid; -+ -+ /* Maximum additional audio delay in microsecond (us) */ -+ uint32_t additional_audio_delay; -+ /* Audio latency value in microsecond (us) */ -+ uint32_t audio_latency; -+ /* Interlace video latency value in microsecond (us) */ -+ uint32_t video_latency_interlace; -+ /* Progressive video latency value in microsecond (us) */ -+ uint32_t video_latency_progressive; -+ /* Dongle caps: Maximum pixel clock supported over dongle for HDMI */ -+ uint32_t max_hdmi_pixel_clock; -+ /* Dongle caps: Maximum deep color supported over dongle for HDMI */ -+ enum dc_color_depth max_hdmi_deep_color; -+ -+ /************************************************************ -+ capabilities going OUT OF SOURCE DEVICE (link capabilities) -+ ************************************************************/ -+ /* support for Spread Spectrum(SS) */ -+ bool ss_supported; -+ /* DP link settings (laneCount, linkRate, Spread) */ -+ uint32_t dp_link_lane_count; -+ uint32_t dp_link_rate; -+ uint32_t dp_link_spead; -+ -+ enum dcs_dpcd_revision dpcd_revision; -+ /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, -+ indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ -+ bool is_dp_hdmi_s3d_converter; -+ /* to check if we have queried the display capability -+ * for eDP panel already. */ -+ bool is_edp_sink_cap_valid; -+}; -+ -+struct dp_receiver_id_info { -+ uint32_t dpcd_rev; -+ uint32_t sink_id; -+ int8_t sink_id_str[6]; -+ int8_t sink_hw_revision; -+ int8_t sink_fw_revision[2]; -+ uint32_t branch_id; -+ int8_t branch_name[6]; -+ enum display_dongle_type dongle_type; -+}; -+ -+struct av_sync_data { -+ uint8_t av_granularity;/* DPCD 00023h */ -+ uint8_t aud_dec_lat1;/* DPCD 00024h */ -+ uint8_t aud_dec_lat2;/* DPCD 00025h */ -+ uint8_t aud_pp_lat1;/* DPCD 00026h */ -+ uint8_t aud_pp_lat2;/* DPCD 00027h */ -+ uint8_t vid_inter_lat;/* DPCD 00028h */ -+ uint8_t vid_prog_lat;/* DPCD 00029h */ -+ uint8_t aud_del_ins1;/* DPCD 0002Bh */ -+ uint8_t aud_del_ins2;/* DPCD 0002Ch */ -+ uint8_t aud_del_ins3;/* DPCD 0002Dh */ -+}; -+ -+/** EDID retrieval related constants, also used by MstMgr **/ -+ -+#define DDC_EDID_SEGMENT_SIZE 256 -+#define DDC_EDID_BLOCK_SIZE 128 -+#define DDC_EDID_BLOCKS_PER_SEGMENT \ -+ (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) -+ -+#define DDC_EDID_EXT_COUNT_OFFSET 0x7E -+ -+#define DDC_EDID_ADDRESS_START 0x50 -+#define DDC_EDID_ADDRESS_END 0x52 -+#define DDC_EDID_SEGMENT_ADDRESS 0x30 -+ -+/* signatures for Edid 1x */ -+#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 -+#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 -+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 -+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 -+#define DDC_EDID1X_CHECKSUM_OFFSET 127 -+/* signatures for Edid 20*/ -+#define DDC_EDID_20_SIGNATURE_OFFSET 0 -+#define DDC_EDID_20_SIGNATURE 0x20 -+ -+#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 -+#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 -+#define DDC_EDID20_CHECKSUM_OFFSET 255 -+#define DDC_EDID20_CHECKSUM_LEN 1 -+ -+/*DP to VGA converter*/ -+static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; -+/*DP to Dual link DVI converter*/ -+static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa"; -+/*Travis*/ -+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; -+/*Nutmeg*/ -+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; -+/*DP to VGA converter*/ -+static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga"; -+/*DP to Dual link DVI converter*/ -+static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa"; -+/*DP to Dual link DVI converter 2*/ -+static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa"; -+ -+static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0"; -+ -+/* Identifies second generation PSR TCON from Parade: Device ID string: -+ * yy-xx-**-**-**-** -+ */ -+/* xx - Hw ID high byte */ -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE = -+ 0x06; -+ -+/* yy - HW ID low byte, the same silicon has several package/feature flavors */ -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 = -+ 0x61; -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 = -+ 0x62; -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 = -+ 0x63; -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 = -+ 0x72; -+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 = -+ 0x73; -+ -+#endif /* __DAL_DDC_SERVICE_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/default_mode_list_interface.h b/drivers/gpu/drm/amd/dal/include/default_mode_list_interface.h -new file mode 100644 -index 0000000..35a5695 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/default_mode_list_interface.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_DEFAULT_MODE_LIST_INTERFACE_H__ -+#define __DAL_DEFAULT_MODE_LIST_INTERFACE_H__ -+ -+struct default_mode_list; -+ -+uint32_t dal_default_mode_list_get_count(const struct default_mode_list *dml); -+ -+struct dc_mode_info *dal_default_mode_list_get_mode_info_at_index( -+ const struct default_mode_list *dml, -+ uint32_t index); -+ -+#endif /*__DAL_DEFAULT_MODE_LIST_INTERFACE_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h -new file mode 100644 -index 0000000..2f48b8a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/display_clock_interface.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 __DISPLAY_CLOCK_INTERFACE_H__ -+#define __DISPLAY_CLOCK_INTERFACE_H__ -+ -+#include "hw_sequencer_types.h" -+#include "grph_object_defs.h" -+#include "signal_types.h" -+#include "scaler_types.h" -+ -+/* Timing related information*/ -+struct dc_timing_params { -+ uint32_t INTERLACED:1; -+ uint32_t HCOUNT_BY_TWO:1; -+ uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/ -+ uint32_t PREFETCH:1; -+ -+ uint32_t h_total; -+ uint32_t h_addressable; -+ uint32_t h_sync_width; -+}; -+ -+/* Scaling related information*/ -+struct dc_scaling_params { -+ uint32_t h_overscan_right; -+ uint32_t h_overscan_left; -+ uint32_t h_taps; -+ uint32_t v_taps; -+}; -+ -+/*Display Request Mode (1 and 2 valid when scaler is OFF)*/ -+enum display_request_mode { -+ REQUEST_ONLY_AT_EVERY_READ_POINTER_INCREMENT = 0, -+ REQUEST_WAITING_FOR_THE_FIRST_READ_POINTER_ONLY, -+ REQUEST_WITHOUT_WAITING_FOR_READ_POINTER -+}; -+ -+/* FBC minimum CompressionRatio*/ -+enum fbc_compression_ratio { -+ FBC_COMPRESSION_NOT_USED = 0, -+ FBC_MINIMUM_COMPRESSION_RATIO_1 = 1, -+ FBC_MINIMUM_COMPRESSION_RATIO_2 = 2, -+ FBC_MINIMUM_COMPRESSION_RATIO_4 = 4, -+ FBC_MINIMUM_COMPRESSION_RATIO_8 = 8 -+}; -+ -+/* VScalerEfficiency */ -+enum v_scaler_efficiency { -+ V_SCALER_EFFICIENCY_LB36BPP = 0, -+ V_SCALER_EFFICIENCY_LB30BPP = 1, -+ V_SCALER_EFFICIENCY_LB24BPP = 2, -+ V_SCALER_EFFICIENCY_LB18BPP = 3 -+}; -+ -+/* Parameters required for minimum Engine -+ * and minimum Display clock calculations*/ -+struct min_clock_params { -+ uint32_t id; -+ uint32_t requested_pixel_clock; /* in KHz */ -+ uint32_t actual_pixel_clock; /* in KHz */ -+ struct view source_view; -+ struct view dest_view; -+ struct dc_timing_params timing_info; -+ struct dc_scaling_params scaling_info; -+ struct color_quality color_info; -+ enum signal_type signal_type; -+ enum dc_color_depth deep_color_depth; -+ enum v_scaler_efficiency scaler_efficiency; -+ bool line_buffer_prefetch_enabled; -+}; -+ -+/* Enumerations for Source selection of the Display clock */ -+enum display_clock_source_select { -+ USE_PIXEL_CLOCK_PLL = 0, -+ USE_EXTERNAL_CLOCK, -+ USE_ENGINE_CLOCK -+}; -+ -+/* Result of Minimum System and Display clock calculations. -+ * Minimum System clock and Display clock, source and path to be used -+ * for Display clock*/ -+struct minimum_clocks_calculation_result { -+ uint32_t min_sclk_khz; -+ uint32_t min_dclk_khz; -+ uint32_t min_mclk_khz; -+ uint32_t min_deep_sleep_sclk; -+}; -+ -+/* Enumeration of all clocks states */ -+enum clocks_state { -+ CLOCKS_STATE_INVALID, -+ CLOCKS_STATE_ULTRA_LOW, -+ CLOCKS_STATE_LOW, -+ CLOCKS_STATE_NOMINAL, -+ CLOCKS_STATE_PERFORMANCE -+}; -+ -+/* Structure containing all state-dependent clocks -+ * (dependent on "enum clocks_state") */ -+struct state_dependent_clocks { -+ uint32_t display_clk_khz; -+ uint32_t pixel_clk_khz; -+ uint32_t dvo_clk_khz; -+}; -+ -+struct display_clock_state { -+ uint32_t DFS_BYPASS_ACTIVE:1; -+}; -+ -+struct display_clock; -+ -+struct display_clock *dal_display_clock_dce110_create( -+ struct dc_context *ctx, -+ struct adapter_service *as); -+ -+struct display_clock *dal_display_clock_dce80_create( -+ struct dc_context *ctx, -+ struct adapter_service *as); -+ -+void dal_display_clock_destroy(struct display_clock **to_destroy); -+bool dal_display_clock_validate( -+ struct display_clock *disp_clk, -+ struct min_clock_params *params); -+uint32_t dal_display_clock_calculate_min_clock( -+ struct display_clock *disp_clk, -+ uint32_t path_num, -+ struct min_clock_params *params); -+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); -+void dal_display_clock_set_clock( -+ struct display_clock *disp_clk, -+ uint32_t requested_clock_khz); -+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk); -+enum clocks_state dal_display_clock_get_min_clocks_state( -+ struct display_clock *disp_clk); -+enum clocks_state dal_display_clock_get_required_clocks_state( -+ struct display_clock *disp_clk, -+ struct state_dependent_clocks *req_clocks); -+bool dal_display_clock_set_min_clocks_state( -+ struct display_clock *disp_clk, -+ enum clocks_state clocks_state); -+uint32_t dal_display_clock_get_dp_ref_clk_frequency( -+ struct display_clock *disp_clk); -+/*the second parameter of "switchreferenceclock" is -+ * a dummy argument for all pre dce 6.0 versions*/ -+void dal_display_clock_switch_reference_clock( -+ struct display_clock *disp_clk, -+ bool use_external_ref_clk, -+ uint32_t requested_clock_khz); -+void dal_display_clock_set_dp_ref_clock_source( -+ struct display_clock *disp_clk, -+ enum clock_source_id clk_src); -+void dal_display_clock_store_max_clocks_state( -+ struct display_clock *disp_clk, -+ enum clocks_state max_clocks_state); -+void dal_display_clock_set_clock_state( -+ struct display_clock *disp_clk, -+ struct display_clock_state clk_state); -+struct display_clock_state dal_display_clock_get_clock_state( -+ struct display_clock *disp_clk); -+uint32_t dal_display_clock_get_dfs_bypass_threshold( -+ struct display_clock *disp_clk); -+void dal_display_clock_invalid_clock_state( -+ struct display_clock *disp_clk); -+ -+ -+#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/display_path_interface.h b/drivers/gpu/drm/amd/dal/include/display_path_interface.h -new file mode 100644 -index 0000000..7bf2ef2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/display_path_interface.h -@@ -0,0 +1,436 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DISPLAY_PATH_INTERFACE_H__ -+#define __DISPLAY_PATH_INTERFACE_H__ -+ -+#include "display_path_types.h" -+#include "dcs_types.h" -+#include "grph_object_ctrl_defs.h" -+#include "signal_types.h" -+#include "controller_types.h" -+ -+struct encoder; -+struct controller; -+struct connector; -+struct audio; -+struct clock_source; -+struct link_service; -+struct goc_link_service_data; -+struct drr_config; -+ -+struct display_path; -+ -+struct display_path *dal_display_path_create(void); -+ -+struct display_path *dal_display_path_clone( -+ const struct display_path *self, -+ bool copy_active_state); -+ -+void dal_display_path_destroy( -+ struct display_path **to_destroy); -+ -+bool dal_display_path_validate( -+ struct display_path *path, -+ enum signal_type sink_signal); -+ -+bool dal_display_path_add_link( -+ struct display_path *path, -+ struct encoder *encoder); -+ -+bool dal_display_path_add_connector( -+ struct display_path *path, -+ struct connector *connector); -+ -+struct connector *dal_display_path_get_connector( -+ struct display_path *path); -+ -+int32_t dal_display_path_acquire( -+ struct display_path *path); -+ -+bool dal_display_path_is_acquired( -+ const struct display_path *path); -+ -+int32_t dal_display_path_get_ref_counter( -+ const struct display_path *path); -+ -+int32_t dal_display_path_release( -+ struct display_path *path); -+ -+void dal_display_path_release_resources( -+ struct display_path *path); -+ -+void dal_display_path_acquire_links( -+ struct display_path *path); -+ -+bool dal_display_path_is_source_blanked( -+ const struct display_path *path); -+ -+bool dal_display_path_is_source_unblanked( -+ const struct display_path *path); -+ -+void dal_display_path_set_source_blanked( -+ struct display_path *path, -+ enum display_tri_state state); -+ -+bool dal_display_path_is_target_blanked( -+ const struct display_path *path); -+ -+bool dal_display_path_is_target_unblanked( -+ const struct display_path *path); -+ -+void dal_display_path_set_target_blanked( -+ struct display_path *path, -+ enum display_tri_state state); -+ -+bool dal_display_path_is_target_powered_on( -+ const struct display_path *path); -+ -+bool dal_display_path_is_target_powered_off( -+ const struct display_path *path); -+ -+void dal_display_path_set_target_powered_on( -+ struct display_path *path, -+ enum display_tri_state state); -+ -+bool dal_display_path_is_target_connected( -+ const struct display_path *path); -+ -+void dal_display_path_set_target_connected( -+ struct display_path *path, -+ bool c); -+ -+uint32_t dal_display_path_get_display_index( -+ const struct display_path *path); -+ -+void dal_display_path_set_display_index( -+ struct display_path *path, -+ uint32_t index); -+ -+struct connector_device_tag_info *dal_display_path_get_device_tag( -+ struct display_path *path); -+ -+void dal_display_path_set_device_tag( -+ struct display_path *path, -+ struct connector_device_tag_info tag); -+ -+enum clock_sharing_group dal_display_path_get_clock_sharing_group( -+ const struct display_path *path); -+ -+void dal_display_path_set_clock_sharing_group( -+ struct display_path *path, -+ enum clock_sharing_group clock); -+ -+union display_path_properties dal_display_path_get_properties( -+ const struct display_path *path); -+ -+void dal_display_path_set_properties( -+ struct display_path *path, -+ union display_path_properties p); -+ -+struct dcs *dal_display_path_get_dcs( -+ const struct display_path *path); -+ -+void dal_display_path_set_dcs( -+ struct display_path *path, -+ struct dcs *dcs); -+ -+uint32_t dal_display_path_get_number_of_links( -+ const struct display_path *path); -+ -+void dal_display_path_set_controller( -+ struct display_path *path, -+ struct controller *controller); -+ -+struct controller *dal_display_path_get_controller( -+ const struct display_path *path); -+ -+void dal_display_path_set_clock_source( -+ struct display_path *path, -+ struct clock_source *clock); -+ -+struct clock_source *dal_display_path_get_clock_source( -+ const struct display_path *path); -+ -+void dal_display_path_set_alt_clock_source( -+ struct display_path *path, -+ struct clock_source *clock); -+ -+struct clock_source *dal_display_path_get_alt_clock_source( -+ const struct display_path *path); -+ -+void dal_display_path_set_fbc_info( -+ struct display_path *path, -+ struct fbc_info *clock); -+ -+struct fbc_info *dal_display_path_get_fbc_info( -+ struct display_path *path); -+ -+void dal_display_path_set_drr_config( -+ struct display_path *path, -+ struct drr_config *clock); -+ -+void dal_display_path_get_drr_config( -+ const struct display_path *path, -+ struct drr_config *clock); -+ -+void dal_display_path_set_static_screen_triggers( -+ struct display_path *path, -+ const struct static_screen_events *events); -+ -+void dal_display_path_get_static_screen_triggers( -+ const struct display_path *path, -+ struct static_screen_events *events); -+ -+bool dal_display_path_is_psr_supported( -+ const struct display_path *path); -+ -+bool dal_display_path_is_drr_supported( -+ const struct display_path *path); -+ -+void dal_display_path_set_link_service_data( -+ struct display_path *path, -+ uint32_t idx, -+ const struct goc_link_service_data *data); -+ -+bool dal_display_path_get_link_service_data( -+ const struct display_path *path, -+ uint32_t idx, -+ struct goc_link_service_data *data); -+ -+struct link_service *dal_display_path_get_link_query_interface( -+ const struct display_path *path, -+ uint32_t idx); -+ -+void dal_display_path_set_link_query_interface( -+ struct display_path *path, -+ uint32_t idx, -+ struct link_service *link); -+ -+struct link_service *dal_display_path_get_link_config_interface( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct link_service *dal_display_path_get_link_service_interface( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct encoder *dal_display_path_get_upstream_encoder( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct encoder *dal_display_path_get_upstream_object( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct encoder *dal_display_path_get_downstream_encoder( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct encoder *dal_display_path_get_downstream_object( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct audio *dal_display_path_get_audio( -+ const struct display_path *path, -+ uint32_t idx); -+ -+void dal_display_path_set_audio( -+ struct display_path *path, -+ uint32_t idx, -+ struct audio *a); -+ -+struct audio *dal_display_path_get_audio_object( -+ const struct display_path *path, -+ uint32_t idx); -+ -+void dal_display_path_set_audio_active_state( -+ struct display_path *path, -+ uint32_t idx, -+ bool state); -+ -+enum engine_id dal_display_path_get_stream_engine( -+ const struct display_path *path, -+ uint32_t idx); -+ -+void dal_display_path_set_stream_engine( -+ struct display_path *path, -+ uint32_t idx, -+ enum engine_id id); -+ -+bool dal_display_path_is_link_active( -+ const struct display_path *path, -+ uint32_t idx); -+ -+void dal_display_path_set_link_active_state( -+ struct display_path *path, -+ uint32_t idx, -+ bool state); -+ -+enum signal_type dal_display_path_get_config_signal( -+ const struct display_path *path, -+ uint32_t idx); -+ -+enum signal_type dal_display_path_get_query_signal( -+ const struct display_path *path, -+ uint32_t idx); -+ -+struct link_service *dal_display_path_get_mst_link_service( -+ const struct display_path *path); -+ -+void dal_display_path_set_sync_output_object( -+ struct display_path *path, -+ enum sync_source o_source, -+ struct encoder *o_object); -+ -+struct encoder *dal_display_path_get_sync_output_object( -+ const struct display_path *path); -+ -+void dal_display_path_set_stereo_sync_object( -+ struct display_path *path, -+ struct encoder *stereo_sync); -+ -+struct encoder *dal_display_path_get_stereo_sync_object( -+ const struct display_path *path); -+ -+void dal_display_path_set_sync_input_source( -+ struct display_path *path, -+ enum sync_source s); -+ -+enum sync_source dal_display_path_get_sync_input_source( -+ const struct display_path *path); -+ -+void dal_display_path_set_sync_output_source( -+ struct display_path *path, -+ enum sync_source s); -+ -+enum sync_source dal_display_path_get_sync_output_source( -+ const struct display_path *path); -+ -+bool dal_display_path_set_pixel_clock_safe_range( -+ struct display_path *path, -+ struct pixel_clock_safe_range *range); -+ -+bool dal_display_path_get_pixel_clock_safe_range( -+ const struct display_path *path, -+ struct pixel_clock_safe_range *range); -+ -+void dal_display_path_set_ddi_channel_mapping( -+ struct display_path *path, -+ union ddi_channel_mapping mapping); -+ -+bool dal_display_path_set_sink_signal( -+ struct display_path *path, -+ enum signal_type sink_signal); -+ -+enum signal_type dal_display_path_sink_signal_to_asic_signal( -+ struct display_path *path, -+ enum signal_type sink_signal); -+ -+enum signal_type dal_display_path_sink_signal_to_link_signal( -+ struct display_path *path, -+ enum signal_type sink_signal, -+ uint32_t idx); -+ -+enum signal_type dal_display_path_downstream_to_upstream_signal( -+ struct display_path *path, -+ enum signal_type signal, -+ uint32_t idx); -+ -+bool dal_display_path_is_audio_present( -+ const struct display_path *path, -+ uint32_t *audio_pin); -+ -+bool dal_display_path_is_dp_auth_supported( -+ struct display_path *path); -+ -+bool dal_display_path_is_vce_supported( -+ const struct display_path *path); -+ -+bool dal_display_path_is_sls_capable( -+ const struct display_path *path); -+ -+bool dal_display_path_is_gen_lock_capable( -+ const struct display_path *path); -+ -+struct transmitter_configuration dal_display_path_get_transmitter_configuration( -+ const struct display_path *path, -+ bool physical); -+ -+bool dal_display_path_is_ss_supported( -+ const struct display_path *path); -+ -+bool dal_display_path_is_ss_configurable( -+ const struct display_path *path); -+ -+void dal_display_path_set_ss_support( -+ struct display_path *path, -+ bool s); -+ -+enum signal_type dal_display_path_get_active_signal( -+ struct display_path *path, -+ uint32_t idx); -+ -+bool dal_display_path_contains_object( -+ struct display_path *path, -+ struct graphics_object_id id); -+ -+/* Multi-plane declarations. -+ * This structure should also be used for Stereo. */ -+struct display_path_plane { -+ struct controller *controller; -+ /* During dal_tm_acquire_plane_resources() set blnd_mode, because -+ * "layer index" is known at that point, and we must decide how -+ * "controller" should do the blending */ -+ enum blender_mode blnd_mode; -+ /* Some use-cases allow to power-gate FE. -+ * For example, with Full Screen Video on Underlay we can -+ * disable the 'root' plane. -+ * This flag indicates that FE should be power-gated */ -+ bool disabled; -+}; -+ -+bool dal_display_path_add_plane( -+ struct display_path *path, -+ struct display_path_plane *plane); -+ -+uint8_t dal_display_path_get_number_of_planes( -+ const struct display_path *path); -+ -+struct display_path_plane *dal_display_path_get_plane_at_index( -+ const struct display_path *path, -+ uint8_t index); -+ -+struct controller *dal_display_path_get_controller_for_layer_index( -+ const struct display_path *path, -+ uint8_t layer_index); -+ -+void dal_display_path_release_planes( -+ struct display_path *path); -+ -+void dal_display_path_release_non_root_planes( -+ struct display_path *path); -+ -+#endif /* __DISPLAY_PATH_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/display_path_types.h b/drivers/gpu/drm/amd/dal/include/display_path_types.h -new file mode 100644 -index 0000000..8aac46d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/display_path_types.h -@@ -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 -+ * -+ */ -+ -+#ifndef __DAL_DISPLAY_PATH_TYPES_H__ -+#define __DAL_DISPLAY_PATH_TYPES_H__ -+ -+#include "grph_object_defs.h" -+ -+enum { -+ CONTROLLER_HANDLE_INVALID = (uint32_t) (-1) -+}; -+ -+/*Limit maximum number of cofunctional paths*/ -+enum { -+ MAX_COFUNCTIONAL_PATHS = 6 -+}; -+ -+struct pixel_clock_safe_range { -+ uint32_t min_frequency; -+ uint32_t max_frequency; -+}; -+ -+/** -+ * ClockSharingGroup -+ * Enumeration of Clock Source Sharing categories -+ * Instead using enum we define valid range for clock sharing group values -+ * This is because potential num of group can be pretty big -+ */ -+ -+enum clock_sharing_group { -+ /* Default group for display paths that cannot share clock source. -+ * Display path in such group will aqcuire clock source exclusively*/ -+ CLOCK_SHARING_GROUP_EXCLUSIVE = 0, -+ /* DisplayPort paths will have this group if clock sharing -+ * level is DisplayPortShareable*/ -+ CLOCK_SHARING_GROUP_DISPLAY_PORT = 1, -+ /* Mst paths will have this group if clock sharing -+ * level is DpMstShareable*/ -+ CLOCK_SHARING_GROUP_DP_MST = 2, -+ /* Display paths will have this group when -+ * desired to use alternative DPRef clock source.*/ -+ CLOCK_SHARING_GROUP_ALTERNATIVE_DP_REF = 3, -+ /* Start of generic SW sharing groups.*/ -+ CLOCK_SHARING_GROUP_GROUP1 = 4, -+ /* Total number of clock sharing groups.*/ -+ CLOCK_SHARING_GROUP_MAX = 32, -+}; -+/* Should be around maximal number of ever connected displays (since boot :)*/ -+/*TEMP*/ -+enum goc_link_settings_type { -+ GOC_LINK_SETTINGS_TYPE_PREFERRED = 0, -+ GOC_LINK_SETTINGS_TYPE_REPORTED, -+ GOC_LINK_SETTINGS_TYPE_TRAINED, -+ GOC_LINK_SETTINGS_TYPE_OVERRIDEN_TRAINED, -+ GOC_LINK_SETTINGS_TYPE_MAX -+}; -+ -+struct dp_audio_test_data { -+ -+ struct dp_audio_test_data_flags { -+ uint32_t test_requested:1; -+ uint32_t disable_video:1; -+ } flags; -+ -+ /*struct dp_audio_test_data_flags flags;*/ -+ uint32_t sampling_rate; -+ uint32_t channel_count; -+ uint32_t pattern_type; -+ uint8_t pattern_period[8]; -+}; -+ -+struct goc_link_service_data { -+ struct dp_audio_test_data dp_audio_test_data; -+}; -+/* END-OF-TEMP*/ -+ -+ -+union display_path_properties { -+ struct bit_map { -+ uint32_t ALWAYS_CONNECTED:1; -+ uint32_t HPD_SUPPORTED:1; -+ uint32_t NON_DESTRUCTIVE_POLLING:1; -+ uint32_t FORCE_CONNECT_SUPPORTED:1; -+ uint32_t FAKED_PATH:1; -+ uint32_t IS_BRANCH_DP_MST_PATH:1; -+ uint32_t IS_ROOT_DP_MST_PATH:1; -+ uint32_t IS_DP_AUDIO_SUPPORTED:1; -+ uint32_t IS_HDMI_AUDIO_SUPPORTED:1; -+ } bits; -+ -+ uint32_t raw; -+}; -+ -+enum display_tri_state { -+ DISPLAY_TRI_STATE_UNKNOWN = 0, -+ DISPLAY_TRI_STATE_TRUE, -+ DISPLAY_TRI_STATE_FALSE -+}; -+ -+enum { -+ MAX_NUM_OF_LINKS_PER_PATH = 2 -+}; -+enum { -+ SINK_LINK_INDEX = (uint32_t) (-1) -+}; -+enum { -+ ASIC_LINK_INDEX = 0 -+}; -+ -+#endif /* __DAL_DISPLAY_PATH_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/display_service_interface.h b/drivers/gpu/drm/amd/dal/include/display_service_interface.h -new file mode 100644 -index 0000000..b602bca ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/display_service_interface.h -@@ -0,0 +1,165 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_SERVICE_INTERFACE_H__ -+#define __DISPLAY_SERVICE_INTERFACE_H__ -+ -+#include "include/display_service_types.h" -+#include "include/display_path_types.h" -+#include "include/grph_object_ctrl_defs.h" -+ -+struct display_service; -+struct ds_overlay; -+struct ds_dispatch; -+struct ds_synchronization; -+struct path_mode_set; -+ -+struct display_service *dal_display_service_create( -+ struct ds_init_data *data); -+ -+void dal_display_service_destroy( -+ struct display_service **ds); -+ -+struct ds_dispatch *dal_display_service_get_adjustment_interface( -+ struct display_service *ds); -+ -+struct ds_overlay *dal_display_service_get_overlay_interface( -+ struct display_service *ds); -+ -+struct ds_dispatch *dal_display_service_get_set_mode_interface( -+ struct display_service *ds); -+ -+struct ds_dispatch *dal_display_service_get_reset_mode_interface( -+ struct display_service *ds); -+ -+struct ds_synchronization *dal_display_service_get_synchronization_interface( -+ struct display_service *ds); -+ -+enum ds_return dal_display_service_notify_v_sync_int_state( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool maintain_v_sync_phase); -+ -+enum ds_return dal_display_service_target_power_control( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool power_on); -+ -+enum ds_return dal_display_service_power_down_active_hw( -+ struct display_service *ds, -+ enum dc_video_power_state state); -+ -+enum ds_return dal_display_service_mem_request_control( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool enable); -+ -+enum ds_return dal_display_service_set_multimedia_pass_through_mode( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool passThrough); -+ -+enum ds_return dal_display_service_set_palette( -+ struct display_service *ds, -+ uint32_t display_index, -+ const struct ds_devclut *palette, -+ const uint32_t start, -+ const uint32_t length); -+ -+enum ds_return dal_display_service_apply_pix_clk_range( -+ struct display_service *ds, -+ uint32_t display_index, -+ struct pixel_clock_safe_range *range); -+ -+enum ds_return dal_display_service_get_safe_pix_clk( -+ struct display_service *ds, -+ uint32_t display_index, -+ uint32_t *pix_clk_khz); -+ -+enum ds_return dal_display_service_apply_refreshrate_adjustment( -+ struct display_service *ds, -+ uint32_t display_index, -+ enum ds_refreshrate_adjust_action action, -+ struct ds_refreshrate *refreshrate); -+ -+enum ds_return dal_display_service_pre_ddc( -+ struct display_service *ds, -+ uint32_t display_index); -+ -+enum ds_return dal_display_service_post_ddc( -+ struct display_service *ds, -+ uint32_t display_index); -+ -+enum ds_return dal_display_service_backlight_control( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool enable); -+ -+enum ds_return dal_display_service_get_backlight_user_level( -+ struct display_service *ds, -+ uint32_t display_index, -+ uint32_t *level); -+ -+enum ds_return dal_display_service_get_backlight_effective_level( -+ struct display_service *ds, -+ uint32_t display_index, -+ uint32_t *level); -+ -+enum ds_return dal_display_service_enable_hpd( -+ struct display_service *ds, -+ uint32_t display_index); -+ -+enum ds_return dal_display_service_disable_hpd( -+ struct display_service *ds, -+ uint32_t display_index); -+ -+enum ds_return dal_display_service_get_min_mem_channels( -+ struct display_service *ds, -+ const struct path_mode_set *path_mode_set, -+ uint32_t mem_channels_num, -+ uint32_t *min_mem_channels_num); -+ -+enum ds_return dal_display_service_enable_advanced_request( -+ struct display_service *ds, -+ bool enable); -+ -+/*Audio related*/ -+enum ds_return dal_display_service_enable_audio_endpoint( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool enable); -+ -+enum ds_return dal_display_service_mute_audio_endpoint( -+ struct display_service *ds, -+ uint32_t display_index, -+ bool mute); -+ -+bool dal_display_service_calc_view_port_for_wide_display( -+ struct display_service *ds, -+ uint32_t display_index, -+ const struct ds_view_port *set_view_port, -+ struct ds_get_view_port *get_view_port); -+ -+#endif /* __DISPLAY_SERVICE_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/display_service_types.h b/drivers/gpu/drm/amd/dal/include/display_service_types.h -new file mode 100644 -index 0000000..4f27f59 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/display_service_types.h -@@ -0,0 +1,167 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DISPLAY_SERVICE_TYPES_H__ -+#define __DAL_DISPLAY_SERVICE_TYPES_H__ -+struct ds_dispatch { -+ -+}; -+ -+struct ds_view_port_alignment { -+ uint8_t x_width_size_alignment; -+ uint8_t y_height_size_alignment; -+ uint8_t x_start_alignment; -+ uint8_t y_start_alignment; -+}; -+ -+struct hw_sequencer; -+struct topology_mgr; -+struct adapter_service; -+struct timing_service; -+ -+struct ds_init_data { -+ struct dal_context *dal_context; -+ struct hw_sequencer *hwss; -+ struct topology_mgr *tm; -+ struct adapter_service *as; -+ struct timing_service *ts; -+ struct ds_view_port_alignment view_port_alignment; -+}; -+ -+enum ds_return { -+ DS_SUCCESS, -+ DS_SUCCESS_FALLBACK, -+ DS_ERROR, -+ DS_SET_MODE_REQUIRED, -+ DS_REBOOT_REQUIRED, -+ DS_OUT_OF_RANGE, -+ DS_RESOURCE_UNAVAILABLE, -+ DS_NOT_SUPPORTED -+}; -+ -+struct ds_devclut { -+ uint8_t red; -+ uint8_t green; -+ uint8_t blue; -+ uint8_t reserved; -+}; -+ -+enum ds_refreshrate_adjust_action { -+ DS_REFRESHRATE_ADJUST_ACTION_SET, -+ DS_REFRESHRATE_ADJUST_ACTION_RESET, -+ DS_REFRESHRATE_ADJUST_ACTION_UPDATE, -+}; -+ -+struct ds_refreshrate { -+ uint32_t numerator; -+ uint32_t denominator; -+}; -+ -+/*Contains delta in pixels between two active CRTC timings and relevant timing -+details. Delta will be positive if CRTC1 timing running before CRTC2 and -+negative otherwise (CRTC2 timing running before CRTC1)*/ -+/*CRTC1 running before CRTC2 = CRTC1 pixel position in -+frame smaller then CRTC2 position*/ -+struct ds_timings_delta_info { -+ int32_t delta_in_pixels; -+ uint32_t pix_clk_khz; -+ uint32_t h_total; -+ uint32_t v_total; -+}; -+ -+enum ds_audio_os_channel_name { -+ DS_AUDIO_OS_CHANNEL_L = 0, -+ DS_AUDIO_OS_CHANNEL_R = 1, -+ DS_AUDIO_OS_CHANNEL_C = 2, -+ DS_AUDIO_OS_CHANNEL_SUB = 3, -+ DS_AUDIO_OS_CHANNEL_RL = 4, -+ DS_AUDIO_OS_CHANNEL_RR = 5, -+ DS_AUDIO_OS_CHANNEL_SL = 6, -+ DS_AUDIO_OS_CHANNEL_SR = 7, -+ DS_AUDIO_OS_CHANNEL_SILENT = 8, -+ DS_AUDIO_OS_CHANNEL_NO_ASSOCIATION = 15 -+}; -+ -+enum ds_audio_azalia_channel_name { -+ DS_AUDIO_AZALIA_CHANNEL_FL = 0, -+ DS_AUDIO_AZALIA_CHANNEL_FR = 1, -+ DS_AUDIO_AZALIA_CHANNEL_FC = 2, -+ DS_AUDIO_AZALIA_CHANNEL_SUB = 3, -+ DS_AUDIO_AZALIA_CHANNEL_SL = 4, -+ DS_AUDIO_AZALIA_CHANNEL_SR = 5, -+ DS_AUDIO_AZALIA_CHANNEL_BL = 6, -+ DS_AUDIO_AZALIA_CHANNEL_BR = 7, -+ DS_AUDIO_AZALIA_CHANNEL_SILENT = 8, -+ DS_AUDIO_AZALIA_CHANNEL_NO_ASSOCIATION = 15 -+}; -+ -+enum ds_audio_channel_format { -+ DS_AUDIO_CHANNEL_FORMAT_2P0 = 0, -+ DS_AUDIO_CHANNEL_FORMAT_2P1, -+ DS_AUDIO_CHANNEL_FORMAT_5P1, -+ DS_AUDIO_CHANNEL_FORMAT_7P1 -+}; -+ -+/*Used for get/set Mirabilis*/ -+enum ds_mirabilis_control_option { -+ DS_MIRABILIS_UNINITIALIZE = 0, -+ DS_MIRABILIS_DISABLE, -+ DS_MIRABILIS_ENABLE, -+ DS_MIRABILIS_SAVE_PROFILE -+}; -+ -+struct ds_disp_identifier { -+ uint32_t display_index; -+ uint32_t manufacture_id; -+ uint32_t product_id; -+ uint32_t serial_no; -+}; -+ -+struct ds_view_port { -+ uint32_t x_start; -+ uint32_t y_start; -+ uint32_t width; -+ uint32_t height; -+ uint32_t controller; -+}; -+ -+#define DS_MAX_NUM_VIEW_PORTS 2 -+struct ds_get_view_port { -+ uint32_t num_of_view_ports; -+ struct ds_view_port view_ports[DS_MAX_NUM_VIEW_PORTS]; -+}; -+ -+struct ranged_timing_preference_flags { -+ union { -+ struct { -+ uint32_t prefer_enable_drr:1; -+ uint32_t force_disable_drr:1; -+ -+ } bits; -+ uint32_t u32all; -+ }; -+}; -+ -+#endif /* __DAL_DISPLAY_SERVICE_TYPE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_interface.h b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h -new file mode 100644 -index 0000000..c712cc2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h -@@ -0,0 +1,87 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DMCU_INTERFACE_H__ -+#define __DAL_DMCU_INTERFACE_H__ -+ -+#include "grph_object_defs.h" -+#include "dmcu_types.h" -+ -+/* Interface functions */ -+ -+/* DMCU setup related interface functions */ -+struct dmcu *dal_dmcu_create( -+ struct dmcu_init_data *init_data); -+void dal_dmcu_destroy(struct dmcu **dmcu); -+void dal_dmcu_release_hw(struct dmcu *dmcu); -+ -+void dal_dmcu_power_up(struct dmcu *dmcu); -+void dal_dmcu_power_down(struct dmcu *dmcu); -+ -+void dal_dmcu_configure_wait_loop( -+ struct dmcu *dmcu, -+ uint32_t display_clock); -+ -+/* PSR feature related interface functions */ -+void dal_dmcu_psr_setup( -+ struct dmcu *dmcu, -+ struct dmcu_context *dmcu_context); -+void dal_dmcu_psr_enable(struct dmcu *dmcu); -+void dal_dmcu_psr_disable(struct dmcu *dmcu); -+void dal_dmcu_psr_block(struct dmcu *dmcu, bool block_psr); -+bool dal_dmcu_psr_is_blocked(struct dmcu *dmcu); -+void dal_dmcu_psr_set_level( -+ struct dmcu *dmcu, -+ union dmcu_psr_level psr_level); -+void dal_dmcu_psr_allow_power_down_crtc( -+ struct dmcu *dmcu, -+ bool should_allow_crtc_power_down); -+bool dal_dmcu_psr_submit_command( -+ struct dmcu *dmcu, -+ struct dmcu_context *dmcu_context, -+ struct dmcu_config_data *config_data); -+void dal_dmcu_psr_get_config_data( -+ struct dmcu *dmcu, -+ uint32_t v_total, -+ struct dmcu_config_data *config_data); -+ -+/* ABM feature related interface functions */ -+void dal_dmcu_abm_enable( -+ struct dmcu *dmcu, -+ enum controller_id controller_id, -+ uint32_t vsync_rate_hz); -+void dal_dmcu_abm_disable(struct dmcu *dmcu); -+bool dal_dmcu_abm_enable_smooth_brightness(struct dmcu *dmcu); -+bool dal_dmcu_abm_disable_smooth_brightness(struct dmcu *dmcu); -+void dal_dmcu_abm_varibright_control( -+ struct dmcu *dmcu, -+ const struct varibright_control *varibright_control); -+bool dal_dmcu_abm_set_backlight_level( -+ struct dmcu *dmcu, -+ uint8_t backlight_8_bit); -+uint8_t dal_dmcu_abm_get_user_backlight_level(struct dmcu *dmcu); -+uint8_t dal_dmcu_abm_get_current_backlight_level(struct dmcu *dmcu); -+ -+#endif /* __DAL_DMCU_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_types.h b/drivers/gpu/drm/amd/dal/include/dmcu_types.h -new file mode 100644 -index 0000000..1f3107d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dmcu_types.h -@@ -0,0 +1,199 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_DMCU_TYPES_H__ -+#define __DAL_DMCU_TYPES_H__ -+ -+/* Forward declaration */ -+struct dmcu; -+ -+/* Required information for creation and initialization of a controller */ -+struct dmcu_init_data { -+ struct dal_context *dal_context; -+ struct adapter_service *as; -+ uint32_t max_engine_clock_in_khz; -+}; -+ -+/* Interface structure defines */ -+ -+enum dmcu_action { -+ DMCU_ACTION_PSR_ENABLE, -+ DMCU_ACTION_PSR_EXIT, -+ DMCU_ACTION_PSR_RFB_UPDATE, -+ DMCU_ACTION_PSR_SET, -+ DMCU_ACTION_PSR_CLEAR_COUNT, -+ DMCU_ACTION_PSR_COUNT_REQUEST, -+ DMCU_ACTION_PSR_STATE_REQUEST, -+ DMCU_ACTION_PSR_SET_LEVEL, -+ DMCU_ACTION_PSR_ADVANCE_STATE, -+ DMCU_ACTION_PSR_SET_WAITLOOP -+}; -+ -+enum dmcu_output { -+ DMCU_OUTPUT_PSR_ACK, -+ DMCU_OUTPUT_PSR_NACK, -+ DMCU_OUTPUT_PSR_AUX_ERR, -+ DMCU_OUTPUT_PSR_COUNT_STATUS, -+ DMCU_OUTPUT_PSR_STATE_STATUS, -+ DMCU_OUTPUT_PSR_RFB_UPDATE_ERR, -+ DMCU_OUTPUT_PSR_ERR, -+ DMCU_OUTPUT_PSR_GET_REPLY, -+ DMCU_OUTPUT_PSR_ENTRY_ERROR, -+ DMCU_OUTPUT_PSR_LT_ERROR, -+ DMCU_OUTPUT_PSR_FORCE_SR_ERROR, -+ DMCU_OUTPUT_PSR_SDP_SEND_TIMEOUT -+}; -+ -+/* PSR states, based similarly on states defined in eDP specification. */ -+enum psr_state { -+ STATE0, /* PSR is disabled */ -+ STATE1, /* PSR is enabled, but inactive */ -+ STATE1A, -+ STATE2, /* PSR is transitioning to active state */ -+ STATE2A, -+ STATE3, /* PSR is active; Display is in self refresh */ -+ STATE3INIT, -+ STATE4, /* RFB single frame update */ -+ STATE4A, -+ STATE4B, -+ STATE4C, -+ STATE4D, -+ STATE5, /* Exiting from PSR active state */ -+ STATE5A, -+ STATE5B, -+ STATE5C -+}; -+ -+enum phy_type { -+ PHY_TYPE_UNKNOWN = 1, -+ PHY_TYPE_PCIE_PHY = 2, -+ PHY_TYPE_UNIPHY = 3, -+}; -+ -+struct dmcu_context { -+ enum channel_id channel; -+ enum transmitter transmitter_id; -+ enum engine_id engine_id; -+ enum controller_id controller_id; -+ enum phy_type phy_type; -+ enum physical_phy_id smu_physical_phy_id; -+ -+ /* Vertical total pixels from crtc timing. -+ * This is used for static screen detection. -+ * ie. If we want to detect half a frame, -+ * we use this to determine the hyst lines.*/ -+ uint32_t crtc_timing_vertical_total; -+ -+ /* PSR supported from panel capabilities -+ * and current display configuration */ -+ bool psr_supported_display_config; -+ -+ /* Whether fast link training is supported by the panel */ -+ bool psr_exit_link_training_required; -+ -+ /* If RFB setup time is greater than the total VBLANK time, it is not -+ * possible for the sink to capture the video frame in the same frame -+ * the SDP is sent. In this case, the frame capture indication bit -+ * should be set and an extra static frame should be transmitted to -+ * the sink */ -+ bool psr_frame_capture_indication_required; -+ -+ /* Set the last possible line SDP may be transmitted without violating -+ * the RFB setup time */ -+ bool sdp_transmit_line_num_deadline; -+ -+ /* The VSync rate in Hz used to calculate the step size -+ * for smooth brightness feature */ -+ uint32_t vsync_rate_hz; -+}; -+ -+union dmcu_psr_level { -+ struct { -+ bool SKIP_CRC:1; -+ bool SKIP_DP_VID_STREAM_DISABLE:1; -+ bool SKIP_PHY_POWER_DOWN:1; -+ bool SKIP_AUX_ACK_CHECK:1; -+ bool SKIP_CRTC_DISABLE:1; -+ bool SKIP_AUX_RFB_CAPTURE_CHECK:1; -+ bool SKIP_SMU_NOTIFICATION:1; -+ bool SKIP_AUTO_STATE_ADVANCE:1; -+ bool DISABLE_PSR_ENTRY_ABORT:1; -+ } bits; -+ uint32_t u32all; -+}; -+ -+struct dmcu_config_data { -+ /* Command sent to DMCU. */ -+ enum dmcu_action action; -+ /* PSR Level controls which HW blocks to power down during PSR active, -+ * and also other sequence modifications. */ -+ union dmcu_psr_level psr_level; -+ /* To indicate that first changed frame from active state should not -+ * result in exit to inactive state, but instead perform an automatic -+ * single frame RFB update. */ -+ bool rfb_update_auto_en; -+ /* Number of consecutive static frames to detect before entering PSR -+ * active state. */ -+ uint32_t hyst_frames; -+ /* Partial frames before entering PSR active. Note this parameter is in -+ * units of 100 lines. i.e. Wait a value of 5 means wait 500 additional -+ * lines. */ -+ uint32_t hyst_lines; -+ /* Number of repeated AUX retries before indicating failure to driver. -+ * In a working case, first attempt to write/read AUX should pass. */ -+ uint32_t aux_repeat; -+ /* Additional delay after remote frame capture before continuing to -+ * power down. This is mainly for debug purposes to identify timing -+ * issues. */ -+ uint32_t frame_delay; -+ /* Controls how long the delay of a wait loop is. It should be tuned -+ * to 1 us, and needs to be reconfigured every time DISPCLK changes. */ -+ uint32_t wait_loop_num; -+}; -+ -+struct dmcu_output_data { -+ /* DMCU reply */ -+ enum dmcu_output output; -+ /* The current PSR state. */ -+ uint32_t psr_state; -+ /* The number of frames during PSR active state. */ -+ uint32_t psr_count; -+}; -+ -+enum varibright_command { -+ VARIBRIGHT_CMD_SET_VB_LEVEL = 0, -+ VARIBRIGHT_CMD_USER_ENABLE, -+ VARIBRIGHT_CMD_POST_DISPLAY_CONFIG, -+ VARIBRIGHT_CMD_UNKNOWN -+}; -+ -+struct varibright_control { -+ enum varibright_command command; -+ uint8_t level; -+ bool enable; -+ bool activate; -+}; -+ -+#endif /* __DAL_DMCU_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dpcd_access_service_interface.h b/drivers/gpu/drm/amd/dal/include/dpcd_access_service_interface.h -new file mode 100644 -index 0000000..a942c77 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dpcd_access_service_interface.h -@@ -0,0 +1,65 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifdef __DPCD_ACCESS_SERVICE_INTERFACE_HPP__ -+#define __DPCD_ACCESS_SERVICE_INTERFACE_HPP__ -+ -+/* DDC service transaction error codes -+ * depends on transaction status -+ */ -+enum ddc_result { -+ DDCRESULT_UNKNOWN = 0, -+ DDCRESULT_SUCESSFULL, -+ DDCRESULT_FAILEDCHANNELBUSY, -+ DDCRESULT_FAILEDTIMEOUT, -+ DDCRESULT_FAILEDPROTOCOLERROR, -+ DDCRESULT_FAILEDNACK, -+ DDCRESULT_FAILEDINCOMPLETE, -+ DDCRESULT_FAILEDOPERATION, -+ DDCRESULT_FAILEDINVALIDOPERATION, -+ DDCRESULT_FAILEDBUFFEROVERFLOW -+}; -+ -+enum { -+ MaxNativeAuxTransactionSize = 16 -+}; -+ -+struct display_sink_capability; -+ -+/* TO DO: below functions can be moved to ddc_service (think about it)*/ -+enum ddc_result dal_ddc_read_dpcd_data( -+ uint32_t address, -+ unsigned char *data, -+ uint32_t size); -+ -+enum ddc_result dal_ddc_write_dpcd_data( -+ uint32_t address, -+ const unsigned char *data uint32_t size); -+ -+bool dal_aux_query_dp_sink_capability(display_sink_capability *sink_cap); -+bool start_gtc_sync(void); -+bool stop_gtc_sync(void); -+ -+#endif /*__DPCD_ACCESS_SERVICE_INTERFACE_HPP__*/ -diff --git a/drivers/gpu/drm/amd/dal/include/dpcd_defs.h b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h -new file mode 100644 -index 0000000..cefa1fc ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h -@@ -0,0 +1,869 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_SOURCE_RESERVED_START = 0x030C, -+ DPCD_ADDRESS_SOURCE_RESERVED_END = 0x03FF, -+ -+ /* Sink Device Specific Field */ -+ DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400, -+ DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402, -+ DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403, -+ DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408, -+ DPCD_ADDRESS_SINK_REVISION_START = 0x409, -+ DPCD_ADDRESS_SINK_REVISION_END = 0x40B, -+ -+ /* Branch Device Specific Field */ -+ DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500, -+ DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502, -+ DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503, -+ DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508, -+ -+ DPCD_ADDRESS_POWER_STATE = 0x0600, -+ -+ /* EDP related */ -+ DPCD_ADDRESS_EDP_REV = 0x0700, -+ DPCD_ADDRESS_EDP_CAPABILITY = 0x0701, -+ DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702, -+ DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703, -+ -+ DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720, -+ DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721, -+ DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722, -+ DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723, -+ DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724, -+ DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725, -+ DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726, -+ DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727, -+ DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728, -+ DPCD_ADDRESS_EDP_REVERVED = 0x0729, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E, -+ DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F, -+ -+ DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732, -+ DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733, -+ -+ /* Sideband MSG Buffers 1.2 */ -+ DPCD_ADDRESS_DOWN_REQ_START = 0x01000, -+ DPCD_ADDRESS_DOWN_REQ_END = 0x011ff, -+ -+ DPCD_ADDRESS_UP_REP_START = 0x01200, -+ DPCD_ADDRESS_UP_REP_END = 0x013ff, -+ -+ DPCD_ADDRESS_DOWN_REP_START = 0x01400, -+ DPCD_ADDRESS_DOWN_REP_END = 0x015ff, -+ -+ DPCD_ADDRESS_UP_REQ_START = 0x01600, -+ DPCD_ADDRESS_UP_REQ_END = 0x017ff, -+ -+ /* ESI (Event Status Indicator) Field 1.2 */ -+ DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002, -+ DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003, -+ DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004, -+ /*@todo move dpcd_address_Lane01Status back here*/ -+ -+ DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006, -+ DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007, -+ DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008, -+ DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009, -+ DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A, -+ -+ /* Travis specific addresses */ -+ DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0, -+ DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET = 0x5f1, -+ DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2, -+}; -+ -+enum dpcd_revision { -+ DPCD_REV_10 = 0x10, -+ DPCD_REV_11 = 0x11, -+ DPCD_REV_12 = 0x12 -+}; -+ -+enum dp_pwr_state { -+ DP_PWR_STATE_D0 = 1,/* direct HW translation! */ -+ DP_PWR_STATE_D3 -+}; -+ -+/* these are the types stored at DOWNSTREAMPORT_PRESENT */ -+enum dpcd_downstream_port_type { -+ DOWNSTREAM_DP = 0, -+ DOWNSTREAM_VGA, -+ DOWNSTREAM_DVI_HDMI, -+ DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */ -+}; -+ -+enum dpcd_link_test_patterns { -+ LINK_TEST_PATTERN_NONE = 0, -+ LINK_TEST_PATTERN_COLOR_RAMP, -+ LINK_TEST_PATTERN_VERTICAL_BARS, -+ LINK_TEST_PATTERN_COLOR_SQUARES -+}; -+ -+enum dpcd_test_color_format { -+ TEST_COLOR_FORMAT_RGB = 0, -+ TEST_COLOR_FORMAT_YCBCR422, -+ TEST_COLOR_FORMAT_YCBCR444 -+}; -+ -+enum dpcd_test_bit_depth { -+ TEST_BIT_DEPTH_6 = 0, -+ TEST_BIT_DEPTH_8, -+ TEST_BIT_DEPTH_10, -+ TEST_BIT_DEPTH_12, -+ TEST_BIT_DEPTH_16 -+}; -+ -+/* PHY (encoder) test patterns -+The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) */ -+enum dpcd_phy_test_patterns { -+ PHY_TEST_PATTERN_NONE = 0, -+ PHY_TEST_PATTERN_D10_2, -+ PHY_TEST_PATTERN_SYMBOL_ERROR, -+ PHY_TEST_PATTERN_PRBS7, -+ PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */ -+ PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */ -+}; -+ -+enum dpcd_test_dyn_range { -+ TEST_DYN_RANGE_VESA = 0, -+ TEST_DYN_RANGE_CEA -+}; -+ -+enum dpcd_audio_test_pattern { -+ AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */ -+ AUDIO_TEST_PATTERN_SAWTOOTH -+}; -+ -+enum dpcd_audio_sampling_rate { -+ AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */ -+ AUDIO_SAMPLING_RATE_44_1KHZ, -+ AUDIO_SAMPLING_RATE_48KHZ, -+ AUDIO_SAMPLING_RATE_88_2KHZ, -+ AUDIO_SAMPLING_RATE_96KHZ, -+ AUDIO_SAMPLING_RATE_176_4KHZ, -+ AUDIO_SAMPLING_RATE_192KHZ -+}; -+ -+enum dpcd_audio_channels { -+ AUDIO_CHANNELS_1 = 0,/* direct HW translation */ -+ AUDIO_CHANNELS_2, -+ AUDIO_CHANNELS_3, -+ AUDIO_CHANNELS_4, -+ AUDIO_CHANNELS_5, -+ AUDIO_CHANNELS_6, -+ AUDIO_CHANNELS_7, -+ AUDIO_CHANNELS_8, -+ -+ AUDIO_CHANNELS_COUNT -+}; -+ -+enum dpcd_audio_test_pattern_periods { -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */ -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_3, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_6, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_12, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_24, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_48, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_96, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_192, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_384, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_768, -+ DPCD_AUDIO_TEST_PATTERN_PERIOD_1536 -+}; -+ -+/* This enum is for programming DPCD TRAINING_PATTERN_SET */ -+enum dpcd_training_patterns { -+ DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */ -+ DPCD_TRAINING_PATTERN_1, -+ DPCD_TRAINING_PATTERN_2, -+ DPCD_TRAINING_PATTERN_3 -+}; -+ -+/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus -+It defines the possible PSR states. */ -+enum dpcd_psr_sink_states { -+ PSR_SINK_STATE_INACTIVE = 0, -+ PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1, -+ PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2, -+ PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3, -+ PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4, -+ PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, -+}; -+ -+/* This enum defines the Panel's eDP revision at DPCD 700h -+ * 00h = eDP v1.1 or lower -+ * 01h = eDP v1.2 -+ * 02h = eDP v1.3 (PSR support starts here) -+ * 03h = eDP v1.4 -+ * If unknown revision, treat as eDP v1.1, meaning least functionality set. -+ * This enum has values matched to eDP spec, thus values should not change. -+ */ -+enum dpcd_edp_revision { -+ DPCD_EDP_REVISION_EDP_V1_1 = 0, -+ DPCD_EDP_REVISION_EDP_V1_2 = 1, -+ DPCD_EDP_REVISION_EDP_V1_3 = 2, -+ DPCD_EDP_REVISION_EDP_V1_4 = 3, -+ DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, -+}; -+ -+union dpcd_rev { -+ struct { -+ uint8_t MINOR:4; -+ uint8_t MAJOR:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+union max_lane_count { -+ struct { -+ uint8_t MAX_LANE_COUNT:5; -+ uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; -+ uint8_t TPS3_SUPPORTED:1; -+ uint8_t ENHANCED_FRAME_CAP:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union max_down_spread { -+ struct { -+ uint8_t MAX_DOWN_SPREAD:1; -+ uint8_t RESERVED:5; -+ uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; -+ uint8_t RESERVED1:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union mstm_cap { -+ struct { -+ uint8_t MST_CAP:1; -+ uint8_t RESERVED:7; -+ } bits; -+ uint8_t raw; -+}; -+ -+union mstm_cntl { -+ struct { -+ uint8_t MST_EN:1; -+ uint8_t UP_REQ_EN:1; -+ uint8_t UPSTREAM_IS_SRC:1; -+ uint8_t RESERVED:5; -+ } bits; -+ uint8_t raw; -+}; -+ -+union lane_count_set { -+ struct { -+ uint8_t LANE_COUNT_SET:5; -+ uint8_t POST_LT_ADJ_REQ_GRANTED:1; -+ uint8_t RESERVED:1; -+ uint8_t ENHANCED_FRAMING:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* for DPCD_ADDRESS_I2C_SPEED_CNTL_CAP -+ * and DPCD_ADDRESS_I2C_SPEED_CNTL -+ */ -+union i2c_speed { -+ struct { -+ uint8_t _1KBPS:1; -+ uint8_t _5KBPS:1; -+ uint8_t _10KBPS:1; -+ uint8_t _100KBPS:1; -+ uint8_t _400KBPS:1; -+ uint8_t _1MBPS:1; -+ uint8_t reserved:2; -+ } bits; -+ uint8_t raw; -+}; -+ -+union payload_table_update_status { -+ struct { -+ uint8_t VC_PAYLOAD_TABLE_UPDATED:1; -+ uint8_t ACT_HANDLED:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union device_irq_esi_0 { -+ struct { -+ uint8_t REMOTE_CONTROL_CMD_PENDING:1; -+ uint8_t AUTOMATED_TEST_REQUEST:1; -+ uint8_t CP_IRQ:1; -+ uint8_t MCCS_IRQ:1; -+ uint8_t DOWN_REP_MSG_RDY:1; -+ uint8_t UP_REQ_MSG_RDY:1; -+ uint8_t SINK_SPECIFIC_IRQ:1; -+ uint8_t RESERVED:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union lane_status { -+ struct { -+ uint8_t CR_DONE_0:1; -+ uint8_t CHANNEL_EQ_DONE_0:1; -+ uint8_t SYMBOL_LOCKED_0:1; -+ uint8_t RESERVED0:1; -+ uint8_t CR_DONE_1:1; -+ uint8_t CHANNEL_EQ_DONE_1:1; -+ uint8_t SYMBOL_LOCKED_1:1; -+ uint8_t RESERVED_1:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union device_service_irq { -+ struct { -+ uint8_t REMOTE_CONTROL_CMD_PENDING:1; -+ uint8_t AUTOMATED_TEST:1; -+ uint8_t CP_IRQ:1; -+ uint8_t MCCS_IRQ:1; -+ uint8_t DOWN_REP_MSG_RDY:1; -+ uint8_t UP_REQ_MSG_RDY:1; -+ uint8_t SINK_SPECIFIC:1; -+ uint8_t reserved:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union downstream_port { -+ struct { -+ uint8_t PRESENT:1; -+ uint8_t TYPE:2; -+ uint8_t FORMAT_CONV:1; -+ uint8_t DETAILED_CAPS:1; -+ uint8_t RESERVED:3; -+ } bits; -+ uint8_t raw; -+}; -+ -+union sink_count { -+ struct { -+ uint8_t SINK_COUNT:6; -+ uint8_t CPREADY:1; -+ uint8_t RESERVED:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union lane_align_status_updated { -+ struct { -+ uint8_t INTERLANE_ALIGN_DONE:1; -+ uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; -+ uint8_t RESERVED:4; -+ uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; -+ uint8_t LINK_STATUS_UPDATED:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union lane_adjust { -+ struct { -+ uint8_t VOLTAGE_SWING_LANE:2; -+ uint8_t PRE_EMPHASIS_LANE:2; -+ uint8_t RESERVED:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* Automated test structures */ -+union test_request { -+ struct { -+ uint8_t LINK_TRAINING:1; -+ uint8_t LINK_TEST_PATTERN:1; -+ uint8_t EDID_READ:1; -+ uint8_t PHY_TEST_PATTERN:1; -+ uint8_t AUDIO_TEST_PATTERN:1; -+ uint8_t AUDIO_TEST_NO_VIDEO:1; -+ uint8_t RESERVED:1; -+ uint8_t TEST_STEREO_3D:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union test_response { -+ struct { -+ uint8_t ACK:1; -+ uint8_t NO_ACK:1; -+ uint8_t RESERVED:6; -+ } bits; -+ uint8_t raw; -+}; -+ -+union link_test_pattern { -+ struct { -+ uint8_t PATTERN:2;/*DpcdLinkTestPatterns*/ -+ uint8_t RESERVED:6; -+ } bits; -+ uint8_t raw; -+}; -+ -+union test_misc { -+ struct dpcd_test_misc_bits { -+ uint8_t SYNC_CLOCK:1; -+ uint8_t CLR_FORMAT:2;/*DpcdTestColorFormat*/ -+ uint8_t DYN_RANGE:1;/*DpcdTestDynRange*/ -+ uint8_t YCBCR:1;/*DpcdTestYCbCrStandard*/ -+ uint8_t BPC:3;/*DpcdTestBitDepth*/ -+ } bits; -+ uint8_t raw; -+}; -+ -+union phy_test_pattern { -+ struct { -+ /* This field is 2 bits for DP1.1 and 3 bits for DP1.2.*/ -+ uint8_t PATTERN:3; -+ uint8_t RESERVED:5;/* BY spec, bit7:2 is 0 for DP1.1.*/ -+ } bits; -+ uint8_t raw; -+}; -+ -+union audio_test_mode { -+ struct { -+ uint8_t SAMPLING_RATE:4; -+ uint8_t CHANNEL_COUNT:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+union audio_tes_tpattern_period { -+ struct { -+ uint8_t PATTERN_PERIOD:4; -+ uint8_t RESERVED:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+struct audio_test_pattern_type { -+ uint8_t value; -+}; -+ -+union dpcd_training_pattern { -+ struct { -+ uint8_t TRAINING_PATTERN_SET:2; -+ uint8_t LINK_QUAL_PATTERN_SET:2; -+ uint8_t RECOVERED_CLOCK_OUT_EN:1; -+ uint8_t SCRAMBLING_DISABLE:1; -+ uint8_t RESERVED:2; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* Training Lane is used to configure downstream DP device's voltage swing -+and pre-emphasis levels*/ -+/* The DPCD addresses are from 0x103 to 0x106*/ -+union dpcd_training_lane { -+ struct { -+ uint8_t VOLTAGE_SWING_SET:2; -+ uint8_t MAX_SWING_REACHED:1; -+ uint8_t PRE_EMPHASIS_SET:2; -+ uint8_t MAX_PRE_EMPHASIS_REACHED:1; -+ uint8_t RESERVED:2; -+ } bits; -+ uint8_t raw; -+}; -+ -+/*Training Lane Set 2 is used to configure downstream DP device's -+post cursor 2 level of Training Pattern 2 or 3*/ -+/* The DPCD addresses are 0x10F (TRAINING_LANE0_1_SET2) -+and 0x110 (TRAINING_LANE2_3_SET2)*/ -+union dpcd_training_lane_set2 { -+ struct { -+ uint8_t POST_CURSOR2_SET:2; -+ uint8_t MAX_POST_CURSOR2_REACHED:1; -+ uint8_t RESERVED:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union dpcd_psr_configuration { -+ struct { -+ uint8_t ENABLE:1; -+ uint8_t TRANSMITTER_ACTIVE_IN_PSR:1; -+ uint8_t CRC_VERIFICATION:1; -+ uint8_t FRAME_CAPTURE_INDICATION:1; -+ uint8_t LINE_CAPTURE_INDICATION:1; -+ uint8_t IRQ_HPD_WITH_CRC_ERROR:1; -+ uint8_t RESERVED:2; -+ } bits; -+ uint8_t raw; -+}; -+ -+union psr_error_status { -+ struct { -+ uint8_t LINK_CRC_ERROR:1; -+ uint8_t RFB_STORAGE_ERROR:1; -+ uint8_t RESERVED:6; -+ } bits; -+ uint8_t raw; -+}; -+ -+union psr_event_status_ind { -+ struct { -+ uint8_t SINK_PSR_CAP_CHANGE:1; -+ uint8_t RESERVED:7; -+ } bits; -+ uint8_t raw; -+}; -+ -+union psr_sink_psr_status { -+ struct { -+ uint8_t SINK_SELF_REFRESH_STATUS:3; -+ uint8_t RESERVED:5; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* EDP related 0x701 */ -+union edp_generial_cap1 { -+ struct { -+ uint8_t TCON_BACKLIGHT_ADJUSTMENT_CAPABLE:1; -+ uint8_t BACKLIGHT_PIN_ENABLE_CAPABLE:1; -+ uint8_t BACKLIGHT_AUX_ENABLE_CAPABLE:1; -+ uint8_t PANEL_SELFTEST_PIN_ENABLE_CAPABLE:1; -+ uint8_t BACKLIGHT_SELFTEST_AUX_ENABLE_CAPABLE:1; -+ uint8_t FRC_ENABLE_CAPABLE:1; -+ uint8_t COLOR_ENGINE_CAPABLE:1; -+ /*bit 7, pane can be controlled by 0x600*/ -+ uint8_t SET_POWER_CAPABLE:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* TMDS-converter related */ -+union dwnstream_port_caps_byte0 { -+ struct { -+ uint8_t DWN_STRM_PORTX_TYPE:3; -+ uint8_t DWN_STRM_PORTX_HPD:1; -+ uint8_t RESERVERD:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ -+enum dpcd_downstream_port_detailed_type { -+ DOWN_STREAM_DETAILED_DP = 0, -+ DOWN_STREAM_DETAILED_VGA, -+ DOWN_STREAM_DETAILED_DVI, -+ DOWN_STREAM_DETAILED_HDMI, -+ DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ -+ DOWN_STREAM_DETAILED_DP_PLUS_PLUS -+}; -+ -+union dwnstream_port_caps_byte2 { -+ struct { -+ uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; -+ uint8_t RESERVED:6; -+ } bits; -+ uint8_t raw; -+}; -+ -+union dp_downstream_port_present { -+ uint8_t byte; -+ struct { -+ uint8_t PORT_PRESENT:1; -+ uint8_t PORT_TYPE:2; -+ uint8_t FMT_CONVERSION:1; -+ uint8_t DETAILED_CAPS:1; -+ uint8_t RESERVED:3; -+ } fields; -+}; -+ -+ -+union dwnstream_port_caps_byte3_dvi { -+ struct { -+ uint8_t RESERVED1:1; -+ uint8_t DUAL_LINK:1; -+ uint8_t HIGH_COLOR_DEPTH:1; -+ uint8_t RESERVED2:5; -+ } bits; -+ uint8_t raw; -+}; -+ -+union dwnstream_port_caps_byte3_hdmi { -+ struct { -+ uint8_t FRAME_SEQ_TO_FRAME_PACK:1; -+ uint8_t RESERVED:7; -+ } bits; -+ uint8_t raw; -+}; -+ -+/*4-byte structure for detailed capabilities of a down-stream port -+(DP-to-TMDS converter).*/ -+union dwnstream_portx_caps { -+ struct { -+ union dwnstream_port_caps_byte0 byte0; -+ uint8_t max_tmds_clk;/* byte1 */ -+ union dwnstream_port_caps_byte2 byte2; -+ -+ union { -+ union dwnstream_port_caps_byte3_dvi byte_dvi; -+ union dwnstream_port_caps_byte3_hdmi byte_hdmi; -+ } byte3; -+ } bytes; -+ uint8_t raw[4]; -+}; -+ -+union sink_status { -+ struct { -+ uint8_t RX_PORT0_STATUS:1; -+ uint8_t RX_PORT1_STATUS:1; -+ uint8_t RESERVED:6; -+ } bits; -+ uint8_t raw; -+}; -+ -+/*6-byte structure corresponding to 6 registers (200h-205h) -+read during handling of HPD-IRQ*/ -+union hpd_irq_data { -+ struct { -+ union sink_count sink_cnt;/* 200h */ -+ union device_service_irq device_service_irq;/* 201h */ -+ union lane_status lane01_status;/* 202h */ -+ union lane_status lane23_status;/* 203h */ -+ union lane_align_status_updated lane_status_updated;/* 204h */ -+ union sink_status sink_status; -+ } bytes; -+ uint8_t raw[6]; -+}; -+ -+union down_stream_port_count { -+ struct { -+ uint8_t DOWN_STR_PORT_COUNT:4; -+ uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ -+ /*Bit 6 = MSA_TIMING_PAR_IGNORED -+ 0 = Sink device requires the MSA timing parameters -+ 1 = Sink device is capable of rendering incoming video -+ stream without MSA timing parameters*/ -+ uint8_t IGNORE_MSA_TIMING_PARAM:1; -+ /*Bit 7 = OUI Support -+ 0 = OUI not supported -+ 1 = OUI supported -+ (OUI and Device Identification mandatory for DP 1.2)*/ -+ uint8_t OUI_SUPPORT:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union down_spread_ctrl { -+ struct { -+ uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ -+ /* Bits 4 = SPREAD_AMP. Spreading amplitude -+ 0 = Main link signal is not downspread -+ 1 = Main link signal is downspread <= 0.5% -+ with frequency in the range of 30kHz ~ 33kHz*/ -+ uint8_t SPREAD_AMP:1; -+ uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ -+ /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN -+ 0 = Source device will send valid data for the MSA Timing Params -+ 1 = Source device may send invalid data for these MSA Timing Params*/ -+ uint8_t IGNORE_MSA_TIMING_PARAM:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+union dpcd_edp_config { -+ struct { -+ uint8_t PANEL_MODE_EDP:1; -+ uint8_t FRAMING_CHANGE_ENABLE:1; -+ uint8_t RESERVED:5; -+ uint8_t PANEL_SELF_TEST_ENABLE:1; -+ } bits; -+ uint8_t raw; -+}; -+ -+struct dp_device_vendor_id { -+ uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ -+ uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ -+}; -+ -+struct dp_sink_hw_fw_revision { -+ uint8_t ieee_hw_rev; -+ uint8_t ieee_fw_rev[2]; -+}; -+ -+/*DPCD register of DP receiver capability field bits-*/ -+union edp_configuration_cap { -+ struct { -+ uint8_t ALT_SCRAMBLER_RESET:1; -+ uint8_t FRAMING_CHANGE:1; -+ uint8_t RESERVED:1; -+ uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; -+ uint8_t RESERVED2:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+union psr_capabilities { -+ struct { -+ uint8_t EXIT_LT_NOT_REQ:1; -+ uint8_t RFB_SETUP_TIME:3; -+ uint8_t RESERVED:4; -+ } bits; -+ uint8_t raw; -+}; -+ -+#endif /* __DAL_DPCD_DEFS_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/dvo_interface.h b/drivers/gpu/drm/amd/dal/include/dvo_interface.h -new file mode 100644 -index 0000000..58d2c6f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/dvo_interface.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_DVO_INTERFACE_H__ -+#define __DAL_DVO_INTERFACE_H__ -+ -+#include "gpio_types.h" -+ -+struct dvo; -+ -+enum gpio_result dal_dvo_open( -+ struct dvo *dvo, -+ enum gpio_mode mode); -+ -+enum gpio_result dal_dvo_get_value( -+ const struct dvo *dvo, -+ uint32_t *value); -+ -+enum gpio_result dal_dvo_set_value( -+ const struct dvo *dvo, -+ uint32_t value); -+ -+void dal_dvo_close( -+ struct dvo *dvo); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/encoder_interface.h b/drivers/gpu/drm/amd/dal/include/encoder_interface.h -new file mode 100644 -index 0000000..5fbf816 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/encoder_interface.h -@@ -0,0 +1,278 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of enc software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and enc permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ENCODER_INTERFACE_H__ -+#define __DAL_ENCODER_INTERFACE_H__ -+ -+#include "encoder_types.h" -+#include "adapter_service_interface.h" -+#include "fixed31_32.h" -+ -+enum encoder_result { -+ ENCODER_RESULT_OK, -+ ENCODER_RESULT_ERROR, -+ ENCODER_RESULT_NOBANDWIDTH, -+ ENCODER_RESULT_SINKCONNECTIVITYCHANGED, -+}; -+ -+struct encoder_init_data { -+ struct adapter_service *adapter_service; -+ enum channel_id channel; -+ struct graphics_object_id connector; -+ enum hpd_source_id hpd_source; -+ /* TODO: in DAL2, here was pointer to EventManagerInterface */ -+ struct graphics_object_id encoder; -+ struct dc_context *ctx; -+}; -+ -+/* forward declaration */ -+struct encoder; -+ -+struct encoder *dal_encoder_create( -+ const struct encoder_init_data *init_data); -+ -+/* access graphics object base */ -+const struct graphics_object_id dal_encoder_get_graphics_object_id( -+ const struct encoder *enc); -+ -+/* -+ * Signal types support -+ */ -+uint32_t dal_encoder_enumerate_input_signals( -+ const struct encoder *enc); -+uint32_t dal_encoder_enumerate_output_signals( -+ const struct encoder *enc); -+bool dal_encoder_is_input_signal_supported( -+ const struct encoder *enc, -+ enum signal_type signal); -+bool dal_encoder_is_output_signal_supported( -+ const struct encoder *enc, -+ enum signal_type signal); -+void dal_encoder_set_input_signals( -+ struct encoder *enc, -+ uint32_t signals); -+void dal_encoder_set_output_signals( -+ struct encoder *enc, -+ uint32_t signals); -+ -+/* -+ * Programming interface -+ */ -+/* perform power-up sequence (boot up, resume, recovery) */ -+enum encoder_result dal_encoder_power_up( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* perform power-down (shut down, stand-by */ -+enum encoder_result dal_encoder_power_down( -+ struct encoder *enc, -+ const struct encoder_output *output); -+/* setup encoder block (DIG, DVO, DAC), does not enables encoder */ -+enum encoder_result dal_encoder_setup( -+ struct encoder *enc, -+ const struct encoder_output *output); -+/* activate transmitter, -+ * do preparation before enables the actual stream output */ -+enum encoder_result dal_encoder_pre_enable_output( -+ struct encoder *enc, -+ const struct encoder_pre_enable_output_param *param); -+/* activate transmitter, enables actual stream output */ -+enum encoder_result dal_encoder_enable_output( -+ struct encoder *enc, -+ const struct encoder_output *output); -+/* deactivate transmitter, disables stream output */ -+enum encoder_result dal_encoder_disable_output( -+ struct encoder *enc, -+ const struct encoder_output *output); -+/* output blank data, -+ *prevents output of the actual surface data on active transmitter */ -+enum encoder_result dal_encoder_blank( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* stop sending blank data, -+ * output the actual surface data on active transmitter */ -+enum encoder_result dal_encoder_unblank( -+ struct encoder *enc, -+ const struct encoder_unblank_param *param); -+/* setup stereo signal from given controller */ -+enum encoder_result dal_encoder_setup_stereo( -+ struct encoder *enc, -+ const struct encoder_3d_setup *setup); -+/* enable HSync/VSync output from given controller */ -+enum encoder_result dal_encoder_enable_sync_output( -+ struct encoder *enc, -+ enum sync_source src); -+/* disable HSync/VSync output */ -+enum encoder_result dal_encoder_disable_sync_output( -+ struct encoder *enc); -+/* action of encoder before DDC transaction */ -+enum encoder_result dal_encoder_pre_ddc( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* action of encoder after DDC transaction */ -+enum encoder_result dal_encoder_post_ddc( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* CRT DDC EDID polling interrupt interface */ -+enum encoder_result dal_encoder_update_implementation( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* set test pattern signal */ -+enum encoder_result dal_encoder_set_dp_phy_pattern( -+ struct encoder *enc, -+ const struct encoder_set_dp_phy_pattern_param *param); -+ -+void dal_encoder_release_hw(struct encoder *enc); -+/* -+ * Information interface -+ */ -+/* check whether sink is present based on SENSE detection, -+ * analog encoders will return true */ -+bool dal_encoder_is_sink_present( -+ struct encoder *enc, -+ struct graphics_object_id downstream); -+/* detect load on the sink, -+ * for analog signal, -+ * load detection will be called for the specified signal */ -+enum signal_type dal_encoder_detect_load( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* detect output sink type, -+ * for digital perform sense detection, -+ * for analog return encoder's signal type */ -+enum signal_type dal_encoder_detect_sink( -+ struct encoder *enc, -+ struct graphics_object_id downstream); -+/* get transmitter id */ -+enum transmitter dal_encoder_get_transmitter( -+ const struct encoder *enc); -+/* */ -+enum transmitter dal_encoder_get_paired_transmitter( -+ const struct encoder *enc); -+/* */ -+enum physical_phy_id dal_encoder_get_phy( -+ const struct encoder *enc); -+/* */ -+enum physical_phy_id dal_encoder_get_paired_phy( -+ const struct encoder *enc); -+/* reports if the encoder supports given link settings */ -+bool dal_encoder_is_link_settings_supported( -+ struct encoder *enc, -+ const struct link_settings *link_settings); -+/* options and features supported by encoder */ -+struct encoder_feature_support dal_encoder_get_supported_features( -+ const struct encoder *enc); -+/* reports list of supported stream engines */ -+union supported_stream_engines dal_encoder_get_supported_stream_engines( -+ const struct encoder *enc); -+/* reports preferred stream engine */ -+enum engine_id dal_encoder_get_preferred_stream_engine( -+ const struct encoder *enc); -+/* reports whether clock source can be used with enc encoder */ -+bool dal_encoder_is_clock_source_supported( -+ const struct encoder *enc, -+ enum clock_source_id clock_source); -+/* check encoder capabilities to confirm -+ * specified timing is in the encoder limits -+ * when outputting certain signal */ -+enum encoder_result dal_encoder_validate_output( -+ struct encoder *enc, -+ const struct encoder_output *output); -+/* retrieves sync source which outputs VSync signal from encoder */ -+enum sync_source dal_encoder_get_vsync_output_source( -+ const struct encoder *enc); -+/* -+ * Adjustments -+ */ -+/* update AVI info frame */ -+void dal_encoder_update_info_frame( -+ struct encoder *enc, -+ const struct encoder_info_frame_param *param); -+/* */ -+void dal_encoder_stop_info_frame( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* */ -+enum encoder_result dal_encoder_set_lcd_backlight_level( -+ struct encoder *enc, -+ uint32_t level); -+/* backlight control interface */ -+enum encoder_result dal_encoder_backlight_control( -+ struct encoder *enc, -+ bool enable); -+/* -+ * DP MST programming -+ */ -+/* update payload slot allocation for each DP MST stream */ -+enum encoder_result dal_encoder_update_mst_alloc_table( -+ struct encoder *enc, -+ const struct dp_mst_stream_allocation_table *table, -+ bool is_removal); -+/* enable virtual channel stream with throttled value X.Y */ -+enum encoder_result dal_encoder_enable_stream( -+ struct encoder *enc, -+ enum engine_id engine, -+ struct fixed31_32 throttled_vcp_size); -+/* disable virtual channel stream */ -+enum encoder_result dal_encoder_disable_stream( -+ struct encoder *enc, -+ enum engine_id engine); -+void dal_encoder_set_multi_path(struct encoder *enc, bool is_multi_path); -+/* -+ * Test harness -+ */ -+/* check whether Test Pattern enabled */ -+bool dal_encoder_is_test_pattern_enabled( -+ struct encoder *enc, -+ enum engine_id engine); -+/* set lane parameters */ -+enum encoder_result dal_encoder_set_lane_settings( -+ struct encoder *enc, -+ const struct encoder_context *ctx, -+ const struct link_training_settings *link_settings); -+/* get lane parameters */ -+enum encoder_result dal_encoder_get_lane_settings( -+ struct encoder *enc, -+ const struct encoder_context *ctx, -+ struct link_training_settings *link_settings); -+/* enable master clock of HPD interrupt */ -+void dal_encoder_enable_hpd( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+/* disable all HPD interrupts */ -+void dal_encoder_disable_hpd( -+ struct encoder *enc, -+ const struct encoder_context *ctx); -+ -+/* get current HW state - used for optimization code path only */ -+enum clock_source_id dal_encoder_get_active_clock_source( -+ const struct encoder *enc); -+enum engine_id dal_encoder_get_active_engine( -+ const struct encoder *enc); -+ -+/* destroy encoder instance */ -+void dal_encoder_destroy( -+ struct encoder **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/encoder_types.h b/drivers/gpu/drm/amd/dal/include/encoder_types.h -new file mode 100644 -index 0000000..2897a1d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/encoder_types.h -@@ -0,0 +1,216 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ENCODER_TYPES_H__ -+#define __DAL_ENCODER_TYPES_H__ -+ -+#include "grph_object_defs.h" -+#include "signal_types.h" -+#include "hw_sequencer_types.h" -+#include "link_service_types.h" -+ -+struct encoder_context { -+ /* -+ * HW programming context -+ */ -+ /* DIG id. Also used as AC context */ -+ enum engine_id engine; -+ /* DDC line */ -+ enum channel_id channel; -+ /* HPD line */ -+ enum hpd_source_id hpd_source; -+ /* -+ * ASIC Control (VBIOS) context -+ */ -+ /* encoder output signal */ -+ enum signal_type signal; -+ /* native connector id */ -+ struct graphics_object_id connector; -+ /* downstream object (can be connector or downstream encoder) */ -+ struct graphics_object_id downstream; -+}; -+ -+union encoder_flags { -+ struct { -+ /* enable audio (DP/eDP only) */ -+ uint32_t ENABLE_AUDIO:1; -+ /* coherency */ -+ uint32_t COHERENT:1; -+ /* delay after Pixel Format change before enable transmitter */ -+ uint32_t DELAY_AFTER_PIXEL_FORMAT_CHANGE:1; -+ /* by default, do not turn off VCC when disabling output */ -+ uint32_t TURN_OFF_VCC:1; -+ /* by default, do wait for HPD low after turn of panel VCC */ -+ uint32_t NO_WAIT_FOR_HPD_LOW:1; -+ /* slow DP panels don't reset internal fifo */ -+ uint32_t VID_STREAM_DIFFER_TO_SYNC:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+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_info_frame_param { -+ struct encoder_info_frame packets; -+ struct encoder_context enc_ctx; -+}; -+ -+/*TODO: cleanup pending encoder cleanup*/ -+struct encoder_output { -+ /* encoder AC & HW programming context */ -+ struct encoder_context enc_ctx; -+ /* requested timing */ -+ struct hw_crtc_timing crtc_timing; -+ /* clock source id (PLL or external) */ -+ enum clock_source_id clock_source; -+ /* link settings (DP/eDP only) */ -+ struct link_settings link_settings; -+ /* info frame packets */ -+ struct encoder_info_frame info_frame; -+ /* timing validation (HDMI only) */ -+ uint32_t max_tmds_clk_from_edid_in_mhz; -+ /* edp panel mode */ -+ enum dp_panel_mode dp_panel_mode; -+ /* delay in milliseconds after powering up DP receiver (DP/eDP only) */ -+ uint32_t delay_after_dp_receiver_power_up; -+ /* various flags for features and workarounds */ -+ union encoder_flags flags; -+ /* delay after pixel format change */ -+ uint32_t delay_after_pixel_format_change; -+ /* controller id */ -+ enum controller_id controller; -+ /* maximum supported deep color depth for HDMI */ -+ enum dc_color_depth max_hdmi_deep_color; -+ /* maximum supported pixel clock for HDMI */ -+ uint32_t max_hdmi_pixel_clock; -+}; -+ -+struct encoder_pre_enable_output_param { -+ struct hw_crtc_timing crtc_timing; -+ struct link_settings link_settings; -+ struct encoder_context enc_ctx; -+}; -+ -+struct encoder_unblank_param { -+ struct hw_crtc_timing crtc_timing; -+ struct link_settings link_settings; -+ enum signal_type signal; -+}; -+ -+/* -+ * @brief -+ * Parameters to setup stereo 3D mode in Encoder: -+ * - source: used for side-band stereo sync (DVO/DAC); -+ * - engine_id: defines engine for this Encoder; -+ * - enable_inband: in-band stereo sync should be enabled; -+ * - enable_sideband: side-band stereo sync should be enabled. -+ */ -+struct encoder_3d_setup { -+ enum engine_id engine; -+ enum sync_source source; -+ union { -+ struct { -+ uint32_t SETUP_SYNC_SOURCE:1; -+ uint32_t ENABLE_INBAND:1; -+ uint32_t ENABLE_SIDEBAND:1; -+ uint32_t DISABLE_INBAND:1; -+ uint32_t DISABLE_SIDEBAND:1; -+ } bits; -+ uint32_t raw; -+ } flags; -+}; -+ -+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 encoder_feature_support { -+ union { -+ struct { -+ /* 1 - external encoder; 0 - internal encoder */ -+ uint32_t EXTERNAL_ENCODER:1; -+ uint32_t ANALOG_ENCODER:1; -+ uint32_t STEREO_SYNC:1; -+ /* check the DDC data pin -+ * when performing DP Sink detection */ -+ uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1; -+ /* CPLIB authentication -+ * for external DP chip supported */ -+ uint32_t CPLIB_DP_AUTHENTICATION:1; -+ uint32_t IS_HBR2_CAPABLE:1; -+ uint32_t IS_HBR2_VALIDATED:1; -+ uint32_t IS_TPS3_CAPABLE:1; -+ uint32_t IS_AUDIO_CAPABLE:1; -+ uint32_t IS_VCE_SUPPORTED:1; -+ uint32_t IS_CONVERTER:1; -+ uint32_t IS_Y_ONLY_CAPABLE:1; -+ uint32_t IS_YCBCR_CAPABLE:1; -+ } bits; -+ uint32_t raw; -+ } flags; -+ /* maximum supported deep color depth */ -+ enum dc_color_depth max_deep_color; -+ /* maximum supported clock */ -+ uint32_t max_pixel_clock; -+}; -+ -+enum dig_encoder_mode { -+ DIG_ENCODER_MODE_DP, -+ DIG_ENCODER_MODE_LVDS, -+ DIG_ENCODER_MODE_DVI, -+ DIG_ENCODER_MODE_HDMI, -+ DIG_ENCODER_MODE_SDVO, -+ DIG_ENCODER_MODE_DP_WITH_AUDIO, -+ DIG_ENCODER_MODE_DP_MST, -+ -+ /* direct HW translation ! */ -+ DIG_ENCODER_MODE_TV = 13, -+ DIG_ENCODER_MODE_CV, -+ DIG_ENCODER_MODE_CRT -+}; -+ -+#endif -+ -diff --git a/drivers/gpu/drm/amd/dal/include/fixed31_32.h b/drivers/gpu/drm/amd/dal/include/fixed31_32.h -new file mode 100644 -index 0000000..507f9f6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/fixed31_32.h -@@ -0,0 +1,389 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_FIXED31_32_H__ -+#define __DAL_FIXED31_32_H__ -+ -+/* -+ * @brief -+ * Arithmetic operations on real numbers -+ * represented as fixed-point numbers. -+ * There are: 1 bit for sign, -+ * 31 bit for integer part, -+ * 32 bits for fractional part. -+ * -+ * @note -+ * Currently, overflows and underflows are asserted; -+ * no special result returned. -+ */ -+ -+struct fixed31_32 { -+ int64_t value; -+}; -+ -+/* -+ * @brief -+ * Useful constants -+ */ -+ -+static const struct fixed31_32 dal_fixed31_32_zero = { 0 }; -+static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL }; -+static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL }; -+static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL }; -+ -+static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL }; -+static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL }; -+static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL }; -+static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL }; -+static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL }; -+ -+/* -+ * @brief -+ * Initialization routines -+ */ -+ -+/* -+ * @brief -+ * result = numerator / denominator -+ */ -+struct fixed31_32 dal_fixed31_32_from_fraction( -+ int64_t numerator, -+ int64_t denominator); -+ -+/* -+ * @brief -+ * result = arg -+ */ -+struct fixed31_32 dal_fixed31_32_from_int( -+ int64_t arg); -+ -+/* -+ * @brief -+ * Unary operators -+ */ -+ -+/* -+ * @brief -+ * result = -arg -+ */ -+struct fixed31_32 dal_fixed31_32_neg( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = abs(arg) := (arg >= 0) ? arg : -arg -+ */ -+struct fixed31_32 dal_fixed31_32_abs( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * Binary relational operators -+ */ -+ -+/* -+ * @brief -+ * result = arg1 < arg2 -+ */ -+bool dal_fixed31_32_lt( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = arg1 <= arg2 -+ */ -+bool dal_fixed31_32_le( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = arg1 == arg2 -+ */ -+bool dal_fixed31_32_eq( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_min( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 -+ */ -+struct fixed31_32 dal_fixed31_32_max( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * | min_value, when arg <= min_value -+ * result = | arg, when min_value < arg < max_value -+ * | max_value, when arg >= max_value -+ */ -+struct fixed31_32 dal_fixed31_32_clamp( -+ struct fixed31_32 arg, -+ struct fixed31_32 min_value, -+ struct fixed31_32 max_value); -+ -+/* -+ * @brief -+ * Binary shift operators -+ */ -+ -+/* -+ * @brief -+ * result = arg << shift -+ */ -+struct fixed31_32 dal_fixed31_32_shl( -+ struct fixed31_32 arg, -+ uint8_t shift); -+ -+/* -+ * @brief -+ * result = arg >> shift -+ */ -+struct fixed31_32 dal_fixed31_32_shr( -+ struct fixed31_32 arg, -+ uint8_t shift); -+ -+/* -+ * @brief -+ * Binary additive operators -+ */ -+ -+/* -+ * @brief -+ * result = arg1 + arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_add( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = arg1 - arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_sub_int( -+ struct fixed31_32 arg1, -+ int32_t arg2); -+ -+/* -+ * @brief -+ * result = arg1 - arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_sub( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * Binary multiplicative operators -+ */ -+ -+/* -+ * @brief -+ * result = arg1 * arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_mul_int( -+ struct fixed31_32 arg1, -+ int32_t arg2); -+ -+/* -+ * @brief -+ * result = arg1 * arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_mul( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * result = square(arg) := arg * arg -+ */ -+struct fixed31_32 dal_fixed31_32_sqr( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = arg1 / arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_div_int( -+ struct fixed31_32 arg1, -+ int64_t arg2); -+ -+/* -+ * @brief -+ * result = arg1 / arg2 -+ */ -+struct fixed31_32 dal_fixed31_32_div( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * Reciprocal function -+ */ -+ -+/* -+ * @brief -+ * result = reciprocal(arg) := 1 / arg -+ * -+ * @note -+ * No special actions taken in case argument is zero. -+ */ -+struct fixed31_32 dal_fixed31_32_recip( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * Trigonometric functions -+ */ -+ -+/* -+ * @brief -+ * result = sinc(arg) := sin(arg) / arg -+ * -+ * @note -+ * Argument specified in radians, -+ * internally it's normalized to [-2pi...2pi] range. -+ */ -+struct fixed31_32 dal_fixed31_32_sinc( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = sin(arg) -+ * -+ * @note -+ * Argument specified in radians, -+ * internally it's normalized to [-2pi...2pi] range. -+ */ -+struct fixed31_32 dal_fixed31_32_sin( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = cos(arg) -+ * -+ * @note -+ * Argument specified in radians -+ * and should be in [-2pi...2pi] range - -+ * passing arguments outside that range -+ * will cause incorrect result! -+ */ -+struct fixed31_32 dal_fixed31_32_cos( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * Transcendent functions -+ */ -+ -+/* -+ * @brief -+ * result = exp(arg) -+ * -+ * @note -+ * Currently, function is verified for abs(arg) <= 1. -+ */ -+struct fixed31_32 dal_fixed31_32_exp( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = log(arg) -+ * -+ * @note -+ * Currently, abs(arg) should be less than 1. -+ * No normalization is done. -+ * Currently, no special actions taken -+ * in case of invalid argument(s). Take care! -+ */ -+struct fixed31_32 dal_fixed31_32_log( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * Power function -+ */ -+ -+/* -+ * @brief -+ * result = pow(arg1, arg2) -+ * -+ * @note -+ * Currently, abs(arg1) should be less than 1. Take care! -+ */ -+struct fixed31_32 dal_fixed31_32_pow( -+ struct fixed31_32 arg1, -+ struct fixed31_32 arg2); -+ -+/* -+ * @brief -+ * Rounding functions -+ */ -+ -+/* -+ * @brief -+ * result = floor(arg) := greatest integer lower than or equal to arg -+ */ -+int32_t dal_fixed31_32_floor( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = round(arg) := integer nearest to arg -+ */ -+int32_t dal_fixed31_32_round( -+ struct fixed31_32 arg); -+ -+/* -+ * @brief -+ * result = ceil(arg) := lowest integer greater than or equal to arg -+ */ -+int32_t dal_fixed31_32_ceil( -+ struct fixed31_32 arg); -+ -+/* the following two function are used in scaler hw programming to convert fixed -+ * point value to format 2 bits from integer part and 19 bits from fractional -+ * part. The same applies for u0d19, 0 bits from integer part and 19 bits from -+ * fractional -+ */ -+ -+uint32_t dal_fixed31_32_u2d19( -+ struct fixed31_32 arg); -+ -+uint32_t dal_fixed31_32_u0d19( -+ struct fixed31_32 arg); -+ -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/fixed32_32.h b/drivers/gpu/drm/amd/dal/include/fixed32_32.h -new file mode 100644 -index 0000000..5fca957 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/fixed32_32.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_FIXED32_32_H__ -+#define __DAL_FIXED32_32_H__ -+ -+struct fixed32_32 { -+ uint64_t value; -+}; -+ -+static const struct fixed32_32 dal_fixed32_32_zero = { 0 }; -+static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL }; -+static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL }; -+ -+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d); -+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value); -+struct fixed32_32 dal_fixed32_32_add( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+struct fixed32_32 dal_fixed32_32_add_int( -+ struct fixed32_32 lhs, -+ uint32_t rhs); -+struct fixed32_32 dal_fixed32_32_sub( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+struct fixed32_32 dal_fixed32_32_sub_int( -+ struct fixed32_32 lhs, -+ uint32_t rhs); -+struct fixed32_32 dal_fixed32_32_mul( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+struct fixed32_32 dal_fixed32_32_mul_int( -+ struct fixed32_32 lhs, -+ uint32_t rhs); -+struct fixed32_32 dal_fixed32_32_div( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+struct fixed32_32 dal_fixed32_32_div_int( -+ struct fixed32_32 lhs, -+ uint32_t rhs); -+struct fixed32_32 dal_fixed32_32_min( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+struct fixed32_32 dal_fixed32_32_max( -+ struct fixed32_32 lhs, -+ struct fixed32_32 rhs); -+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs); -+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs); -+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs); -+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs); -+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs); -+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs); -+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs); -+uint32_t dal_fixed32_32_ceil(struct fixed32_32 value); -+uint32_t dal_fixed32_32_floor(struct fixed32_32 value); -+uint32_t dal_fixed32_32_round(struct fixed32_32 value); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/gpio_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_interface.h -new file mode 100644 -index 0000000..a084d79 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/gpio_interface.h -@@ -0,0 +1,93 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GPIO_INTERFACE_H__ -+#define __DAL_GPIO_INTERFACE_H__ -+ -+#include "gpio_types.h" -+#include "grph_object_defs.h" -+ -+struct gpio; -+ -+/* Open the handle for future use */ -+enum gpio_result dal_gpio_open( -+ struct gpio *gpio, -+ enum gpio_mode mode); -+ -+enum gpio_result dal_gpio_open_ex( -+ struct gpio *gpio, -+ enum gpio_mode mode, -+ void *options); -+ -+/* Get high or low from the pin */ -+enum gpio_result dal_gpio_get_value( -+ const struct gpio *gpio, -+ uint32_t *value); -+ -+/* Set pin high or low */ -+enum gpio_result dal_gpio_set_value( -+ const struct gpio *gpio, -+ uint32_t value); -+ -+/* Get current mode */ -+enum gpio_mode dal_gpio_get_mode( -+ const struct gpio *gpio); -+ -+/* Change mode of the handle */ -+enum gpio_result dal_gpio_change_mode( -+ struct gpio *gpio, -+ enum gpio_mode mode); -+ -+/* Get the GPIO id */ -+enum gpio_id dal_gpio_get_id( -+ const struct gpio *gpio); -+ -+/* Get the GPIO enum */ -+uint32_t dal_gpio_get_enum( -+ const struct gpio *gpio); -+ -+/* Set the GPIO pin configuration */ -+enum gpio_result dal_gpio_set_config( -+ struct gpio *gpio, -+ const struct gpio_config_data *config_data); -+ -+/* Obtain GPIO pin info */ -+enum gpio_result dal_gpio_get_pin_info( -+ const struct gpio *gpio, -+ struct gpio_pin_info *pin_info); -+ -+/* Obtain GPIO sync source */ -+enum sync_source dal_gpio_get_sync_source( -+ const struct gpio *gpio); -+ -+/* Obtain GPIO pin output state (active low or active high) */ -+enum gpio_pin_output_state dal_gpio_get_output_state( -+ const struct gpio *gpio); -+ -+/* Close the handle */ -+void dal_gpio_close( -+ struct gpio *gpio); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h -new file mode 100644 -index 0000000..b22bb1b ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h -@@ -0,0 +1,94 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "dvo_interface.h" -+#include "ddc_interface.h" -+#include "irq_interface.h" -+ -+struct gpio_service; -+ -+struct gpio_service *dal_gpio_service_create( -+ enum dce_version dce_version, -+ struct dc_context *ctx); -+ -+struct gpio *dal_gpio_service_create_gpio( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ enum gpio_pin_output_state output_state); -+ -+struct gpio *dal_gpio_service_create_gpio_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en, -+ enum gpio_pin_output_state output_state); -+ -+void dal_gpio_service_destroy_gpio( -+ struct gpio **gpio); -+ -+struct ddc *dal_gpio_service_create_ddc( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask, -+ struct gpio_ddc_hw_info *info); -+ -+void dal_gpio_service_destroy_ddc( -+ struct ddc **ddc); -+ -+struct dvo *dal_gpio_service_create_dvo( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask); -+ -+struct dvo *dal_gpio_service_create_dvo_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en); -+ -+void dal_gpio_service_destroy_dvo( -+ struct dvo **ptr); -+ -+struct irq *dal_gpio_service_create_irq( -+ struct gpio_service *service, -+ uint32_t offset, -+ uint32_t mask); -+ -+struct irq *dal_gpio_service_create_irq_ex( -+ struct gpio_service *service, -+ enum gpio_id id, -+ uint32_t en); -+ -+void dal_gpio_service_destroy_irq( -+ struct irq **ptr); -+ -+void dal_gpio_service_destroy( -+ struct gpio_service **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/gpio_types.h b/drivers/gpu/drm/amd/dal/include/gpio_types.h -new file mode 100644 -index 0000000..d616d62 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/gpio_types.h -@@ -0,0 +1,393 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_DVO1, -+ GPIO_ID_DVO12, -+ GPIO_ID_DVO24, -+ 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_DVO1, -+ 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_dvo1 { -+ GPIO_DVO1_UNKNOWN = (-1), -+ GPIO_DVO1_0, -+ GPIO_DVO1_1, -+ GPIO_DVO1_2, -+ GPIO_DVO1_3, -+ GPIO_DVO1_4, -+ GPIO_DVO1_5, -+ GPIO_DVO1_6, -+ GPIO_DVO1_7, -+ GPIO_DVO1_8, -+ GPIO_DVO1_9, -+ GPIO_DVO1_10, -+ GPIO_DVO1_11, -+ GPIO_DVO1_12, -+ GPIO_DVO1_13, -+ GPIO_DVO1_14, -+ GPIO_DVO1_15, -+ GPIO_DVO1_16, -+ GPIO_DVO1_17, -+ GPIO_DVO1_18, -+ GPIO_DVO1_19, -+ GPIO_DVO1_20, -+ GPIO_DVO1_21, -+ GPIO_DVO1_22, -+ GPIO_DVO1_23, -+ GPIO_DVO1_COUNT, -+ GPIO_DVO1_MIN = GPIO_DVO1_0, -+ GPIO_DVO1_MAX = GPIO_DVO1_23 -+}; -+ -+enum gpio_dvo12 { -+ GPIO_DVO12_UNKNOWN = (-1), -+ GPIO_DVO12_A, -+ GPIO_DVO12_B, -+ GPIO_DVO12_COUNT, -+ GPIO_DVO12_MIN = GPIO_DVO12_A, -+ GPIO_DVO12_MAX = GPIO_DVO12_B -+}; -+ -+enum gpio_dvo24 { -+ GPIO_DVO24_UNKNOWN = (-1), -+ GPIO_DVO24_A, -+ GPIO_DVO24_COUNT, -+ GPIO_DVO24_MIN = GPIO_DVO24_A, -+ GPIO_DVO24_MAX = GPIO_DVO24_A -+}; -+ -+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, -+ GPIO_SIGNAL_SOURCE_DVO_STEREO_SYNC -+}; -+ -+enum gpio_stereo_source { -+ GPIO_STEREO_SOURCE_UNKNOWN = (-1), -+ GPIO_STEREO_SOURCE_D1, -+ GPIO_STEREO_SOURCE_D2, -+ GPIO_STEREO_SOURCE_D3, -+ GPIO_STEREO_SOURCE_D4, -+ GPIO_STEREO_SOURCE_D5, -+ GPIO_STEREO_SOURCE_D6 -+}; -+ -+/* -+ * GPIO config -+ */ -+ -+enum gpio_config_type { -+ GPIO_CONFIG_TYPE_NONE, -+ GPIO_CONFIG_TYPE_DDC, -+ GPIO_CONFIG_TYPE_HPD, -+ GPIO_CONFIG_TYPE_GENERIC_MUX, -+ GPIO_CONFIG_TYPE_GSL_MUX, -+ GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE -+}; -+ -+/* DDC configuration */ -+ -+enum gpio_ddc_config_type { -+ GPIO_DDC_CONFIG_TYPE_MODE_AUX, -+ GPIO_DDC_CONFIG_TYPE_MODE_I2C, -+ GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT, -+ GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT, -+ GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING -+}; -+ -+struct gpio_ddc_config { -+ enum gpio_ddc_config_type type; -+ bool data_en_bit_present; -+ bool clock_en_bit_present; -+}; -+ -+/* HPD configuration */ -+ -+struct gpio_hpd_config { -+ uint32_t delay_on_connect; /* milliseconds */ -+ uint32_t delay_on_disconnect; /* milliseconds */ -+}; -+ -+struct gpio_generic_mux_config { -+ bool enable_output_from_mux; -+ enum gpio_signal_source mux_select; -+ enum gpio_stereo_source stereo_select; -+}; -+ -+enum gpio_gsl_mux_config_type { -+ GPIO_GSL_MUX_CONFIG_TYPE_DISABLE, -+ GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC, -+ GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC -+}; -+ -+struct gpio_gsl_mux_config { -+ enum gpio_gsl_mux_config_type type; -+ /* Actually sync_source type, -+ * however we want to avoid inter-component includes here */ -+ uint32_t gsl_group; -+}; -+ -+struct gpio_config_data { -+ enum gpio_config_type type; -+ union { -+ struct gpio_ddc_config ddc; -+ struct gpio_hpd_config hpd; -+ struct gpio_generic_mux_config generic_mux; -+ struct gpio_gsl_mux_config gsl_mux; -+ } config; -+}; -+ -+struct gpio_ddc_hw_info { -+ bool hw_supported; -+ uint32_t ddc_channel; -+}; -+ -+struct gpio_ddc_open_options { -+ bool en_bit_present; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/gpu_clock_info.h b/drivers/gpu/drm/amd/dal/include/gpu_clock_info.h -new file mode 100644 -index 0000000..c9b47b2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/gpu_clock_info.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_GPU_CLOCK_INFO__ -+#define __DAL_GPU_CLOCK_INFO__ -+ -+#include "include/gpu_interface.h" -+ -+/*TODO this structures should be defined*/ -+struct gpu_static_clk_info; -+struct gpu_dynamic_clk_info; -+ -+bool init_static_clk_info( -+ struct gpu *gpu, -+ struct gpu_static_clk_info *st_clk_info); -+ -+bool update_dynamic_clk_info( -+ struct gpu *gpu, -+ struct gpu_dynamic_clk_info *dyn_clk_info); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/gpu_interface.h b/drivers/gpu/drm/amd/dal/include/gpu_interface.h -new file mode 100644 -index 0000000..63262c3 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/gpu_interface.h -@@ -0,0 +1,91 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GPU_INTERFACE__ -+#define __DAL_GPU_INTERFACE__ -+ -+#include "include/adapter_service_interface.h" -+#include "include/grph_object_ctrl_defs.h" -+ -+enum gpu_clocks_state { -+ GPU_CLOCKS_STATE_INVALID, -+ GPU_CLOCKS_STATE_ULTRA_LOW, -+ GPU_CLOCKS_STATE_LOW, -+ GPU_CLOCKS_STATE_NOMINAL, -+ GPU_CLOCKS_STATE_PERFORMANCE -+}; -+ -+struct gpu_clock_info { -+ uint32_t min_sclk_khz; -+ uint32_t max_sclk_khz; -+ -+ uint32_t min_mclk_khz; -+ uint32_t max_mclk_khz; -+ -+ uint32_t min_dclk_khz; -+ uint32_t max_dclk_khz; -+}; -+ -+struct gpu; -+struct irq_manager; -+ -+struct gpu_init_data { -+ struct dc_context *ctx; -+ struct adapter_service *adapter_service; -+ struct irq_manager *irq_manager; -+}; -+ -+struct gpu *dal_gpu_create(struct gpu_init_data *init_data); -+void dal_gpu_destroy(struct gpu **); -+ -+void dal_gpu_power_up(struct gpu *); -+void dal_gpu_power_down( -+ struct gpu *gpu, -+ enum dc_video_power_state power_state); -+void dal_gpu_light_sleep_vbios_wa(struct gpu *gpu, bool enable); -+void dal_gpu_release_hw(struct gpu *gpu); -+ -+uint32_t dal_gpu_get_num_of_functional_controllers(const struct gpu *gpu); -+uint32_t dal_gpu_get_max_num_of_primary_controllers(const struct gpu *gpu); -+uint32_t dal_gpu_get_max_num_of_underlay_controllers(const struct gpu *gpu); -+struct controller *dal_gpu_create_controller( -+ struct gpu *gpu, -+ uint32_t index); -+uint32_t dal_gpu_get_num_of_clock_sources(const struct gpu *gpu); -+struct clock_source *dal_gpu_create_clock_source( -+ struct gpu *gpu, -+ uint32_t index); -+ -+/* gpu_clock_interface implementation */ -+bool dal_gpu_init_static_clock_info(struct gpu *gpu, -+ struct gpu_clock_info *gpu_clk_info); -+ -+bool dal_gpu_update_dynamic_clock_info(struct gpu *gpu, -+ struct gpu_clock_info *gpu_clk_info); -+ -+void dal_gpu_get_static_clock_info(struct gpu *gpu, -+ struct gpu_clock_info *gpu_clk_info); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h -new file mode 100644 -index 0000000..711b458 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h -@@ -0,0 +1,98 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GRPH_CSC_TYPES_H__ -+#define __DAL_GRPH_CSC_TYPES_H__ -+ -+#include "set_mode_types.h" -+ -+enum color_space { -+ COLOR_SPACE_UNKNOWN, -+ COLOR_SPACE_SRGB_FULL_RANGE, -+ COLOR_SPACE_SRGB_LIMITED_RANGE, -+ COLOR_SPACE_YPBPR601, -+ COLOR_SPACE_YPBPR709, -+ COLOR_SPACE_YCBCR601, -+ COLOR_SPACE_YCBCR709, -+ COLOR_SPACE_YCBCR601_YONLY, -+ COLOR_SPACE_YCBCR709_YONLY, -+ COLOR_SPACE_N_MVPU_SUPER_AA, -+}; -+ -+enum grph_color_adjust_option { -+ GRPH_COLOR_MATRIX_HW_DEFAULT = 1, -+ GRPH_COLOR_MATRIX_SW -+}; -+ -+enum grph_csc_adjust_item { -+ GRPH_ADJUSTMENT_CONTRAST = 1, -+ GRPH_ADJUSTMENT_SATURATION, -+ GRPH_ADJUSTMENT_BRIGHTNESS, -+ GRPH_ADJUSTMENT_HUE, -+ GRPH_ADJUSTMENT_COLOR_TEMPERATURE -+}; -+ -+#define CSC_TEMPERATURE_MATRIX_SIZE 9 -+ -+enum graphics_csc_adjust_type { -+ GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, -+ GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ -+ GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ -+}; -+ -+enum graphics_gamut_adjust_type { -+ GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0, -+ GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */ -+ GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ -+}; -+ -+struct grph_csc_adjustment { -+ enum grph_color_adjust_option color_adjust_option; -+ enum color_space c_space; -+ int32_t grph_cont; -+ int32_t grph_sat; -+ int32_t grph_bright; -+ int32_t grph_hue; -+ int32_t adjust_divider; -+ int32_t temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; -+ int32_t temperature_divider; -+ uint32_t lb_color_depth; -+ uint8_t gamma; /* gamma from Edid */ -+ enum dc_color_depth color_depth; /* clean up to uint32_t */ -+ enum pixel_format surface_pixel_format; -+ enum graphics_csc_adjust_type csc_adjust_type; -+ enum graphics_gamut_adjust_type gamut_adjust_type; -+}; -+ -+struct default_adjustment { -+ uint32_t lb_color_depth; -+ enum color_space color_space; -+ enum dc_color_depth color_depth; -+ enum pixel_format surface_pixel_format; -+ enum graphics_csc_adjust_type csc_adjust_type; -+ bool force_hw_default; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h -new file mode 100644 -index 0000000..d804109 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h -@@ -0,0 +1,598 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__ -+#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__ -+ -+#include "grph_object_defs.h" -+ -+/* -+ * ##################################################### -+ * ##################################################### -+ * -+ * These defines shared between asic_control/bios_parser and other -+ * DAL components -+ * -+ * ##################################################### -+ * ##################################################### -+ */ -+ -+enum tv_standard { -+ TV_STANDARD_UNKNOWN = 0, /* direct HW (mmBIOS_SCRATCH_2) translation! */ -+ TV_STANDARD_NTSC, -+ TV_STANDARD_NTSCJ, -+ TV_STANDARD_PAL, -+ TV_STANDARD_PALM, -+ TV_STANDARD_PALCN, -+ TV_STANDARD_PALN, -+ TV_STANDARD_PAL60, -+ TV_STANDARD_SECAM -+}; -+ -+enum cv_standard { -+ CV_STANDARD_UNKNOWN = 0x0000, -+ CV_STANDARD_HD_MASK = 0x0800, /* Flag mask HDTV output */ -+ CV_STANDARD_SD_NTSC_MASK = 0x1000, /* Flag mask NTSC output */ -+ CV_STANDARD_SD_NTSC_M, /* NTSC (North America) output 1001 */ -+ CV_STANDARD_SD_NTSC_J, /* NTSC (Japan) output 1002 */ -+ CV_STANDARD_SD_480I, /* SDTV 480i output 1003 */ -+ CV_STANDARD_SD_480P, /* SDTV 480p output 1004 */ -+ CV_STANDARD_HD_720_60P = 0x1800,/* HDTV 720/60p output 1800 */ -+ CV_STANDARD_HD_1080_60I, /* HDTV 1080/60i output 1801 */ -+ CV_STANDARD_SD_PAL_MASK = 0x2000,/* Flag mask PAL output */ -+ CV_STANDARD_SD_PAL_B, /* PAL B output 2001 */ -+ CV_STANDARD_SD_PAL_D, /* PAL D output 2002 */ -+ CV_STANDARD_SD_PAL_G, /* PAL G output 2003 */ -+ CV_STANDARD_SD_PAL_H, /* PAL H output 2004 */ -+ CV_STANDARD_SD_PAL_I, /* PAL I output 2005 */ -+ CV_STANDARD_SD_PAL_M, /* PAL M output 2006 */ -+ CV_STANDARD_SD_PAL_N, /* PAL N output 2007 */ -+ CV_STANDARD_SD_PAL_N_COMB, /* PAL Combination N output 2008 */ -+ CV_STANDARD_SD_PAL_60, /* PAL 60 output (test mode) 2009 */ -+ CV_STANDARD_SD_576I, /* SDTV 576i output 2010 */ -+ CV_STANDARD_SD_576P, /* SDTV 576p output 2011 */ -+ CV_STANDARD_HD_720_50P = 0x2800,/* HDTV 720/50p output 2800 */ -+ CV_STANDARD_HD_1080_50I, /* HDTV 1080/50i output 2801 */ -+ CV_STANDARD_SD_SECAM_MASK = 0x4000, /* Flag mask SECAM output */ -+ CV_STANDARD_SD_SECAM_B, /* SECAM B output 4001 */ -+ CV_STANDARD_SD_SECAM_D, /* SECAM D output 4002 */ -+ CV_STANDARD_SD_SECAM_G, /* SECAM G output 4003 */ -+ CV_STANDARD_SD_SECAM_H, /* SECAM H output 4004 */ -+ CV_STANDARD_SD_SECAM_K, /* SECAM K output 4005 */ -+ CV_STANDARD_SD_SECAM_K1, /* SECAM K1 output 4006 */ -+ CV_STANDARD_SD_SECAM_L, /* SECAM L output 4007 */ -+ CV_STANDARD_SD_SECAM_L1 /* SECAM L1 output 4009 */ -+}; -+ -+enum disp_pll_config { -+ DISP_PLL_CONFIG_UNKNOWN = 0, -+ DISP_PLL_CONFIG_DVO_DDR_MODE_LOW_12BIT, -+ DISP_PLL_CONFIG_DVO_DDR_MODE_UPPER_12BIT, -+ DISP_PLL_CONFIG_DVO_DDR_MODE_24BIT -+}; -+ -+enum display_output_bit_depth { -+ PANEL_UNDEFINE = 0, -+ PANEL_6BIT_COLOR = 1, -+ PANEL_8BIT_COLOR = 2, -+ PANEL_10BIT_COLOR = 3, -+ PANEL_12BIT_COLOR = 4, -+ PANEL_16BIT_COLOR = 5, -+}; -+ -+enum lcd_scale { -+ /* No request to turn on LCD SCALER (Centering or Replication) */ -+ LCD_SCALE_NONE = 0, -+ /* Request LCD SCALER in full panel mode */ -+ LCD_SCALE_FULLPANEL, -+ /* Request LCD SCALER in aspect-ratio mode */ -+ LCD_SCALE_ASPECTRATIO, -+ -+ LCD_SCALE_UNKNOWN = (-1L), -+}; -+ -+/* Device type as abstracted by ATOM BIOS */ -+enum dal_device_type { -+ DEVICE_TYPE_UNKNOWN = 0, -+ DEVICE_TYPE_LCD, -+ DEVICE_TYPE_CRT, -+ DEVICE_TYPE_DFP, -+ DEVICE_TYPE_CV, -+ DEVICE_TYPE_TV, -+ DEVICE_TYPE_CF, -+ DEVICE_TYPE_WIRELESS -+}; -+ -+/* Device ID as abstracted by ATOM BIOS */ -+struct device_id { -+ enum dal_device_type device_type:16; -+ uint32_t enum_id:16; /* 1 based enum */ -+}; -+ -+struct graphics_object_i2c_info { -+ struct gpio_info { -+ uint32_t clk_mask_register_index; -+ uint32_t clk_en_register_index; -+ uint32_t clk_y_register_index; -+ uint32_t clk_a_register_index; -+ uint32_t data_mask_register_index; -+ uint32_t data_en_register_index; -+ uint32_t data_y_register_index; -+ uint32_t data_a_register_index; -+ -+ uint32_t clk_mask_shift; -+ uint32_t clk_en_shift; -+ uint32_t clk_y_shift; -+ uint32_t clk_a_shift; -+ uint32_t data_mask_shift; -+ uint32_t data_en_shift; -+ uint32_t data_y_shift; -+ uint32_t data_a_shift; -+ } gpio_info; -+ -+ bool i2c_hw_assist; -+ uint32_t i2c_line; -+ uint32_t i2c_engine_id; -+ uint32_t i2c_slave_address; -+}; -+ -+ -+struct graphics_object_hpd_info { -+ uint8_t hpd_int_gpio_uid; -+ uint8_t hpd_active; -+}; -+ -+struct connector_device_tag_info { -+ uint32_t acpi_device; -+ struct device_id dev_id; -+}; -+ -+struct device_timing { -+ struct misc_info { -+ uint32_t HORIZONTAL_CUT_OFF:1; -+ /* 0=Active High, 1=Active Low */ -+ uint32_t H_SYNC_POLARITY:1; -+ /* 0=Active High, 1=Active Low */ -+ uint32_t V_SYNC_POLARITY:1; -+ uint32_t VERTICAL_CUT_OFF:1; -+ uint32_t H_REPLICATION_BY2:1; -+ uint32_t V_REPLICATION_BY2:1; -+ uint32_t COMPOSITE_SYNC:1; -+ uint32_t INTERLACE:1; -+ uint32_t DOUBLE_CLOCK:1; -+ uint32_t RGB888:1; -+ uint32_t GREY_LEVEL:2; -+ uint32_t SPATIAL:1; -+ uint32_t TEMPORAL:1; -+ uint32_t API_ENABLED:1; -+ } misc_info; -+ -+ uint32_t pixel_clk; /* in KHz */ -+ uint32_t horizontal_addressable; -+ uint32_t horizontal_blanking_time; -+ uint32_t vertical_addressable; -+ uint32_t vertical_blanking_time; -+ uint32_t horizontal_sync_offset; -+ uint32_t horizontal_sync_width; -+ uint32_t vertical_sync_offset; -+ uint32_t vertical_sync_width; -+ uint32_t horizontal_border; -+ uint32_t vertical_border; -+}; -+ -+struct supported_refresh_rate { -+ uint32_t REFRESH_RATE_30HZ:1; -+ uint32_t REFRESH_RATE_40HZ:1; -+ uint32_t REFRESH_RATE_48HZ:1; -+ uint32_t REFRESH_RATE_50HZ:1; -+ uint32_t REFRESH_RATE_60HZ:1; -+}; -+ -+struct embedded_panel_info { -+ struct device_timing lcd_timing; -+ uint32_t ss_id; -+ struct supported_refresh_rate supported_rr; -+ uint32_t drr_enabled; -+ uint32_t min_drr_refresh_rate; -+}; -+ -+struct embedded_panel_patch_mode { -+ uint32_t width; -+ uint32_t height; -+}; -+ -+struct firmware_info { -+ struct pll_info { -+ uint32_t crystal_frequency; /* in KHz */ -+ uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */ -+ uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */ -+ uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */ -+ uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */ -+ } pll_info; -+ -+ struct firmware_feature { -+ uint32_t memory_clk_ss_percentage; -+ uint32_t engine_clk_ss_percentage; -+ } feature; -+ -+ uint32_t default_display_engine_pll_frequency; /* in KHz */ -+ uint32_t external_clock_source_frequency_for_dp; /* in KHz */ -+ uint32_t smu_gpu_pll_output_freq; /* in KHz */ -+ uint8_t min_allowed_bl_level; -+ uint8_t remote_display_config; -+}; -+ -+/* direct HW (mmBIOS_SCRATCH_2) translation! */ -+union tv_standard_support { -+ uint8_t u_all; -+ struct { -+ bool TV_SUPPORT_NTSC:1; -+ bool TV_SUPPORT_NTSCJ:1; -+ -+ bool TV_SUPPORT_PAL:1; -+ bool TV_SUPPORT_PALM:1; -+ bool TV_SUPPORT_PALCN:1; -+ bool TV_SUPPORT_PALN:1; -+ bool TV_SUPPORT_PAL60:1; -+ -+ bool TV_SUPPORT_SECAM:1; -+ } bits; -+}; -+ -+struct analog_tv_info { -+ union tv_standard_support tv_suppported; -+ union tv_standard_support tv_boot_up_default; -+}; -+ -+struct 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 { -+ uint32_t step; -+ uint32_t delay; -+ uint32_t recommended_ref_div; -+ } step_and_delay_info; -+ /* For mem/engine/uvd, Clock Out frequence (VCO ), -+ in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock, -+ for DP, it is link clock ( 270000 or 162000 ) */ -+ uint32_t target_clock_range; /* in KHz */ -+ }; -+ -+}; -+ -+struct graphics_object_encoder_cap_info { -+ uint32_t dp_hbr2_cap:1; -+ uint32_t dp_hbr2_validated:1; -+ uint32_t reserved:15; -+}; -+ -+struct din_connector_info { -+ uint32_t gpio_id; -+ bool gpio_tv_active_state; -+}; -+ -+/* Invalid channel mapping */ -+enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 }; -+ -+/** -+ * DDI PHY channel mapping reflecting XBAR setting -+ */ -+union ddi_channel_mapping { -+ struct mapping { -+ uint8_t lane0:2; /* Mapping for lane 0 */ -+ uint8_t lane1:2; /* Mapping for lane 1 */ -+ uint8_t lane2:2; /* Mapping for lane 2 */ -+ uint8_t lane3:2; /* Mapping for lane 3 */ -+ } mapping; -+ uint8_t raw; -+}; -+ -+/** -+* Transmitter output configuration description -+*/ -+struct transmitter_configuration_info { -+ /* DDI PHY ID for the transmitter */ -+ enum transmitter transmitter_phy_id; -+ /* DDI PHY channel mapping reflecting crossbar setting */ -+ union ddi_channel_mapping output_channel_mapping; -+}; -+ -+struct transmitter_configuration { -+ /* Configuration for the primary transmitter */ -+ struct transmitter_configuration_info primary_transmitter_config; -+ /* Secondary transmitter configuration for Dual-link DVI */ -+ struct transmitter_configuration_info secondary_transmitter_config; -+}; -+ -+ -+/* These size should be sufficient to store info coming from BIOS */ -+#define NUMBER_OF_UCHAR_FOR_GUID 16 -+#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7 -+#define NUMBER_OF_CSR_M3_ARB 10 -+#define NUMBER_OF_DISP_CLK_VOLTAGE 4 -+#define NUMBER_OF_AVAILABLE_SCLK 5 -+ -+/* V6 */ -+struct integrated_info { -+ struct clock_voltage_caps { -+ /* The Voltage Index indicated by FUSE, same voltage index -+ shared with SCLK DPM fuse table */ -+ uint32_t voltage_index; -+ /* Maximum clock supported with specified voltage index */ -+ uint32_t max_supported_clk; /* in KHz */ -+ } disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE]; -+ -+ struct display_connection_info { -+ struct external_display_path { -+ /* A bit vector to show what devices are supported */ -+ uint32_t device_tag; -+ /* 16bit device ACPI id. */ -+ uint32_t device_acpi_enum; -+ /* A physical connector for displays to plug in, -+ using object connector definitions */ -+ struct graphics_object_id device_connector_id; -+ /* An index into external AUX/DDC channel LUT */ -+ uint8_t ext_aux_ddc_lut_index; -+ /* An index into external HPD pin LUT */ -+ uint8_t ext_hpd_pin_lut_index; -+ /* external encoder object id */ -+ struct graphics_object_id ext_encoder_obj_id; -+ /* XBAR mapping of the PHY channels */ -+ union ddi_channel_mapping channel_mapping; -+ } path[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; -+ -+ uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID]; -+ uint8_t checksum; -+ } ext_disp_conn_info; /* exiting long long time */ -+ -+ struct available_s_clk_list { -+ /* Maximum clock supported with specified voltage index */ -+ uint32_t supported_s_clk; /* in KHz */ -+ /* The Voltage Index indicated by FUSE for specified SCLK */ -+ uint32_t voltage_index; -+ /* The Voltage ID indicated by FUSE for specified SCLK */ -+ uint32_t voltage_id; -+ } avail_s_clk[NUMBER_OF_AVAILABLE_SCLK]; -+ -+ uint8_t memory_type; -+ uint8_t ma_channel_number; -+ uint32_t boot_up_engine_clock; /* in KHz */ -+ uint32_t dentist_vco_freq; /* in KHz */ -+ uint32_t boot_up_uma_clock; /* in KHz */ -+ uint32_t boot_up_req_display_vector; -+ uint32_t other_display_misc; -+ uint32_t gpu_cap_info; -+ uint32_t sb_mmio_base_addr; -+ uint32_t system_config; -+ uint32_t cpu_cap_info; -+ uint32_t max_nb_voltage; -+ uint32_t min_nb_voltage; -+ uint32_t boot_up_nb_voltage; -+ uint32_t ext_disp_conn_info_offset; -+ uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB]; -+ uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB]; -+ uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB]; -+ uint32_t gmc_restore_reset_time; -+ uint32_t minimum_n_clk; -+ uint32_t idle_n_clk; -+ uint32_t ddr_dll_power_up_time; -+ uint32_t ddr_pll_power_up_time; -+ /* start for V6 */ -+ uint32_t pcie_clk_ss_type; -+ uint32_t lvds_ss_percentage; -+ uint32_t lvds_sspread_rate_in_10hz; -+ uint32_t hdmi_ss_percentage; -+ uint32_t hdmi_sspread_rate_in_10hz; -+ uint32_t dvi_ss_percentage; -+ uint32_t dvi_sspread_rate_in_10_hz; -+ uint32_t sclk_dpm_boost_margin; -+ uint32_t sclk_dpm_throttle_margin; -+ uint32_t sclk_dpm_tdp_limit_pg; -+ uint32_t sclk_dpm_tdp_limit_boost; -+ uint32_t boost_engine_clock; -+ uint32_t boost_vid_2bit; -+ uint32_t enable_boost; -+ uint32_t gnb_tdp_limit; -+ /* Start from V7 */ -+ uint32_t max_lvds_pclk_freq_in_single_link; -+ uint32_t lvds_misc; -+ uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms; -+ uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms; -+ uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms; -+ uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms; -+ uint32_t lvds_off_to_on_delay_in_4ms; -+ uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms; -+ uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms; -+ uint32_t lvds_reserved1; -+ uint32_t lvds_bit_depth_control_val; -+}; -+ -+/** -+* Power source ids. -+*/ -+enum power_source { -+ POWER_SOURCE_AC = 0, -+ POWER_SOURCE_DC, -+ POWER_SOURCE_LIMITED_POWER, -+ POWER_SOURCE_LIMITED_POWER_2, -+ POWER_SOURCE_MAX -+}; -+ -+struct bios_event_info { -+ uint32_t thermal_state; -+ uint32_t backlight_level; -+ enum power_source powerSource; -+ bool has_thermal_state_changed; -+ bool has_power_source_changed; -+ bool has_forced_mode_changed; -+ bool forced_mode; -+ bool backlight_changed; -+}; -+ -+union stereo_3d_support { -+ struct { -+ /* HW can alter left and right image sequentially */ -+ uint32_t FRAME_ALTERNATE:1; -+ /* Frame Alternate + HW can integrate stereosync -+ signal into TMDS stream */ -+ uint32_t DVI_FRAME_ALT:1; -+ /* Frame Alternate + HW can integrate stereosync -+ signal into DP stream */ -+ uint32_t DISPLAY_PORT_FRAME_ALT:1; -+ /* Frame Alternate + HW can drive stereosync signal -+ on separate line */ -+ uint32_t SIDEBAND_FRAME_ALT:1; -+ /* SW allowed to pack left and right image into single frame. -+ Used for HDMI only, DP has it's own flags. */ -+ uint32_t SW_FRAME_PACK:1; -+ /* HW can pack left and right image into single HDMI frame */ -+ uint32_t PROGRESSIVE_FRAME_PACK:1; -+ /* HW can pack left and right interlaced images into -+ single HDMI frame */ -+ uint32_t INTERLACE_FRAME_PACK:1; -+ /* HW can pack left and right images into single DP frame */ -+ uint32_t DISPLAY_PORT_FRAME_PACK:1; -+ /* SW can pack left and right images into single DP frame */ -+ uint32_t DISPLAY_PORT_SW_FRAME_PACK:1; -+ /* HW can mix left and right images into single image */ -+ uint32_t INTERLEAVE:1; -+ /* HW can mix left and right interlaced images -+ into single image */ -+ uint32_t INTERLACE_INTERLEAVE:1; -+ /* Allow display-based formats (whatever supported) -+ in WS stereo mode */ -+ uint32_t DISPLAY_3DIN_WS_MODE:1; -+ /* Side-by-side, packed by application/driver into 2D frame */ -+ uint32_t SIDE_BY_SIDE_SW_PACKED:1; -+ /* Top-and-bottom, packed by application/driver into 2D frame */ -+ uint32_t TOP_AND_BOTTOM_SW_PACKED:1; -+ } bits; -+ uint32_t u_all; -+}; -+ -+/* Bitvector and bitfields of possible optimizations -+ #IMPORTANT# Keep bitfields match bitvector! */ -+enum optimization_feature { -+ /* Don't do HW programming on panels that were enabled by VBIOS */ -+ OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY = 0x1, -+ OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME = 0x2, -+ OF_SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME = 0x4, -+ OF_SKIP_POWER_UP_VBIOS_ENABLED_ENCODER = 0x8, -+ /* Do not turn off VCC while powering down on boot or resume */ -+ OF_KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME = 0x10, -+ /* Do not turn off VCC while performing SetMode */ -+ OF_KEEP_VCC_DURING_SET_MODE = 0x20, -+ OF_DO_NOT_WAIT_FOR_HPD_LOW = 0x40, -+ OF_SKIP_POWER_DOWN_INACTIVE_ENCODER = 0x80 -+}; -+ -+union optimization_flags { -+ struct { -+ /* Don't do HW programming if panels were enabled by VBIOS */ -+ uint32_t SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:1; -+ uint32_t SKIP_RESET_OF_ALL_HW_ON_S3RESUME:1; -+ uint32_t SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME:1; -+ uint32_t SKIP_POWER_UP_VBIOS_ENABLED_ENCODER:1; -+ /* Do not turn off VCC while powering down on boot or resume */ -+ uint32_t KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME:1; -+ /* Do not turn off VCC while performing SetMode */ -+ uint32_t KEEP_VCC_DURING_SET_MODE:1; -+ uint32_t DO_NOT_WAIT_FOR_HPD_LOW:1; -+ } bits; -+ uint32_t u_all; -+}; -+ -+/* Bitvector and bitfields of performance measurements -+ #IMPORTANT# Keep bitfields match bitvector! */ -+enum perf_measure { -+ PERF_MEASURE_ADAPTER_POWER_STATE = 0x1, -+ PERF_MEASURE_DISPLAY_POWER_STATE = 0x2, -+ PERF_MEASURE_SET_MODE_SEQ = 0x4, -+ PERF_MEASURE_DETECT_AT_RESUME = 0x8, -+ PERF_MEASURE_MEMORY_READ_CONTROL = 0x10, -+}; -+ -+union perf_measure_flags { -+ struct { -+ uint32_t ADAPTER_POWER_STATE:1; -+ uint32_t DISPLAY_POWER_STATE:1; -+ uint32_t SET_MODE_SEQ:1; -+ uint32_t DETECT_AT_RESUME:1; -+ uint32_t MEMORY_READ_CONTROL:1; -+ -+ } bits; -+ uint32_t u_all; -+}; -+ -+enum { -+ PERF_MEASURE_POWERCODE_OFFSET = 0x0, -+ PERF_MEASURE_POWER_CODE_MASK = 0xFF, -+ PERF_MEASURE_POWER_STATE_OFFSET = 8, -+ PERF_MEASURE_POWER_STATE_MASK = 0x000FF00, -+ PERF_MEASURE_PREV_POWER_STATE_OFFSET = 16, -+ PERF_MEASURE_PREV_POWER_STATE_MASK = 0x00FF0000, -+ PERF_MEASURE_DISPLAY_INDEX_OFFSET = 24, -+ PERF_MEASURE_DISPLAY_INDEX_MASK = 0xFF000000 -+}; -+ -+enum { -+ HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000, -+ TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000 -+}; -+ -+/* -+ * DFS-bypass flag -+ */ -+/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */ -+enum { -+ DFS_BYPASS_ENABLE = 0x10 -+}; -+ -+enum { -+ INVALID_BACKLIGHT = -1 -+}; -+ -+struct panel_backlight_boundaries { -+ uint32_t min_signal_level; -+ uint32_t max_signal_level; -+}; -+ -+struct panel_backlight_default_levels { -+ uint32_t ac_level_percentage; -+ uint32_t dc_level_percentage; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h -new file mode 100644 -index 0000000..a1e468f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h -@@ -0,0 +1,328 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_GRPH_OBJECT_DEFS_H__ -+#define __DAL_GRPH_OBJECT_DEFS_H__ -+ -+#include "grph_object_id.h" -+ -+/* ******************************************************************** -+ * ******************************************************************** -+ * -+ * These defines shared between All Graphics Objects -+ * -+ * ******************************************************************** -+ * ******************************************************************** -+ */ -+ -+/* HPD unit id - HW direct translation */ -+enum hpd_source_id { -+ HPD_SOURCEID1 = 0, -+ HPD_SOURCEID2, -+ HPD_SOURCEID3, -+ HPD_SOURCEID4, -+ HPD_SOURCEID5, -+ HPD_SOURCEID6, -+ -+ HPD_SOURCEID_COUNT, -+ HPD_SOURCEID_UNKNOWN -+}; -+ -+/* DDC unit id - HW direct translation */ -+enum channel_id { -+ CHANNEL_ID_UNKNOWN = 0, -+ CHANNEL_ID_DDC1, -+ CHANNEL_ID_DDC2, -+ CHANNEL_ID_DDC3, -+ CHANNEL_ID_DDC4, -+ CHANNEL_ID_DDC5, -+ CHANNEL_ID_DDC6, -+ CHANNEL_ID_DDC_VGA, -+ CHANNEL_ID_I2C_PAD, -+ CHANNEL_ID_COUNT -+}; -+ -+#define DECODE_CHANNEL_ID(ch_id) \ -+ (ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \ -+ (ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \ -+ (ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \ -+ (ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \ -+ (ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \ -+ (ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \ -+ (ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \ -+ (ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid" -+ -+enum transmitter { -+ TRANSMITTER_UNKNOWN = (-1L), -+ TRANSMITTER_UNIPHY_A, -+ TRANSMITTER_UNIPHY_B, -+ TRANSMITTER_UNIPHY_C, -+ TRANSMITTER_UNIPHY_D, -+ TRANSMITTER_UNIPHY_E, -+ TRANSMITTER_UNIPHY_F, -+ TRANSMITTER_NUTMEG_CRT, -+ TRANSMITTER_TRAVIS_CRT, -+ TRANSMITTER_TRAVIS_LCD, -+ TRANSMITTER_UNIPHY_G, -+ TRANSMITTER_COUNT -+}; -+ -+enum physical_phy_id { -+ PHY_ID_UNKNOWN = (-1L), -+ PHY_ID_0, -+ PHY_ID_1, -+ PHY_ID_2, -+ PHY_ID_3, -+ PHY_ID_4, -+ PHY_ID_5, -+ PHY_ID_6, -+ PHY_ID_7, -+ PHY_ID_8, -+ PHY_ID_9, -+ PHY_ID_COUNT -+}; -+ -+/* Generic source of the synchronisation input/output signal */ -+/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */ -+enum sync_source { -+ SYNC_SOURCE_NONE = 0, -+ -+ /* Source based on controllers */ -+ SYNC_SOURCE_CONTROLLER0, -+ SYNC_SOURCE_CONTROLLER1, -+ SYNC_SOURCE_CONTROLLER2, -+ SYNC_SOURCE_CONTROLLER3, -+ SYNC_SOURCE_CONTROLLER4, -+ SYNC_SOURCE_CONTROLLER5, -+ -+ /* Source based on GSL group */ -+ SYNC_SOURCE_GSL_GROUP0, -+ SYNC_SOURCE_GSL_GROUP1, -+ SYNC_SOURCE_GSL_GROUP2, -+ -+ /* Source based on GSL IOs */ -+ /* These IOs normally used as GSL input/output */ -+ SYNC_SOURCE_GSL_IO_FIRST, -+ SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST, -+ SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC, -+ SYNC_SOURCE_GSL_IO_SWAPLOCK_A, -+ SYNC_SOURCE_GSL_IO_SWAPLOCK_B, -+ SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B, -+ -+ /* Source based on regular IOs */ -+ SYNC_SOURCE_IO_FIRST, -+ SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST, -+ SYNC_SOURCE_IO_GENERIC_B, -+ SYNC_SOURCE_IO_GENERIC_C, -+ SYNC_SOURCE_IO_GENERIC_D, -+ SYNC_SOURCE_IO_GENERIC_E, -+ SYNC_SOURCE_IO_GENERIC_F, -+ SYNC_SOURCE_IO_HPD1, -+ SYNC_SOURCE_IO_HPD2, -+ SYNC_SOURCE_IO_HSYNC_A, -+ SYNC_SOURCE_IO_VSYNC_A, -+ SYNC_SOURCE_IO_HSYNC_B, -+ SYNC_SOURCE_IO_VSYNC_B, -+ SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B, -+ -+ /* Misc. flow control sources */ -+ SYNC_SOURCE_DUAL_GPU_PIN -+}; -+ -+enum trigger_edge { -+ TRIGGER_EDGE_RISING = 0, -+ TRIGGER_EDGE_FALLING, -+ TRIGGER_EDGE_BOTH, -+ TRIGGER_EDGE_DEFAULT -+}; -+ -+/* Parameters to enable CRTC trigger */ -+struct trigger_params { -+ enum sync_source source; -+ enum trigger_edge edge; -+}; -+ -+/* CRTC Static Screen event triggers */ -+struct static_screen_events { -+ union { -+ /* event mask to enable/disable various -+ trigger sources for static screen detection */ -+ struct { -+ /* Force event high */ -+ uint32_t FRAME_START:1; -+ /* Cursor register change */ -+ uint32_t CURSOR_MOVE:1; -+ /* Memory write to any client other than MCIF */ -+ uint32_t MEM_WRITE:1; -+ /* Memory write to hit memory region 0 */ -+ uint32_t MEM_REGION0_WRITE:1; -+ /* Memory write to hit memory region 1 */ -+ uint32_t MEM_REGION1_WRITE:1; -+ /* Memory write to hit memory region 2 */ -+ uint32_t MEM_REGION2_WRITE:1; -+ /* Memory write to hit memory region 3 */ -+ uint32_t MEM_REGION3_WRITE:1; -+ /* Graphics Surface Update Pending */ -+ uint32_t GFX_UPDATE:1; -+ /* Overlay Surface Update Pending */ -+ uint32_t OVL_UPDATE:1; -+ /* Compressed surface invalidated in FBC */ -+ uint32_t INVALIDATE_FBC_SURFACE:1; -+ /* Register pending update in any double buffered -+ register group in the display pipe -+ (i.e. Blender, DCP, or SCL) */ -+ uint32_t REG_PENDING_UPDATE:1; -+ /* Crtc_trig_a: Based on signal from any other CRTC */ -+ uint32_t CRTC_TRIG_A:1; -+ /* Crtc_trig_b: Based on signal from any other CRTC */ -+ uint32_t CRTC_TRIG_B:1; -+ /* Readback of CRTC nominal vertical count register -+ by driver indicates that OS may be trying to change -+ mode or contents of the display therefore need to -+ switch to higher refresh rate */ -+ uint32_t READBACK_NOMINAL_VERTICAL:1; -+ /* Readback of CRTC dynamic vertical count register -+ by driver indicates that OS may be trying to change -+ mode or contents of the display therefore need to -+ switch to higher refresh rate */ -+ uint32_t READBACK_DYNAMIC_VERTICAL:1; -+ /* Reserved */ -+ uint32_t RESERVED:1; -+ } bits; -+ uint32_t u_all; -+ }; -+}; -+ -+ -+/* -+ * *************************************************************** -+ * ********************* Register programming sequences ******** -+ * *************************************************************** -+ */ -+ -+/* GPIO/Register access sequences */ -+enum io_register_sequence { -+ /* GLSync sequences to access SwapReady & SwapRequest -+ GPIOs - GLSync Connector parameter */ -+ IO_REG_SEQUENCE_SWAPREADY_SET = 0, -+ IO_REG_SEQUENCE_SWAPREADY_RESET, -+ IO_REG_SEQUENCE_SWAPREADY_READ, -+ IO_REG_SEQUENCE_SWAPREQUEST_SET, -+ IO_REG_SEQUENCE_SWAPREQUEST_RESET, -+ IO_REG_SEQUENCE_SWAPREQUEST_READ, -+ -+ /* Frame synchronization start/stop - display index parameter */ -+ IO_REG_SEQUENCE_FRAMELOCK_STOP, -+ IO_REG_SEQUENCE_FRAMELOCK_START, -+ -+ /* Flip lock/unlock - GLSync Connector parameter */ -+ IO_REG_SEQUENCE_GLOBALSWAP_LOCK, -+ IO_REG_SEQUENCE_GLOBALSWAP_UNLOCK, -+ -+ IO_REG_SEQUENCEENUM_MAX -+}; -+ -+#define IO_REGISTER_SEQUENCE_MAX_LENGTH 5 -+ -+/* -+ ***************************************************************************** -+ * struct io_register -+ ***************************************************************************** -+ * Generic struct for read/write register or GPIO. -+ * It allows controlling only some bit section of register, rather then the -+ * whole one. -+ * For write operation should be used as following: -+ * 1. data = READ(Base + RegisterOffset) -+ * 2. data &= ANDMask -+ * 3. data |= ORMask -+ * 4. WRITE(Base + RegisterOffset, data) -+ * -+ * Note: In case of regular register, ANDMask will be typically 0. -+ * In case of GPIO, ANDMask will have typically all bits set -+ * except the specific GPIO bit. -+ * -+ * For read operation should be used as following: -+ * 1. data = READ(Base + RegisterOffset) -+ * 2. data &= ANDMask -+ * 3. data >>= BitShift -+ * -+ * Note: In case of regular register, ANDMask will be typically 0xFFFFFFFF. -+ * In case of GPIO, ANDMask will have typically only specific GPIO bit set -+ * -+ * Note: Base Address is not exposed in this structure due to -+ * security consideration. -+ */ -+ -+/* -+ * The generic sequence to program/access registers or GPIOs. -+ * There could be 2 types of sequences - read and write. -+ * Read sequence may have 0 or more writes and in the end one read -+ * Write sequence may have 1 or more writes. -+ */ -+struct io_reg_sequence { -+ /* Ordered array of register to program */ -+ struct { -+ /* Offset of memory mapped register or GPIO */ -+ uint32_t register_offset; -+ /* Mask to use at AND operation (Mandatory, comes -+ before OR operation) */ -+ uint32_t and_mask; -+ union { -+ /* Mask to use at OR operation (For write -+ sequence only, comes after AND operation) */ -+ uint32_t or_mask; -+ /* Number of bits to shift to get the actual value -+ (For read sequence only, comes after AND operation) */ -+ uint32_t bit_shift; -+ }; -+ } io_registers[IO_REGISTER_SEQUENCE_MAX_LENGTH]; -+ -+ uint32_t steps_num; /* Total number of r/w steps in the sequence */ -+}; -+ -+/* Sequence ID - uniqly defines sequence on single adapter */ -+struct io_reg_sequence_id { -+ enum io_register_sequence sequence; /* Sequence enumeration Index/ID */ -+ union { -+ /* Refers to object to which the sequence applies.*/ -+ uint32_t index; -+ uint32_t display_index; -+ uint32_t controller_index; -+ uint32_t glsync_connector_index; -+ }; -+}; -+ -+struct fbc_info { -+ bool fbc_enable; -+ bool lpt_enable; -+}; -+ -+/* Event to request TM change IRQ registration state */ -+struct hotplug_irq_data { -+ bool disable; -+ struct graphics_object_id connector; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_id.h b/drivers/gpu/drm/amd/dal/include/grph_object_id.h -new file mode 100644 -index 0000000..fcf3eea ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/grph_object_id.h -@@ -0,0 +1,285 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_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 */ -+ CLOCK_SOURCE_ID_DP_DTO, /* Used to distinguish between */ -+ /* programming pixel clock */ -+ /* and ID (Phy) clock */ -+}; -+ -+ -+/* 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 */ -+ ENCODER_ID_INTERNAL_SDVOA, -+ ENCODER_ID_INTERNAL_SDVOB, -+ -+ /* External Third Party Encoders */ -+ ENCODER_ID_EXTERNAL_SI170B, -+ ENCODER_ID_EXTERNAL_CH7303, -+ ENCODER_ID_EXTERNAL_CH7301, /* 10 in decimal */ -+ ENCODER_ID_INTERNAL_DVO1, /* Belongs to Radeon Display Hardware */ -+ ENCODER_ID_EXTERNAL_SDVOA, -+ ENCODER_ID_EXTERNAL_SDVOB, -+ ENCODER_ID_EXTERNAL_TITFP513, -+ ENCODER_ID_INTERNAL_LVTM1, /* not used for Radeon */ -+ ENCODER_ID_EXTERNAL_VT1623, -+ ENCODER_ID_EXTERNAL_SI1930, /* HDMI */ -+ ENCODER_ID_INTERNAL_HDMI, -+ -+ /* Kaledisope (KLDSCP) Class Display Hardware */ -+ ENCODER_ID_INTERNAL_KLDSCP_TMDS1, -+ ENCODER_ID_INTERNAL_KLDSCP_DVO1, -+ ENCODER_ID_INTERNAL_KLDSCP_DAC1, -+ ENCODER_ID_INTERNAL_KLDSCP_DAC2, /* Shared with CV/TV and CRT */ -+ /* External TMDS (dual link) */ -+ ENCODER_ID_EXTERNAL_SI178, -+ ENCODER_ID_EXTERNAL_MVPU_FPGA, /* MVPU FPGA chip */ -+ ENCODER_ID_INTERNAL_DDI, -+ ENCODER_ID_EXTERNAL_VT1625, -+ ENCODER_ID_EXTERNAL_SI1932, -+ ENCODER_ID_EXTERNAL_AN9801, /* External Display Port */ -+ ENCODER_ID_EXTERNAL_DP501, /* External Display Port */ -+ 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_EXTERNAL_GENERIC_DVO = 0xFF -+}; -+ -+ -+/* Connector object ids */ -+enum connector_id { -+ CONNECTOR_ID_UNKNOWN = 0, -+ CONNECTOR_ID_SINGLE_LINK_DVII, -+ CONNECTOR_ID_DUAL_LINK_DVII, -+ CONNECTOR_ID_SINGLE_LINK_DVID, -+ CONNECTOR_ID_DUAL_LINK_DVID, -+ CONNECTOR_ID_VGA, -+ CONNECTOR_ID_HDMI_TYPE_A, -+ CONNECTOR_ID_NOT_USED, -+ CONNECTOR_ID_LVDS, -+ CONNECTOR_ID_PCIE, -+ CONNECTOR_ID_HARDCODE_DVI, -+ CONNECTOR_ID_DISPLAY_PORT, -+ CONNECTOR_ID_EDP, -+ CONNECTOR_ID_MXM, -+ CONNECTOR_ID_WIRELESS, /* wireless display pseudo-connector */ -+ CONNECTOR_ID_MIRACAST, /* used for VCE encode display path -+ * for Miracast */ -+ -+ CONNECTOR_ID_COUNT -+}; -+ -+ -+/* 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_DVO, -+ ENGINE_ID_DACA, -+ ENGINE_ID_DACB, -+ ENGINE_ID_VCE, /* wireless display pseudo-encoder */ -+ -+ ENGINE_ID_COUNT, -+ ENGINE_ID_UNKNOWN = (-1L) -+}; -+ -+union supported_stream_engines { -+ struct { -+ uint32_t ENGINE_ID_DIGA:1; -+ uint32_t ENGINE_ID_DIGB:1; -+ uint32_t ENGINE_ID_DIGC:1; -+ uint32_t ENGINE_ID_DIGD:1; -+ uint32_t ENGINE_ID_DIGE:1; -+ uint32_t ENGINE_ID_DIGF:1; -+ uint32_t ENGINE_ID_DIGG:1; -+ uint32_t ENGINE_ID_DVO:1; -+ uint32_t ENGINE_ID_DACA:1; -+ uint32_t ENGINE_ID_DACB:1; -+ uint32_t ENGINE_ID_VCE:1; -+ } engine; -+ uint32_t u_all; -+}; -+ -+ -+/* -+ ***************************************************************************** -+ * graphics_object_id struct -+ * -+ * graphics_object_id is a very simple struct wrapping 32bit Graphics -+ * Object identication -+ * -+ * This struct should stay very simple -+ * No dependencies at all (no includes) -+ * No debug messages or asserts -+ * No #ifndef and preprocessor directives -+ * No grow in space (no more data member) -+ ***************************************************************************** -+ */ -+ -+struct graphics_object_id { -+ uint32_t id:8; -+ uint32_t enum_id:4; -+ uint32_t type:4; -+ uint32_t reserved:16; /* for padding. total size should be u32 */ -+}; -+ -+/* some simple functions for convenient graphics_object_id handle */ -+ -+static inline struct graphics_object_id dal_graphics_object_id_init( -+ uint32_t id, -+ enum object_enum_id enum_id, -+ enum object_type type) -+{ -+ struct graphics_object_id result = { -+ id, enum_id, type, 0 -+ }; -+ -+ return result; -+} -+ -+bool dal_graphics_object_id_is_valid( -+ struct graphics_object_id id); -+bool dal_graphics_object_id_is_equal( -+ struct graphics_object_id id1, -+ struct graphics_object_id id2); -+uint32_t dal_graphics_object_id_to_uint( -+ struct graphics_object_id id); -+ -+ -+enum controller_id dal_graphics_object_id_get_controller_id( -+ struct graphics_object_id id); -+enum clock_source_id dal_graphics_object_id_get_clock_source_id( -+ struct graphics_object_id id); -+enum encoder_id dal_graphics_object_id_get_encoder_id( -+ struct graphics_object_id id); -+enum connector_id dal_graphics_object_id_get_connector_id( -+ struct graphics_object_id id); -+enum audio_id dal_graphics_object_id_get_audio_id( -+ struct graphics_object_id id); -+enum engine_id dal_graphics_object_id_get_engine_id( -+ struct graphics_object_id id); -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/hw_adjustment_set.h b/drivers/gpu/drm/amd/dal/include/hw_adjustment_set.h -new file mode 100644 -index 0000000..10fb8e2 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/hw_adjustment_set.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_ADJUSTMENT_SET_H__ -+#define __DAL_HW_ADJUSTMENT_SET_H__ -+ -+#include "include/hw_adjustment_types.h" -+ -+struct hw_adjustment_gamma_ramp; -+ -+struct hw_adjustment_set { -+ struct hw_adjustment_gamma_ramp *gamma_ramp; -+ struct hw_adjustment_deflicker *deflicker_filter; -+ struct hw_adjustment_value *coherent; -+ struct hw_adjustment_value *h_sync; -+ struct hw_adjustment_value *v_sync; -+ struct hw_adjustment_value *composite_sync; -+ struct hw_adjustment_value *backlight; -+ struct hw_adjustment_value *vb_level; -+ struct hw_adjustment_color_control *color_control; -+ union hw_adjustment_bit_depth_reduction *bit_depth; -+}; -+/* -+struct hw_adjustment *dal_adjustment_set_get_by_id( -+ struct hw_adjustment_set *adjustment_set, -+ enum hw_adjustment_id id);*/ -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/hw_adjustment_types.h b/drivers/gpu/drm/amd/dal/include/hw_adjustment_types.h -new file mode 100644 -index 0000000..cfae832 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/hw_adjustment_types.h -@@ -0,0 +1,205 @@ -+#ifndef __DAL_HW_ADJUSTMENT_TYPES_H__ -+#define __DAL_HW_ADJUSTMENT_TYPES_H__ -+ -+#include "hw_sequencer_types.h" -+ -+enum hw_adjustment_id { -+ HW_ADJUSTMENT_ID_COLOR_CONTROL, -+ HW_ADJUSTMENT_ID_GAMMA_LUT, -+ HW_ADJUSTMENT_ID_GAMMA_RAMP, -+ HW_ADJUSTMENT_ID_DEFLICKER, -+ HW_ADJUSTMENT_ID_SHARPNESS_CONTROL, -+ HW_ADJUSTMENT_ID_TIMING, -+ HW_ADJUSTMENT_ID_TIMING_AND_PIXEL_CLOCK, -+ HW_ADJUSTMENT_ID_OVERSCAN, -+ HW_ADJUSTMENT_ID_UNDERSCAN_TYPE, -+ HW_ADJUSTMENT_ID_VERTICAL_SYNC, -+ HW_ADJUSTMENT_ID_HORIZONTAL_SYNC, -+ HW_ADJUSTMENT_ID_COMPOSITE_SYNC, -+ HW_ADJUSTMENT_ID_VIDEO_STANDARD, -+ HW_ADJUSTMENT_ID_BACKLIGHT, -+ HW_ADJUSTMENT_ID_BIT_DEPTH_REDUCTION, -+ HW_ADJUSTMENT_ID_REDUCED_BLANKING, -+ HW_ADJUSTMENT_ID_COHERENT, -+ /* OVERLAY ADJUSTMENTS*/ -+ HW_ADJUSTMENT_ID_OVERLAY, -+ HW_ADJUSTMENT_ID_OVERLAY_ALPHA, -+ HW_ADJUSTMENT_ID_OVERLAY_VARIABLE_GAMMA, -+ HW_ADJUSTMENT_ID_COUNT, -+ HW_ADJUSTMENT_ID_UNDEFINED, -+}; -+ -+struct hw_adjustment_deflicker { -+ int32_t hp_factor; -+ uint32_t hp_divider; -+ int32_t lp_factor; -+ uint32_t lp_divider; -+ int32_t sharpness; -+ bool enable_sharpening; -+}; -+ -+struct hw_adjustment_value { -+ union { -+ uint32_t ui_value; -+ int32_t i_value; -+ }; -+}; -+ -+enum hw_color_adjust_option { -+ HWS_COLOR_MATRIX_HW_DEFAULT = 1, -+ HWS_COLOR_MATRIX_SW -+}; -+ -+enum { -+ HW_TEMPERATURE_MATRIX_SIZE = 9, -+ HW_TEMPERATURE_MATRIX_SIZE_WITH_OFFSET = 12 -+}; -+ -+struct hw_adjustment_color_control { -+ enum hw_color_space color_space; -+ enum hw_color_adjust_option option; -+ enum pixel_format surface_pixel_format; -+ enum dc_color_depth color_depth; -+ uint32_t lb_color_depth; -+ int32_t contrast; -+ int32_t saturation; -+ int32_t brightness; -+ int32_t hue; -+ uint32_t adjust_divider; -+ uint32_t temperature_divider; -+ uint32_t temperature_matrix[HW_TEMPERATURE_MATRIX_SIZE]; -+}; -+ -+struct hw_underscan_adjustment { -+ struct hw_adjustment_deflicker deflicker; -+ struct overscan_info hw_overscan; -+}; -+ -+struct hw_underscan_adjustment_data { -+ enum hw_adjustment_id hw_adj_id; -+ struct hw_underscan_adjustment hw_underscan_adj; -+}; -+ -+union hw_adjustment_bit_depth_reduction { -+ uint32_t raw; -+ struct { -+ uint32_t TRUNCATE_ENABLED:1; -+ uint32_t TRUNCATE_DEPTH:2; -+ uint32_t TRUNCATE_MODE:1; -+ uint32_t SPATIAL_DITHER_ENABLED:1; -+ uint32_t SPATIAL_DITHER_DEPTH:2; -+ uint32_t SPATIAL_DITHER_MODE:2; -+ uint32_t RGB_RANDOM:1; -+ uint32_t FRAME_RANDOM:1; -+ uint32_t HIGHPASS_RANDOM:1; -+ uint32_t FRAME_MODULATION_ENABLED:1; -+ uint32_t FRAME_MODULATION_DEPTH:2; -+ uint32_t TEMPORAL_LEVEL:1; -+ uint32_t FRC_25:2; -+ uint32_t FRC_50:2; -+ uint32_t FRC_75:2; -+ } bits; -+}; -+ -+struct hw_color_control_range { -+ struct hw_adjustment_range contrast; -+ struct hw_adjustment_range saturation; -+ struct hw_adjustment_range brightness; -+ struct hw_adjustment_range hue; -+ struct hw_adjustment_range temperature; -+}; -+ -+enum hw_surface_type { -+ HW_OVERLAY_SURFACE = 1, -+ HW_GRAPHIC_SURFACE -+}; -+ -+/* LUT type for GammaCorrection */ -+struct hw_gamma_lut { -+ uint32_t red; -+ uint32_t green; -+ uint32_t blue; -+}; -+ -+struct hw_devc_lut { -+ uint8_t red; -+ uint8_t green; -+ uint8_t blue; -+ uint8_t reserved; -+}; -+ -+struct hw_adjustment_gamma_lut { -+ struct hw_gamma_lut *pGammaLut; -+ uint32_t size_in_elements; -+ enum pixel_format surface_pixel_format; -+}; -+ -+ -+enum hw_gamma_ramp_type { -+ HW_GAMMA_RAMP_UNITIALIZED = 0, -+ HW_GAMMA_RAMP_DEFAULT, -+ HW_GAMMA_RAMP_RBG_256x3x16, -+ HW_GAMMA_RAMP_RBG_DXGI_1 -+}; -+ -+#define HW_GAMMA_RAMP_RBG_256 256 -+ -+struct hw_gamma_ramp_rgb256x3x16 { -+ unsigned short red[HW_GAMMA_RAMP_RBG_256]; -+ unsigned short green[HW_GAMMA_RAMP_RBG_256]; -+ unsigned short blue[HW_GAMMA_RAMP_RBG_256]; -+}; -+ -+union hw_gamma_flags { -+ uint32_t raw; -+ struct { -+ uint32_t gamma_ramp_array :1; -+ uint32_t graphics_degamma_srgb :1; -+ uint32_t overlay_degamma_srgb :1; -+ uint32_t apply_degamma :1; -+ uint32_t reserved :28; -+ } bits; -+}; -+ -+struct hw_regamma_coefficients { -+ int32_t gamma[3]; -+ int32_t a0[3]; -+ int32_t a1[3]; -+ int32_t a2[3]; -+ int32_t a3[3]; -+}; -+ -+struct hw_regamma_ramp { -+ /* Gamma ramp packed as RGB */ -+ unsigned short gamma[256 * 3]; -+}; -+ -+struct hw_regamma_lut { -+ union hw_gamma_flags flags; -+ union { -+ struct hw_regamma_ramp gamma; -+ struct hw_regamma_coefficients coeff; -+ }; -+}; -+ -+union hw_gamma_flag { -+ uint32_t uint; -+ struct { -+ uint32_t config_is_changed :1; -+ uint32_t regamma_update :1; -+ uint32_t gamma_update :1; -+ uint32_t reserved :29; -+ } bits; -+}; -+ -+struct hw_adjustment_gamma_ramp { -+ uint32_t size; -+ enum hw_gamma_ramp_type type; -+ enum pixel_format surface_pixel_format; -+ enum hw_color_space color_space; -+ struct hw_regamma_lut regamma; -+ union hw_gamma_flag flag; -+ struct hw_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/hw_path_mode_set_interface.h b/drivers/gpu/drm/amd/dal/include/hw_path_mode_set_interface.h -new file mode 100644 -index 0000000..28ac018 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/hw_path_mode_set_interface.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_HW_PATH_MODE_SET_INTERFACE_H__ -+#define __DAL_HW_PATH_MODE_SET_INTERFACE_H__ -+ -+struct hw_path_mode; -+struct hw_path_mode_set; -+ -+struct hw_path_mode_set *dal_hw_path_mode_set_create(void); -+ -+void dal_hw_path_mode_set_destroy(struct hw_path_mode_set **set); -+ -+bool dal_hw_path_mode_set_add( -+ struct hw_path_mode_set *set, -+ struct hw_path_mode *path_mode, -+ uint32_t *index); -+ -+struct hw_path_mode *dal_hw_path_mode_set_get_path_by_index( -+ const struct hw_path_mode_set *set, -+ uint32_t index); -+ -+uint32_t dal_hw_path_mode_set_get_paths_number( -+ const struct hw_path_mode_set *set); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h -new file mode 100644 -index 0000000..ddd78d6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h -@@ -0,0 +1,388 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_SEQUENCER_INTERFACE_H__ -+#define __DAL_HW_SEQUENCER_INTERFACE_H__ -+ -+#include "hw_sequencer_types.h" -+#include "hw_adjustment_types.h" -+#include "include/display_clock_interface.h" -+#include "include/scaler_types.h" -+#include "include/grph_csc_types.h" -+#include "plane_types.h" -+ -+#include "adapter_service_interface.h" -+ -+enum hwss_result { -+ HWSS_RESULT_OK, -+ HWSS_RESULT_ERROR, -+ HWSS_RESULT_NO_BANDWIDTH, -+ HWSS_RESULT_OUT_OF_RANGE, -+ HWSS_RESULT_NOT_SUPPORTED, -+ HWSS_RESULT_UNKNOWN -+}; -+ -+struct hws_init_data { -+ struct adapter_service *as; -+ struct dal_context *dal_context; -+}; -+ -+/* TODO: below is three almost equal structures. -+ * We should decide what to do with them */ -+struct blank_stream_param { -+ struct display_path *display_path; -+ uint32_t link_idx; -+ struct hw_crtc_timing timing; -+ struct link_settings link_settings; -+}; -+ -+struct enable_stream_param { -+ struct display_path *display_path; -+ uint32_t link_idx; -+ struct hw_crtc_timing timing; -+ struct link_settings link_settings; -+ -+ const struct hw_path_mode *path_mode; -+}; -+ -+struct enable_link_param { -+ struct display_path *display_path; -+ uint32_t link_idx; -+ struct hw_crtc_timing timing; -+ struct link_settings link_settings; -+ -+ bool optimized_programming; -+ const struct hw_path_mode *path_mode; -+}; -+ -+struct validate_link_param { -+ const struct display_path *display_path; -+ uint32_t link_idx; -+ struct link_settings link_settings; -+}; -+ -+struct set_dp_phy_pattern_param { -+ struct display_path *display_path; -+ uint32_t link_idx; -+ enum dp_test_pattern test_pattern; -+ const uint8_t *custom_pattern; -+ uint32_t cust_pattern_size; -+}; -+ -+struct hw_global_objects; -+struct hw_sequencer; -+struct hw_adjustment; -+struct hw_path_mode_set; -+struct hw_path_mode; -+struct hwss_build_params; -+struct controller; -+ -+void dal_hw_sequencer_mute_audio_endpoint( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ bool mute); -+ -+void dal_hw_sequencer_enable_audio_endpoint( -+ struct hw_sequencer *hws, -+ struct link_settings *ls, -+ struct display_path *display_path, -+ bool enable); -+ -+enum hwss_result dal_hw_sequencer_reset_audio_device( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+enum hwss_result dal_hw_sequencer_validate_link( -+ struct hw_sequencer *hws, -+ const struct validate_link_param *param); -+ -+bool dal_hw_sequencer_is_supported_dp_training_pattern3( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ uint32_t link_idx); -+ -+enum hwss_result dal_hw_sequencer_set_dp_phy_pattern( -+ struct hw_sequencer *hws, -+ const struct set_dp_phy_pattern_param *param); -+ -+enum hwss_result dal_hw_sequencer_set_lane_settings( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ const struct link_training_settings *link_settings); -+ -+void dal_hw_sequencer_set_test_pattern( -+ struct hw_sequencer *hws, -+ struct hw_path_mode *path_mode, -+ enum dp_test_pattern test_pattern, -+ const struct link_training_settings *link_settings, -+ const uint8_t *custom_pattern, -+ uint8_t cust_pattern_size); -+ -+bool dal_hw_sequencer_has_audio_bandwidth_changed( -+ struct hw_sequencer *hws, -+ const struct hw_path_mode *old, -+ const struct hw_path_mode *new); -+ -+void dal_hw_sequencer_enable_azalia_audio_jack_presence( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+void dal_hw_sequencer_disable_azalia_audio_jack_presence( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+void dal_hw_sequencer_enable_memory_requests( -+ struct hw_sequencer *hws, -+ struct hw_path_mode *path_mode); -+ -+void dal_hw_sequencer_update_info_packets( -+ struct hw_sequencer *hws, -+ struct hw_path_mode *path_mode); -+ -+/* Static validation for a SINGLE path mode. -+ * Already "active" paths (if any) are NOT taken into account. */ -+enum hwss_result dal_hw_sequencer_validate_display_path_mode( -+ struct hw_sequencer *hws, -+ const struct hw_path_mode *path_mode); -+ -+/* Validation for a SET of path modes, including Video Memory Bandwidth -+ * validation. */ -+enum hwss_result dal_hw_sequencer_validate_display_hwpms( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set); -+ -+struct hw_adjustment_gamma_ramp; -+ -+enum hwss_result dal_hw_sequencer_set_gamma_ramp_adjustment( -+ struct hw_sequencer *hws, -+ const struct display_path *display_path, -+ struct hw_adjustment_gamma_ramp *adjusment); -+ -+enum hwss_result dal_hw_sequencer_set_color_control_adjustment( -+ struct hw_sequencer *hws, -+ struct controller *crtc, -+ struct hw_adjustment_color_control *adjustment); -+ -+enum hwss_result dal_hw_sequencer_set_vertical_sync_adjustment( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ struct hw_adjustment_value *adjustment); -+ -+enum hwss_result dal_hw_sequencer_set_horizontal_sync_adjustment( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ struct hw_adjustment_value *adjustment); -+ -+enum hwss_result dal_hw_sequencer_set_composite_sync_adjustment( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ struct hw_adjustment_value *adjustment); -+ -+enum hwss_result dal_hw_sequencer_enable_sync_output( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+enum hwss_result dal_hw_sequencer_disable_sync_output( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+enum hwss_result dal_hw_sequencer_set_backlight_adjustment( -+ struct hw_sequencer *hws, -+ struct display_path *display_path, -+ struct hw_adjustment_value *adjustment); -+ -+void dal_hw_sequencer_disable_memory_requests( -+ struct hw_sequencer *hws, -+ const struct hw_path_mode *path_mode); -+ -+enum hwss_result dal_hw_sequencer_enable_link( -+ struct hw_sequencer *hws, -+ const struct enable_link_param *in); -+ -+void dal_hw_sequencer_disable_link( -+ struct hw_sequencer *hws, -+ const struct enable_link_param *in); -+ -+void dal_hw_sequencer_enable_stream( -+ struct hw_sequencer *hws, -+ const struct enable_stream_param *in); -+ -+void dal_hw_sequencer_disable_stream( -+ struct hw_sequencer *hws, -+ const struct enable_stream_param *in); -+ -+void dal_hw_sequencer_blank_stream( -+ struct hw_sequencer *hws, -+ const struct blank_stream_param *in); -+ -+void dal_hw_sequencer_unblank_stream( -+ struct hw_sequencer *hws, -+ const struct blank_stream_param *in); -+ -+enum hwss_result dal_hw_sequencer_set_clocks_and_clock_state( -+ struct hw_sequencer *hws, -+ struct hw_global_objects *g_obj, -+ const struct minimum_clocks_calculation_result *min_clk_in, -+ enum clocks_state required_clocks_state); -+ -+enum hwss_result dal_hw_sequencer_set_mode( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set); -+ -+enum signal_type dal_hw_sequencer_detect_sink( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+enum signal_type dal_hw_sequencer_detect_load( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+bool dal_hw_sequencer_is_sink_present( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+void dal_hw_sequencer_psr_setup( -+ struct hw_sequencer *hws, -+ const struct hw_path_mode *path_mode, -+ const struct psr_caps *psr_caps); -+ -+void dal_hw_sequencer_psr_enable( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+void dal_hw_sequencer_psr_disable( -+ struct hw_sequencer *hws, -+ struct display_path *display_path); -+ -+void dal_hw_sequencer_program_drr( -+ struct hw_sequencer *hws, -+ const struct hw_path_mode *path_mode); -+ -+enum hwss_result dal_hw_sequencer_set_safe_displaymark( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set); -+ -+enum hwss_result dal_hw_sequencer_set_displaymark( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set); -+ -+void dal_hw_sequencer_destroy(struct hw_sequencer **hws); -+ -+struct hw_sequencer *dal_hw_sequencer_create( -+ struct hws_init_data *hws_init_data); -+ -+enum hwss_result dal_hw_sequencer_set_overscan_adj( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *set, -+ struct hw_underscan_adjustment_data *hw_underscan); -+ -+bool dal_hw_sequencer_enable_line_buffer_power_gating( -+ struct line_buffer *lb, -+ enum controller_id id, -+ enum pixel_type pixel_type, -+ uint32_t src_pixel_width, -+ uint32_t dst_pixel_width, -+ struct scaling_taps *taps, -+ enum lb_pixel_depth lb_depth, -+ uint32_t src_height, -+ uint32_t dst_height, -+ bool interlaced); -+ -+void dal_hw_sequencer_build_scaler_parameter( -+ const struct hw_path_mode *path_mode, -+ const struct scaling_taps *taps, -+ bool build_timing_required, -+ struct scaler_data *scaler_data); -+ -+void dal_hw_sequencer_update_info_frame( -+ const struct hw_path_mode *hw_path_mode); -+ -+enum hwss_result dal_hw_sequencer_set_bit_depth_reduction_adj( -+ struct hw_sequencer *hws, -+ struct display_path *disp_path, -+ union hw_adjustment_bit_depth_reduction *bit_depth); -+ -+bool dal_hw_sequencer_is_support_custom_gamut_adj( -+ struct hw_sequencer *hws, -+ struct display_path *disp_path, -+ enum hw_surface_type surface_type); -+ -+enum hwss_result dal_hw_sequencer_get_hw_color_adj_range( -+ struct hw_sequencer *hws, -+ struct display_path *disp_path, -+ struct hw_color_control_range *hw_color_range); -+ -+bool dal_hw_sequencer_is_support_custom_gamma_coefficients( -+ struct hw_sequencer *hws, -+ struct display_path *disp_path, -+ enum hw_surface_type surface_type); -+ -+enum hwss_result dal_hw_sequencer_build_csc_adjust( -+ struct hw_sequencer *hws, -+ struct hw_adjustment_color_control *color_control, -+ struct grph_csc_adjustment *adjust); -+ -+void dal_hw_sequencer_build_gamma_ramp_adj_params( -+ const struct hw_adjustment_gamma_ramp *adjusment, -+ struct gamma_parameters *gamma_param, -+ struct gamma_ramp *ramp); -+ -+void translate_from_hw_to_controller_regamma( -+ const struct hw_regamma_lut *hw_regamma, -+ struct regamma_lut *regamma); -+ -+void dal_hw_sequencer_enable_wireless_idle_detection( -+ struct hw_sequencer *hws, -+ bool enable); -+ -+/* Cursor interface */ -+enum hwss_result dal_hw_sequencer_set_cursor_position( -+ struct hw_sequencer *hws, -+ struct display_path *dp, -+ const struct dc_cursor_position *position); -+ -+enum hwss_result dal_hw_sequencer_set_cursor_attributes( -+ struct hw_sequencer *hws, -+ struct display_path *dp, -+ const struct dc_cursor_attributes *attributes); -+ -+/* Underlay/MPO interface */ -+enum hwss_result dal_hw_sequencer_set_plane_config( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set, -+ uint32_t display_index); -+ -+bool dal_hw_sequencer_update_plane_address( -+ struct hw_sequencer *hws, -+ struct display_path *dp, -+ uint32_t num_planes, -+ struct plane_addr_flip_info *info); -+ -+void dal_hw_sequencer_prepare_to_release_planes( -+ struct hw_sequencer *hws, -+ struct hw_path_mode_set *path_set, -+ uint32_t display_index); -+ -+#endif /* __DAL_HW_SEQUENCER_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h -new file mode 100644 -index 0000000..d5d7059 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h -@@ -0,0 +1,305 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_HW_SEQUENCER_TYPES_H__ -+#define __DAL_HW_SEQUENCER_TYPES_H__ -+ -+#include "signal_types.h" -+#include "grph_object_defs.h" -+#include "link_service_types.h" -+#include "plane_types.h" -+ -+struct color_quality { -+ uint32_t bpp_graphics; -+ uint32_t bpp_backend_video; -+}; -+ -+enum { -+ HW_MAX_NUM_VIEWPORTS = 2, -+ HW_CURRENT_PIPE_INDEX = 0, -+ HW_OTHER_PIPE_INDEX = 1 -+}; -+ -+struct hw_view_port_adjustment { -+ int32_t start_adjustment; -+ int32_t width; -+ -+ enum controller_id controller_id; -+}; -+ -+struct hw_view_port_adjustments { -+ uint32_t view_ports_num; -+ struct hw_view_port_adjustment adjustments[HW_MAX_NUM_VIEWPORTS]; -+}; -+ -+/* Timing standard */ -+enum hw_timing_standard { -+ HW_TIMING_STANDARD_UNDEFINED, -+ HW_TIMING_STANDARD_DMT, -+ HW_TIMING_STANDARD_GTF, -+ HW_TIMING_STANDARD_CVT, -+ HW_TIMING_STANDARD_CVT_RB, -+ HW_TIMING_STANDARD_CEA770, -+ HW_TIMING_STANDARD_CEA861, -+ HW_TIMING_STANDARD_HDMI, -+ HW_TIMING_STANDARD_TV_NTSC, -+ HW_TIMING_STANDARD_TV_NTSC_J, -+ HW_TIMING_STANDARD_TV_PAL, -+ HW_TIMING_STANDARD_TV_PAL_M, -+ HW_TIMING_STANDARD_TV_PAL_CN, -+ HW_TIMING_STANDARD_TV_SECAM, -+ /* for explicit timings from VBIOS, EDID etc. */ -+ HW_TIMING_STANDARD_EXPLICIT -+}; -+ -+/* identical to struct crtc_ranged_timing_control -+ * defined in controller\timing_generator_types.h */ -+struct hw_ranged_timing_control { -+ /* set to 1 to force dynamic counter V_COUNT -+ * to lock to constant rate counter V_COUNT_NOM -+ * on page flip event in dynamic refresh mode -+ * when switching from a low refresh rate to nominal refresh rate */ -+ bool force_lock_on_event; -+ /* set to 1 to force CRTC2 (slave) to lock to CRTC1 (master) VSync -+ * in order to overlap their blank regions for MC clock changes */ -+ bool lock_to_master_vsync; -+ -+ /* set to 1 to program Static Screen Detection Masks -+ * without enabling dynamic refresh rate */ -+ bool program_static_screen_mask; -+ /* set to 1 to program Dynamic Refresh Rate */ -+ bool program_dynamic_refresh_rate; -+ /* set to 1 to force disable Dynamic Refresh Rate */ -+ bool force_disable_drr; -+ -+ /* event mask to enable/disable various trigger sources -+ * for static screen detection */ -+ struct static_screen_events event_mask; -+ -+ /* Number of consecutive static screen frames before static state is -+ * asserted. */ -+ uint32_t static_frame_count; -+}; -+ -+/* define the structure of Dynamic Refresh Mode */ -+struct hw_ranged_timing { -+ /* defines the minimum possible vertical dimension of display timing -+ * for CRTC as supported by the panel */ -+ uint32_t vertical_total_min; -+ /* defines the maximum possible vertical dimension of display timing -+ * for CRTC as supported by the panel */ -+ uint32_t vertical_total_max; -+ -+ struct hw_ranged_timing_control control; -+}; -+ -+/* CRTC timing structure */ -+struct hw_crtc_timing { -+ uint32_t h_total; -+ uint32_t h_addressable; -+ uint32_t h_overscan_left; -+ uint32_t h_overscan_right; -+ uint32_t h_sync_start; -+ uint32_t h_sync_width; -+ -+ uint32_t v_total; -+ uint32_t v_addressable; -+ uint32_t v_overscan_top; -+ uint32_t v_overscan_bottom; -+ uint32_t v_sync_start; -+ uint32_t v_sync_width; -+ -+ struct hw_ranged_timing ranged_timing; -+ -+ /* in KHz */ -+ uint32_t pixel_clock; -+ -+ enum hw_timing_standard timing_standard; -+ enum dc_color_depth color_depth; -+ enum dc_pixel_encoding pixel_encoding; -+ -+ struct { -+ uint32_t INTERLACED:1; -+ uint32_t DOUBLESCAN:1; -+ uint32_t PIXEL_REPETITION:4; /* 1...10 */ -+ uint32_t HSYNC_POSITIVE_POLARITY:1; -+ uint32_t VSYNC_POSITIVE_POLARITY:1; -+ /* frame should be packed for 3D -+ * (currently this refers to HDMI 1.4a FramePacking format */ -+ uint32_t HORZ_COUNT_BY_TWO:1; -+ uint32_t PACK_3D_FRAME:1; -+ /* 0 - left eye polarity, 1 - right eye polarity */ -+ uint32_t RIGHT_EYE_3D_POLARITY:1; -+ /* DVI-DL High-Color mode */ -+ uint32_t HIGH_COLOR_DL_MODE:1; -+ uint32_t Y_ONLY:1; -+ /* HDMI 2.0 - Support scrambling for TMDS character -+ * rates less than or equal to 340Mcsc */ -+ uint32_t LTE_340MCSC_SCRAMBLE:1; -+ } flags; -+}; -+ -+struct hw_scaling_info { -+ struct view src; -+ struct view dst; -+ enum signal_type signal; -+}; -+ -+enum hw_color_space { -+ HW_COLOR_SPACE_UNKNOWN = 0, -+ HW_COLOR_SPACE_SRGB_FULL_RANGE, -+ HW_COLOR_SPACE_SRGB_LIMITED_RANGE, -+ HW_COLOR_SPACE_YPBPR601, -+ HW_COLOR_SPACE_YPBPR709, -+ HW_COLOR_SPACE_YCBCR601, -+ HW_COLOR_SPACE_YCBCR709, -+ HW_COLOR_SPACE_YCBCR601_YONLY, -+ HW_COLOR_SPACE_YCBCR709_YONLY, -+ HW_COLOR_SPACE_NMVPU_SUPERAA, -+}; -+ -+enum hw_overlay_color_space { -+ HW_OVERLAY_COLOR_SPACE_UNKNOWN, -+ HW_OVERLAY_COLOR_SPACE_BT709, -+ HW_OVERLAY_COLOR_SPACE_BT601, -+ HW_OVERLAY_COLOR_SPACE_SMPTE240, -+ HW_OVERLAY_COLOR_SPACE_RGB -+}; -+ -+enum hw_overlay_backend_bpp { -+ HW_OVERLAY_BACKEND_BPP_UNKNOWN, -+ HW_OVERLAY_BACKEND_BPP32_FULL_BANDWIDTH, -+ HW_OVERLAY_BACKEND_BPP16_FULL_BANDWIDTH, -+ HW_OVERLAY_BACKEND_BPP32_HALF_BANDWIDTH, -+}; -+enum hw_overlay_format { -+ HW_OVERLAY_FORMAT_UNKNOWN, -+ HW_OVERLAY_FORMAT_YUY2, -+ HW_OVERLAY_FORMAT_UYVY, -+ HW_OVERLAY_FORMAT_RGB565, -+ HW_OVERLAY_FORMAT_RGB555, -+ HW_OVERLAY_FORMAT_RGB32, -+ HW_OVERLAY_FORMAT_YUV444, -+ HW_OVERLAY_FORMAT_RGB32_2101010 -+}; -+ -+enum hw_scale_options { -+ HW_SCALE_OPTION_UNKNOWN, -+ HW_SCALE_OPTION_OVERSCAN, /* multimedia pass through mode */ -+ HW_SCALE_OPTION_UNDERSCAN -+}; -+ -+enum hw_stereo_format { -+ HW_STEREO_FORMAT_NONE = 0, -+ HW_STEREO_FORMAT_SIDE_BY_SIDE = 1, -+ HW_STEREO_FORMAT_TOP_AND_BOTTOM = 2, -+ HW_STEREO_FORMAT_FRAME_ALTERNATE = 3, -+ HW_STEREO_FORMAT_ROW_INTERLEAVED = 5, -+ HW_STEREO_FORMAT_COLUMN_INTERLEAVED = 6, -+ HW_STEREO_FORMAT_CHECKER_BOARD = 7 /* the same as pixel interleave */ -+}; -+ -+enum hw_dithering_options { -+ HW_DITHERING_OPTION_UNKNOWN, -+ HW_DITHERING_OPTION_SKIP_PROGRAMMING, -+ HW_DITHERING_OPTION_ENABLE, -+ HW_DITHERING_OPTION_DISABLE -+}; -+ -+struct hw_stereo_mixer_params { -+ bool sub_sampling; -+ bool single_pipe; -+}; -+ -+ -+ -+struct hw_action_flags { -+ uint32_t RESYNC_PATH:1; -+ uint32_t TIMING_CHANGED:1; -+ uint32_t PIXEL_ENCODING_CHANGED:1; -+ uint32_t GAMUT_CHANGED:1; -+ uint32_t TURN_OFF_VCC:1; -+}; -+ -+enum hw_sync_request { -+ HW_SYNC_REQUEST_NONE = 0, -+ HW_SYNC_REQUEST_SET_INTERPATH, -+ HW_SYNC_REQUEST_SET_GL_SYNC_GENLOCK, -+ HW_SYNC_REQUEST_SET_GL_SYNC_FREE_RUN, -+ HW_SYNC_REQUEST_SET_GL_SYNC_SHADOW, -+ HW_SYNC_REQUEST_RESET_GLSYNC, -+ HW_SYNC_REQUEST_RESYNC_GLSYNC, -+ HW_SYNC_REQUEST_SET_STEREO3D -+}; -+ -+struct hw_sync_info { -+ enum hw_sync_request sync_request; -+ uint32_t target_pixel_clock; /* in KHz */ -+ enum sync_source sync_source; -+}; -+ -+/* TODO hw_info_frame and hw_info_packet structures are same as in encoder -+ * merge it*/ -+struct hw_info_packet { -+ bool valid; -+ uint8_t hb0; -+ uint8_t hb1; -+ uint8_t hb2; -+ uint8_t hb3; -+ uint8_t sb[28]; -+}; -+ -+struct hw_info_frame { -+ /* Auxiliary Video Information */ -+ struct hw_info_packet avi_info_packet; -+ struct hw_info_packet gamut_packet; -+ struct hw_info_packet vendor_info_packet; -+ /* Source Product Description */ -+ struct hw_info_packet spd_packet; -+ /* Video Stream Configuration */ -+ struct hw_info_packet vsc_packet; -+}; -+ -+ -+enum channel_command_type { -+ CHANNEL_COMMAND_I2C, -+ CHANNEL_COMMAND_I2C_OVER_AUX, -+ CHANNEL_COMMAND_AUX -+}; -+ -+ -+/* maximum TMDS transmitter pixel clock is 165 MHz. So it is KHz */ -+#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 -+#define NATIVE_HDMI_MAX_PIXEL_CLOCK_IN_KHZ 297000 -+ -+struct hw_adjustment_range { -+ int32_t hw_default; -+ int32_t min; -+ int32_t max; -+ int32_t step; -+ uint32_t divider; /* (actually HW range is min/divider; divider !=0) */ -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/i2caux_interface.h b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h -new file mode 100644 -index 0000000..b961d24 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h -@@ -0,0 +1,127 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_I2CAUX_INTERFACE_H__ -+#define __DAL_I2CAUX_INTERFACE_H__ -+ -+#include "ddc_interface.h" -+#include "adapter_service_interface.h" -+ -+struct i2c_payload { -+ bool write; -+ uint8_t address; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+enum i2c_command_engine { -+ I2C_COMMAND_ENGINE_DEFAULT, -+ I2C_COMMAND_ENGINE_SW, -+ I2C_COMMAND_ENGINE_HW -+}; -+ -+struct i2c_command { -+ struct i2c_payload *payloads; -+ uint8_t number_of_payloads; -+ -+ enum i2c_command_engine engine; -+ -+ /* expressed in KHz -+ * zero means "use default value" */ -+ uint32_t speed; -+}; -+ -+#define DEFAULT_AUX_MAX_DATA_SIZE 16 -+#define AUX_MAX_DEFER_WRITE_RETRY 20 -+ -+struct aux_payload { -+ /* set following flag to read/write I2C data, -+ * reset it to read/write DPCD data */ -+ bool i2c_over_aux; -+ /* set following flag to write data, -+ * reset it to read data */ -+ bool write; -+ uint32_t address; -+ uint8_t length; -+ uint8_t *data; -+}; -+ -+struct aux_command { -+ struct aux_payload *payloads; -+ uint8_t number_of_payloads; -+ -+ /* expressed in milliseconds -+ * zero means "use default value" */ -+ uint32_t defer_delay; -+ -+ /* zero means "use default value" */ -+ uint32_t max_defer_write_retry; -+}; -+ -+union aux_config { -+ struct { -+ uint32_t ALLOW_AUX_WHEN_HPD_LOW:1; -+ } bits; -+ uint32_t raw; -+}; -+ -+struct i2caux; -+ -+struct i2caux *dal_i2caux_create( -+ struct adapter_service *as, -+ struct dc_context *ctx); -+ -+bool dal_i2caux_submit_i2c_command( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ struct i2c_command *cmd); -+ -+bool dal_i2caux_submit_aux_command( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ struct aux_command *cmd); -+ -+void dal_i2caux_keep_engine_power_up( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ bool keep_power_up); -+ -+bool dal_i2caux_start_gtc_sync( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ -+bool dal_i2caux_stop_gtc_sync( -+ struct i2caux *i2caux, -+ struct ddc *ddc); -+ -+void dal_i2caux_configure_aux( -+ struct i2caux *i2caux, -+ struct ddc *ddc, -+ union aux_config cfg); -+ -+void dal_i2caux_destroy( -+ struct i2caux **ptr); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/irq_interface.h b/drivers/gpu/drm/amd/dal/include/irq_interface.h -new file mode 100644 -index 0000000..0faa48f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/irq_interface.h -@@ -0,0 +1,53 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_INTERFACE_H__ -+#define __DAL_IRQ_INTERFACE_H__ -+ -+#include "gpio_types.h" -+ -+struct irq; -+ -+enum gpio_result dal_irq_open( -+ struct irq *irq); -+ -+enum gpio_result dal_irq_get_value( -+ const struct irq *irq, -+ uint32_t *value); -+ -+enum dc_irq_source dal_irq_get_source( -+ const struct irq *irq); -+ -+enum dc_irq_source dal_irq_get_rx_source( -+ const struct irq *irq); -+ -+enum gpio_result dal_irq_setup_hpd_filter( -+ struct irq *irq, -+ struct gpio_hpd_config *config); -+ -+void dal_irq_close( -+ struct irq *irq); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/irq_service_interface.h b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h -new file mode 100644 -index 0000000..7ae4aeb ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h -@@ -0,0 +1,55 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__ -+#define __DAL_IRQ_SERVICE_INTERFACE_H__ -+ -+#include "include/adapter_service_types.h" -+ -+struct irq_service_init_data { -+ struct dc_context *ctx; -+}; -+ -+struct irq_service *dal_irq_service_create( -+ enum dce_version version, -+ struct irq_service_init_data *init_data); -+ -+void dal_irq_service_destroy(struct irq_service **irq_service); -+ -+bool dal_irq_service_set( -+ struct irq_service *irq_service, -+ enum dc_irq_source source, -+ bool enable); -+ -+bool dal_irq_service_ack( -+ struct irq_service *irq_service, -+ enum dc_irq_source source); -+ -+enum dc_irq_source dal_irq_service_to_irq_source( -+ struct irq_service *irq_service, -+ uint32_t src_id, -+ uint32_t ext_id); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/isr_config_types.h b/drivers/gpu/drm/amd/dal/include/isr_config_types.h -new file mode 100644 -index 0000000..2e822f0 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/isr_config_types.h -@@ -0,0 +1,157 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_ISR_TYPES_H__ -+#define __DAL_ISR_TYPES_H__ -+ -+#include "grph_object_id.h" -+#include "dc_types.h" -+ -+struct plane_config; -+enum { -+ /*move to common*/ -+ MAX_COFUNC_PATH_COMMON = 6, -+ /*CZ worst case*/ -+ MAX_NUM_PLANES = 4 -+}; -+ -+enum plane_type { -+ PLANE_TYPE_GRPH = 0, -+ PLANE_TYPE_VIDEO -+}; -+ -+struct plane_id { -+ enum plane_type select; -+ enum controller_id controller_id; -+}; -+ -+union display_plane_mask { -+ struct { -+ uint32_t CLONE_PRIMARY_CONTROLLER_ID_SET:1; -+ uint32_t INTERLEAVED_CONTROLLER_ID_SET:1; -+ uint32_t RESERVED:30; -+ } bits; -+ uint32_t value; -+}; -+ -+struct display_plane_format { -+ /* always valid */ -+ union display_plane_mask mask; -+ /* always valid */ -+ uint32_t display_index; -+ /* always valid */ -+ enum dc_timing_3d_format format; -+ /* always valid */ -+ enum controller_id controller_id; -+ /* valid only if CLONE_PRIMARY_CONTROLLER_ID_SET on */ -+ enum controller_id clone_primary_controller_id; -+ /* valid only if stereo interleave mode is on */ -+ enum controller_id interleave_controller_id; -+ /* valid only if crtc stereo is on */ -+ uint32_t right_eye_3d_polarity:1; -+}; -+ -+struct display_plane_set { -+ struct display_plane_format -+ set_mode_formats[MAX_COFUNC_PATH_COMMON]; -+ uint32_t reset_mode_index[ -+ MAX_COFUNC_PATH_COMMON]; -+ uint32_t num_set_mode_formats; -+ uint32_t num_reset_mode_index; -+}; -+ -+enum layers_setup { -+ LAYERS_SETUP_NOTHING = 0, -+ LAYERS_SETUP_SET, -+ LAYERS_SETUP_FREE -+}; -+ -+union plane_cfg_internal_flags { -+ struct { -+ uint32_t PLANE_OWNS_CRTC:1; -+ uint32_t RESERVED:31; -+ } bits; -+ uint32_t value; -+}; -+ -+ -+struct plane_cfg_internal { -+ const struct plane_config *config; -+ enum layers_setup setup; -+ union plane_cfg_internal_flags flags; -+}; -+ -+enum lock_type { -+ LOCK_TYPE_GRPH = 0, -+ LOCK_TYPE_SURF, -+ LOCK_TYPE_SCL, -+ LOCK_TYPE_BLND, -+ /* lock the given pipe with options above */ -+ LOCK_TYPE_THIS -+}; -+ -+enum alpha_mode { -+ ALPHA_MODE_PIXEL = 0, -+ ALPHA_MODE_PIXEL_AND_GLOBAL = 1, -+ ALPHA_MODE_GLOBAL = 2 -+}; -+ -+union alpha_mode_cfg_flag { -+ struct { -+ uint32_t MODE_IS_SET:1; -+ uint32_t MODE_MULTIPLIED_IS_SET:1; -+ uint32_t GLOBAL_ALPHA_IS_SET:1; -+ uint32_t GLOBAL_ALPHA_GAIN_IS_SET:1; -+ -+ uint32_t MULTIPLIED_MODE:1; -+ uint32_t GLOBAL_ALPHA:8; -+ /* total 21 bits! */ -+ uint32_t GLOBAL_ALPHA_GAIN:8; -+ } bits; -+ uint32_t value; -+}; -+ -+struct alpha_mode_cfg { -+ union alpha_mode_cfg_flag flags; -+ enum alpha_mode mode; -+}; -+ -+union pending_cfg_changes { -+ struct { -+ uint32_t SCL_UNLOCK_REQUIRED:1; -+ uint32_t BLND_UNLOCK_REQUIRED:1; -+ uint32_t INPUT_CSC_SWITCH_REQUIRED:1; -+ uint32_t OUTPUT_CSC_SWITCH_REQUIRED:1; -+ } bits; -+ uint32_t value; -+}; -+ -+struct pending_plane_changes { -+ union pending_cfg_changes changes; -+ struct plane_id id; -+}; -+ -+ -+#endif /* __DAL_ISR_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/link_encoder_types.h b/drivers/gpu/drm/amd/dal/include/link_encoder_types.h -new file mode 100644 -index 0000000..2a59902 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/link_encoder_types.h -@@ -0,0 +1,32 @@ -+/* -+ * link_encoder_types.h -+ * -+ * Created on: Oct 6, 2015 -+ * Author: yonsun -+ */ -+ -+#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ -+#define DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ -+ -+#include "encoder_interface.h" -+ -+struct link_enc_status { -+ int dummy; /*TODO*/ -+}; -+struct link_encoder { -+ struct adapter_service *adapter_service; -+ int32_t be_engine_offset; -+ int32_t aux_channel_offset; -+ int32_t transmitter_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; -+}; -+ -+#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/include/link_service_interface.h b/drivers/gpu/drm/amd/dal/include/link_service_interface.h -new file mode 100644 -index 0000000..2ac9311 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/link_service_interface.h -@@ -0,0 +1,202 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_LINK_SERVICE_INTERFACE_H__ -+#define __DAL_LINK_SERVICE_INTERFACE_H__ -+ -+#include "include/link_service_types.h" -+ -+/* forward declaration */ -+struct link_service; -+struct hw_crtc_timing; -+struct hw_path_mode; -+struct display_path; -+struct hw_path_mode_set; -+struct link_training_preference; -+enum ddc_result; -+ -+struct link_service *dal_link_service_create( -+ struct link_service_init_data *init_data); -+ -+void dal_link_service_destroy( -+ struct link_service **ls); -+ -+enum link_service_type dal_ls_get_link_service_type( -+ struct link_service *link_service); -+ -+bool dal_ls_validate_mode_timing( -+ struct link_service *ls, -+ uint32_t display_index, -+ const struct hw_crtc_timing *timing, -+ struct link_validation_flags flags); -+ -+bool dal_ls_get_mst_sink_info( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct mst_sink_info *sink_info); -+ -+bool dal_ls_get_gtc_sync_status( -+ struct link_service *ls); -+ -+bool dal_ls_enable_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_disable_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *poath_mode); -+ -+bool dal_ls_optimized_enable_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct display_path *display_path); -+ -+void dal_ls_update_stream_features( -+ struct link_service *ls, -+ const struct hw_path_mode *path_mode); -+ -+bool dal_ls_blank_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_unblank_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_pre_mode_change( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_post_mode_change( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_power_on_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+bool dal_ls_power_off_stream( -+ struct link_service *ls, -+ uint32_t display_index, -+ struct hw_path_mode *path_mode); -+ -+void dal_ls_retrain_link( -+ struct link_service *ls, -+ struct hw_path_mode_set *path_set); -+ -+bool dal_ls_get_current_link_setting( -+ struct link_service *ls, -+ struct link_settings *link_settings); -+ -+void dal_ls_connect_link( -+ struct link_service *ls, -+ const struct display_path *display_path, -+ bool initial_detection); -+ -+void dal_ls_disconnect_link( -+ struct link_service *ls); -+ -+bool dal_ls_is_mst_network_present( -+ struct link_service *ls); -+ -+void dal_ls_invalidate_down_stream_devices( -+ struct link_service *ls); -+ -+bool dal_ls_are_mst_displays_cofunctional( -+ struct link_service *ls, -+ const uint32_t *array_display_index, -+ uint32_t len); -+ -+bool dal_ls_is_sink_present_at_display_index( -+ struct link_service *ls, -+ uint32_t display_index); -+ -+struct ddc_service *dal_ls_obtain_mst_ddc_service( -+ struct link_service *ls, -+ uint32_t display_index); -+ -+void dal_ls_release_mst_ddc_service( -+ struct link_service *ls, -+ struct ddc_service *ddc_service); -+ -+void dal_ls_release_hw( -+ struct link_service *ls); -+ -+bool dal_ls_associate_link( -+ struct link_service *ls, -+ uint32_t display_index, -+ uint32_t link_index, -+ bool is_internal_link); -+ -+bool dal_dpsst_ls_set_overridden_trained_link_settings( -+ struct link_service *ls, -+ const struct link_settings *link_settings); -+ -+void dal_dpsst_ls_set_link_training_preference( -+ struct link_service *ls, -+ const struct link_training_preference *ltp); -+ -+struct link_training_preference -+ dal_dpsst_ls_get_link_training_preference( -+ struct link_service *ls); -+ -+bool dal_ls_should_send_notification( -+ struct link_service *ls); -+ -+uint32_t dal_ls_get_notification_display_index( -+ struct link_service *ls); -+ -+enum ddc_result dal_dpsst_ls_read_dpcd_data( -+ struct link_service *ls, -+ uint32_t address, -+ uint8_t *data, -+ uint32_t size); -+ -+enum ddc_result dal_dpsst_ls_write_dpcd_data( -+ struct link_service *ls, -+ uint32_t address, -+ const uint8_t *data, -+ uint32_t size); -+ -+bool dal_ls_is_link_psr_supported(struct link_service *ls); -+ -+bool dal_ls_is_stream_drr_supported(struct link_service *ls); -+ -+void dal_ls_set_link_psr_capabilities( -+ struct link_service *ls, -+ struct psr_caps *psr_caps); -+ -+void dal_ls_get_link_psr_capabilities( -+ struct link_service *ls, -+ struct psr_caps *psr_caps); -+ -+#endif /* __DAL_LINK_SERVICE_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/link_service_types.h b/drivers/gpu/drm/amd/dal/include/link_service_types.h -new file mode 100644 -index 0000000..0df5687 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/link_service_types.h -@@ -0,0 +1,428 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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 "dal_services_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 link_service_type { -+ LINK_SERVICE_TYPE_LEGACY = 0, -+ LINK_SERVICE_TYPE_DP_SST, -+ LINK_SERVICE_TYPE_DP_MST, -+ LINK_SERVICE_TYPE_MAX -+}; -+ -+struct link_validation_flags { -+ uint32_t DYNAMIC_VALIDATION:1; -+ uint32_t CANDIDATE_TIMING:1; -+ uint32_t START_OF_VALIDATION:1; -+}; -+ -+/* Post Cursor 2 is optional for transmitter -+ * and it applies only to the main link operating at HBR2 -+ */ -+enum post_cursor2 { -+ POST_CURSOR2_DISABLED = 0, /* direct HW translation! */ -+ POST_CURSOR2_LEVEL1, -+ POST_CURSOR2_LEVEL2, -+ POST_CURSOR2_LEVEL3, -+ POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, -+}; -+ -+enum voltage_swing { -+ VOLTAGE_SWING_LEVEL0 = 0, /* direct HW translation! */ -+ VOLTAGE_SWING_LEVEL1, -+ VOLTAGE_SWING_LEVEL2, -+ VOLTAGE_SWING_LEVEL3, -+ VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3 -+}; -+ -+enum pre_emphasis { -+ PRE_EMPHASIS_DISABLED = 0, /* direct HW translation! */ -+ PRE_EMPHASIS_LEVEL1, -+ PRE_EMPHASIS_LEVEL2, -+ PRE_EMPHASIS_LEVEL3, -+ PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3 -+}; -+ -+enum dpcd_value_mask { -+ DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F, -+ DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40, -+ DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80, -+ DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01, -+ DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01 -+}; -+ -+enum dp_power_state { -+ DP_POWER_STATE_D0 = 1, -+ DP_POWER_STATE_D3 -+}; -+ -+enum dpcd_downstream_port_types { -+ DPCD_DOWNSTREAM_DP, -+ DPCD_DOWNSTREAM_VGA, -+ DPCD_DOWNSTREAM_DVI_HDMI, -+ /* has no EDID (TV, CV) */ -+ DPCD_DOWNSTREAM_NON_DDC -+}; -+ -+enum edp_revision { -+ /* eDP version 1.1 or lower */ -+ EDP_REVISION_11 = 0x00, -+ /* eDP version 1.2 */ -+ EDP_REVISION_12 = 0x01, -+ /* eDP version 1.3 */ -+ EDP_REVISION_13 = 0x02 -+}; -+ -+enum lane_count { -+ LANE_COUNT_UNKNOWN = 0, -+ LANE_COUNT_ONE = 1, -+ LANE_COUNT_TWO = 2, -+ LANE_COUNT_FOUR = 4, -+ LANE_COUNT_EIGHT = 8, -+ LANE_COUNT_DP_MAX = LANE_COUNT_FOUR -+}; -+ -+/* This is actually a reference clock (27MHz) multiplier -+ * 162MBps bandwidth for 1.62GHz like rate, -+ * 270MBps for 2.70GHz, -+ * 324MBps for 3.24Ghz, -+ * 540MBps for 5.40GHz -+ */ -+enum link_rate { -+ LINK_RATE_UNKNOWN = 0, -+ LINK_RATE_LOW = 0x06, -+ LINK_RATE_HIGH = 0x0A, -+ LINK_RATE_RBR2 = 0x0C, -+ LINK_RATE_HIGH2 = 0x14 -+}; -+ -+enum { -+ LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ -+}; -+ -+enum link_spread { -+ LINK_SPREAD_DISABLED = 0x00, -+ /* 0.5 % downspread 30 kHz */ -+ LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10, -+ /* 0.5 % downspread 33 kHz */ -+ LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11 -+}; -+ -+/* DPCD_ADDR_DOWNSTREAM_PORT_PRESENT register value */ -+union dpcd_downstream_port { -+ struct { -+#if defined(LITTLEENDIAN_CPU) -+ uint8_t PRESENT:1; -+ uint8_t TYPE:2; -+ uint8_t FORMAT_CONV:1; -+ uint8_t RESERVED:4; -+#elif defined(BIGENDIAN_CPU) -+ uint8_t RESERVED:4; -+ uint8_t FORMAT_CONV:1; -+ uint8_t TYPE:2; -+ uint8_t PRESENT:1; -+#else -+ #error ARCH not defined! -+#endif -+ } bits; -+ -+ uint8_t raw; -+}; -+ -+/* DPCD_ADDR_SINK_COUNT register value */ -+union dpcd_sink_count { -+ struct { -+#if defined(LITTLEENDIAN_CPU) -+ uint8_t SINK_COUNT:6; -+ uint8_t CP_READY:1; -+ uint8_t RESERVED:1; -+#elif defined(BIGENDIAN_CPU) -+ uint8_t RESERVED:1; -+ uint8_t CP_READY:1; -+ uint8_t SINK_COUNT:6; -+#else -+ #error ARCH not defined! -+#endif -+ } bits; -+ -+ uint8_t raw; -+}; -+ -+struct link_settings { -+ enum lane_count lane_count; -+ enum link_rate link_rate; -+ enum link_spread link_spread; -+}; -+ -+struct lane_settings { -+ enum voltage_swing VOLTAGE_SWING; -+ enum pre_emphasis PRE_EMPHASIS; -+ enum post_cursor2 POST_CURSOR2; -+}; -+ -+struct link_training_settings { -+ struct link_settings link_settings; -+ struct lane_settings lane_settings[LANE_COUNT_DP_MAX]; -+ bool allow_invalid_msa_timing_param; -+}; -+ -+enum hw_dp_training_pattern { -+ HW_DP_TRAINING_PATTERN_1 = 0, -+ HW_DP_TRAINING_PATTERN_2, -+ HW_DP_TRAINING_PATTERN_3 -+}; -+ -+/*TODO: Move this enum test harness*/ -+/* Test patterns*/ -+enum dp_test_pattern { -+ /* Input data is pass through Scrambler -+ * and 8b10b Encoder straight to output*/ -+ DP_TEST_PATTERN_VIDEO_MODE = 0, -+ /* phy test patterns*/ -+ DP_TEST_PATTERN_D102, -+ DP_TEST_PATTERN_SYMBOL_ERROR, -+ DP_TEST_PATTERN_PRBS7, -+ -+ DP_TEST_PATTERN_80BIT_CUSTOM, -+ DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE, -+ -+ /* Link Training Patterns */ -+ DP_TEST_PATTERN_TRAINING_PATTERN1, -+ DP_TEST_PATTERN_TRAINING_PATTERN2, -+ DP_TEST_PATTERN_TRAINING_PATTERN3, -+ -+ /* link test patterns*/ -+ DP_TEST_PATTERN_COLOR_SQUARES, -+ DP_TEST_PATTERN_COLOR_SQUARES_CEA, -+ DP_TEST_PATTERN_VERTICAL_BARS, -+ DP_TEST_PATTERN_HORIZONTAL_BARS, -+ DP_TEST_PATTERN_COLOR_RAMP, -+ -+ /* audio test patterns*/ -+ DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED, -+ DP_TEST_PATTERN_AUDIO_SAWTOOTH, -+ -+ DP_TEST_PATTERN_UNSUPPORTED -+}; -+ -+enum dp_panel_mode { -+ /* not required */ -+ DP_PANEL_MODE_DEFAULT, -+ /* standard mode for eDP */ -+ DP_PANEL_MODE_EDP, -+ /* external chips specific settings */ -+ DP_PANEL_MODE_SPECIAL -+}; -+ -+/** -+ * @brief LinkServiceInitOptions to set certain bits -+ */ -+struct link_service_init_options { -+ uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; -+}; -+ -+/** -+ * @brief data required to initialize LinkService -+ */ -+struct link_service_init_data { -+ /* number of displays indices which the MST Mgr would manange*/ -+ uint32_t num_of_displays; -+ enum link_service_type link_type; -+ /*struct mst_mgr_callback_object*topology_change_callback;*/ -+ /* native aux access */ -+ struct ddc_service *dpcd_access_srv; -+ /* for calling HWSS to program HW */ -+ struct hw_sequencer *hwss; -+ /* the source which to register IRQ on */ -+ enum dc_irq_source irq_src_hpd_rx; -+ enum dc_irq_source irq_src_dp_sink; -+ /* other init options such as SW Workarounds */ -+ struct link_service_init_options init_options; -+ uint32_t connector_enum_id; -+ struct graphics_object_id connector_id; -+ struct adapter_service *adapter_service; -+ struct dc_context *ctx; -+ struct topology_mgr *tm; -+}; -+ -+/** -+ * @brief LinkServiceInitOptions to set certain bits -+ */ -+struct LinkServiceInitOptions { -+ uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; -+}; -+ -+/* DPCD_ADDR_TRAINING_LANEx_SET registers value */ -+union dpcd_training_lane_set { -+ struct { -+#if defined(LITTLEENDIAN_CPU) -+ uint8_t VOLTAGE_SWING_SET:2; -+ uint8_t MAX_SWING_REACHED:1; -+ uint8_t PRE_EMPHASIS_SET:2; -+ uint8_t MAX_PRE_EMPHASIS_REACHED:1; -+ /* following is reserved in DP 1.1 */ -+ uint8_t POST_CURSOR2_SET:2; -+#elif defined(BIGENDIAN_CPU) -+ uint8_t POST_CURSOR2_SET:2; -+ uint8_t MAX_PRE_EMPHASIS_REACHED:1; -+ uint8_t PRE_EMPHASIS_SET:2; -+ uint8_t MAX_SWING_REACHED:1; -+ uint8_t VOLTAGE_SWING_SET:2; -+#else -+ #error ARCH not defined! -+#endif -+ } bits; -+ -+ uint8_t raw; -+}; -+ -+/* DPCD_ADDR_TRAINING_LANEx_SET2 registers value - since DP 1.2 */ -+union dpcd_training_lanes_set2 { -+ struct { -+#if defined(LITTLEENDIAN_CPU) -+ uint8_t LANE0_POST_CURSOR2_SET:2; -+ uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1; -+ uint8_t LANE0_RESERVED:1; -+ uint8_t LANE1_POST_CURSOR2_SET:2; -+ uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1; -+ uint8_t LANE1_RESERVED:1; -+#elif defined(BIGENDIAN_CPU) -+ uint8_t LANE1_RESERVED:1; -+ uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1; -+ uint8_t LANE1_POST_CURSOR2_SET:2; -+ uint8_t LANE0_RESERVED:1; -+ uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1; -+ uint8_t LANE0_POST_CURSOR2_SET:2; -+#else -+ #error ARCH not defined! -+#endif -+ } bits; -+ -+ uint8_t raw; -+}; -+ -+/** -+ * @brief represent the 16 byte -+ * global unique identifier -+ */ -+struct mst_guid { -+ uint8_t ids[16]; -+}; -+ -+/** -+ * @brief represents the relative address used -+ * to identify a node in MST topology network -+ */ -+struct mst_rad { -+ /* number of links. rad[0] up to -+ * rad [linkCount - 1] are valid. */ -+ uint32_t rad_link_count; -+ /* relative address. rad[0] is the -+ * first device connected to the source. */ -+ uint8_t rad[15]; -+ /* extra 10 bytes for underscores; for e.g.:2_1_8*/ -+ int8_t rad_str[25]; -+}; -+ -+/** -+ * @brief this structure is used to report -+ * properties associated to a sink device -+ */ -+struct mst_sink_info { -+ /* global unique identifier */ -+ struct mst_guid guid; -+ /* relative address */ -+ struct mst_rad rad; -+ /* total bandwidth available on the DP connector */ -+ uint32_t total_available_bandwidth_in_mbps; -+ /* bandwidth allocated to the sink device. */ -+ uint32_t allocated_bandwidth_in_mbps; -+ /* bandwidth consumed to support for the current mode. */ -+ uint32_t consumed_bandwidth_in_mbps; -+}; -+ -+/** -+ * @brief represent device information in MST topology -+ */ -+struct mst_device_info { -+ /* global unique identifier*/ -+ struct mst_guid guid; -+ /* relative address*/ -+ struct mst_rad rad; -+}; -+ -+/* DP MST stream allocation (payload bandwidth number) */ -+struct dp_mst_stream_allocation { -+ /* stream engine id (DIG) */ -+ enum engine_id engine; -+ /* number of slots required for the DP stream in -+ * transport packet */ -+ uint32_t slot_count; -+ uint32_t pbn; -+ uint32_t pbn_per_slot; -+}; -+ -+/* DP MST stream allocation table */ -+struct dp_mst_stream_allocation_table { -+ /* number of DP video streams */ -+ uint32_t stream_count; -+ /* array of stream allocations */ -+ struct dp_mst_stream_allocation stream_allocations[1]; -+}; -+ -+struct dp_test_event_data { -+ /*size of parameters (starting from params) in bytes*/ -+ uint32_t size; -+ /*parameters block*/ -+ uint32_t params[1]; -+}; -+ -+struct psr_caps { -+ /* These parameters are from PSR capabilities reported by Sink DPCD. */ -+ uint8_t psr_version; -+ uint32_t psr_rfb_setup_time; -+ bool psr_exit_link_training_req; -+ -+ /* These parameters are calculated in Driver, based on display timing -+ * and Sink capabilities. -+ * If VBLANK region is too small and Sink takes a long time to power up -+ * Remote Frame Buffer, it may take an extra frame to enter PSR */ -+ bool psr_frame_capture_indication_req; -+ uint32_t psr_sdp_transmit_line_num_deadline; -+}; -+ -+#endif /*__DAL_LINK_SERVICE_TYPES_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/include/logger_interface.h b/drivers/gpu/drm/amd/dal/include/logger_interface.h -new file mode 100644 -index 0000000..4d945ea ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/logger_interface.h -@@ -0,0 +1,153 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_LOGGER_INTERFACE_H__ -+#define __DAL_LOGGER_INTERFACE_H__ -+ -+#include "logger_types.h" -+ -+struct dal_logger; -+struct dc_context; -+union logger_flags; -+ -+/* -+ * TODO: This logger functionality needs to be implemented and reworked. -+ */ -+ -+ -+/* -+ * -+ * DAL logger functionality -+ * -+ */ -+ -+struct dal_logger *dal_logger_create(struct dc_context *ctx); -+ -+uint32_t dal_logger_destroy(struct dal_logger **logger); -+ -+uint32_t dal_logger_get_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor); -+ -+uint32_t dal_logger_set_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor); -+ -+uint32_t dal_logger_get_masks( -+ struct dal_logger *logger, -+ enum log_major lvl_major); -+ -+void dal_logger_set_masks( -+ struct dal_logger *logger, -+ enum log_major lvl_major, uint32_t log_mask); -+ -+uint32_t dal_logger_unset_mask( -+ struct dal_logger *logger, -+ enum log_major lvl_major, enum log_minor lvl_minor); -+ -+bool dal_logger_should_log( -+ struct dal_logger *logger, -+ enum log_major major, -+ enum log_minor minor); -+ -+uint32_t dal_logger_get_flags( -+ struct dal_logger *logger); -+ -+void dal_logger_set_flags( -+ struct dal_logger *logger, -+ union logger_flags flags); -+ -+void dal_logger_write( -+ struct dal_logger *logger, -+ enum log_major major, -+ enum log_minor minor, -+ const char *msg, -+ ...); -+ -+void dal_logger_append( -+ struct log_entry *entry, -+ const char *msg, -+ ...); -+ -+uint32_t dal_logger_read( -+ struct dal_logger *logger, -+ uint32_t output_buffer_size, -+ char *output_buffer, -+ uint32_t *bytes_read, -+ bool single_line); -+ -+void dal_logger_open( -+ struct dal_logger *logger, -+ struct log_entry *entry, -+ enum log_major major, -+ enum log_minor minor); -+ -+void dal_logger_close(struct log_entry *entry); -+ -+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger); -+ -+uint32_t dal_logger_set_buffer_size( -+ struct dal_logger *logger, -+ uint32_t new_size); -+ -+const struct log_major_info *dal_logger_enum_log_major_info( -+ struct dal_logger *logger, -+ unsigned int enum_index); -+ -+const struct log_minor_info *dal_logger_enum_log_minor_info( -+ struct dal_logger *logger, -+ enum log_major major, -+ unsigned int enum_index); -+ -+/* Any function which is empty or have incomplete implementation should be -+ * marked by this macro. -+ * Note that the message will be printed exactly once for every function -+ * it is used in order to avoid repeating of the same message. */ -+#define DAL_LOGGER_NOT_IMPL(log_minor, fmt, ...) \ -+{ \ -+ static bool print_not_impl = true; \ -+\ -+ if (print_not_impl == true) { \ -+ print_not_impl = false; \ -+ dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \ -+ log_minor, "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \ -+ } \ -+} -+ -+/****************************************************************************** -+ * Convenience macros to save on typing. -+ *****************************************************************************/ -+ -+#define DC_ERROR(...) \ -+ dal_logger_write(dc_ctx->logger, \ -+ LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_DC, \ -+ __VA_ARGS__); -+ -+#define DC_SYNC_INFO(...) \ -+ dal_logger_write(dc_ctx->logger, \ -+ LOG_MAJOR_SYNC, LOG_MINOR_SYNC_TIMING, \ -+ __VA_ARGS__); -+ -+#endif /* __DAL_LOGGER_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/logger_types.h b/drivers/gpu/drm/amd/dal/include/logger_types.h -new file mode 100644 -index 0000000..6147999 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/logger_types.h -@@ -0,0 +1,356 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_LOGGER_TYPES_H__ -+#define __DAL_LOGGER_TYPES_H__ -+ -+ -+/* -+ * TODO: This logger functionality needs to be implemented and reworked. -+ */ -+ -+ -+struct dal_logger; -+ -+enum log_major { -+/*00*/ -+ LOG_MAJOR_ERROR = 0, /*< DAL subcomponent error MSG*/ -+/*01*/ LOG_MAJOR_WARNING, /*< DAL subcomponent warning MSG*/ -+/*02*/ LOG_MAJOR_INTERFACE_TRACE,/*< DAL subcomponent interface tracing*/ -+/*03*/ LOG_MAJOR_HW_TRACE, /*< Log ASIC register read/write, -+ * ATOMBIOS exec table call and delays*/ -+ -+/*04*/ LOG_MAJOR_MST, /*< related to multi-stream*/ -+/*05*/ LOG_MAJOR_DCS, /*< related to Dcs*/ -+/*06*/ LOG_MAJOR_DCP, /*< related to Dcp grph and ovl,gamam and csc*/ -+/*07*/ LOG_MAJOR_BIOS, /*< related to BiosParser*/ -+/*08*/ LOG_MAJOR_REGISTER, /*< register access*/ -+/*09*/ LOG_MAJOR_INFO_PACKETS, /*< info packets*/ -+/*10*/ LOG_MAJOR_DSAT, /*< related -+ * to Display System Analysis Tool*/ -+/*11*/ LOG_MAJOR_EC, /*< External Components - MCIL Events/queries, -+ * PPLib notifications/queries*/ -+/*12*/ LOG_MAJOR_BWM, /*< related to Bandwidth Manager*/ -+/*13*/ LOG_MAJOR_MODE_ENUM, /*< related to mode enumeration*/ -+/*14*/ LOG_MAJOR_I2C_AUX, /*< i2c and aux channel log*/ -+/*15*/ LOG_MAJOR_LINE_BUFFER, /*< Line Buffer object logging activity*/ -+/*16*/ LOG_MAJOR_HWSS, /*< HWSS object logging activity*/ -+/*17*/ LOG_MAJOR_OPTIMIZATION, /*< Optimization code path*/ -+/*18*/ LOG_MAJOR_PERF_MEASURE, /*< Performance measurement dumps*/ -+/*19*/ LOG_MAJOR_SYNC, /*< related to HW and SW Synchronization*/ -+/*20*/ LOG_MAJOR_BACKLIGHT, /*< related to backlight */ -+/*21*/ LOG_MAJOR_INTERRUPTS, /*< logging for all interrupts */ -+ -+/*22*/ LOG_MAJOR_TM, /*< related to Topology Manager*/ -+/*23*/ LOG_MAJOR_DISPLAY_SERVICE, /*< related to Display Service*/ -+/*24*/ LOG_MAJOR_FEATURE_OVERRIDE, /*< related to features*/ -+/*25*/ LOG_MAJOR_DETECTION, /*< related to detection*/ -+ LOG_MAJOR_COUNT, /*< count of the Major categories*/ -+}; -+ -+/** -+* @brief defines minor switch for logging. each of these define sub category -+* of log message per LogMajor -+*/ -+ -+ -+enum log_minor { -+ -+ /* Special case for 'all' checkbox */ -+ LOG_MINOR_MASK_ALL = (uint32_t)-1, /* 0xFFFFFFFF */ -+/** -+* @brief defines minor category for -+* LOG_MAJOR_ERROR, -+* LOG_MAJOR_WARNING, -+* LOG_MAJOR_INTERFACE_TRACE -+* -+* @note each DAL subcomponent should have a corresponding enum -+*/ -+ LOG_MINOR_COMPONENT_LINK_SERVICE = 0, -+ LOG_MINOR_COMPONENT_DAL_INTERFACE, -+ LOG_MINOR_COMPONENT_HWSS, -+ LOG_MINOR_COMPONENT_ADAPTER_SERVICE, -+ LOG_MINOR_COMPONENT_DISPLAY_SERVICE, -+ LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, -+ LOG_MINOR_COMPONENT_ENCODER, -+ LOG_MINOR_COMPONENT_I2C_AUX, -+ LOG_MINOR_COMPONENT_AUDIO, -+ LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, -+ LOG_MINOR_COMPONENT_DMCU, -+ LOG_MINOR_COMPONENT_GPU, -+ LOG_MINOR_COMPONENT_CONTROLLER, -+ LOG_MINOR_COMPONENT_ISR, -+ LOG_MINOR_COMPONENT_BIOS, -+ LOG_MINOR_COMPONENT_DC, -+ LOG_MINOR_COMPONENT_IRQ_SERVICE, -+ -+/** -+* @brief define minor category for LogMajor_HardwareTrace -+* -+* @note defines functionality based HW programming trace -+*/ -+ LOG_MINOR_HW_TRACE_MST = 0, -+ LOG_MINOR_HW_TRACE_TRAVIS, -+ LOG_MINOR_HW_TRACE_HOTPLUG, -+ LOG_MINOR_HW_TRACE_LINK_TRAINING, -+ LOG_MINOR_HW_TRACE_SET_MODE, -+ LOG_MINOR_HW_TRACE_RESUME_S3, -+ LOG_MINOR_HW_TRACE_RESUME_S4, -+ LOG_MINOR_HW_TRACE_BOOTUP, -+ LOG_MINOR_HW_TRACE_AUDIO, -+ LOG_MINOR_HW_TRACE_HPD_IRQ, -+ LOG_MINOR_HW_TRACE_INTERRUPT, -+ LOG_MINOR_HW_TRACE_MPO, -+ -+/** -+* @brief defines minor category for LogMajor_Mst -+* -+* @note define sub functionality related to MST -+*/ -+ LOG_MINOR_MST_IRQ_HPD_RX = 0, -+ LOG_MINOR_MST_IRQ_TIMER, -+ LOG_MINOR_MST_NATIVE_AUX, -+ LOG_MINOR_MST_SIDEBAND_MSG, -+ LOG_MINOR_MST_MSG_TRANSACTION, -+ LOG_MINOR_MST_SIDEBAND_MSG_PARSED, -+ LOG_MINOR_MST_MSG_TRANSACTION_PARSED, -+ LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, -+ LOG_MINOR_MST_PROGRAMMING, -+ LOG_MINOR_MST_TOPOLOGY_DISCOVERY, -+ LOG_MINOR_MST_CONVERTER_CAPS, -+ -+/** -+* @brief defines minor category for LogMajor_DCS -+* -+* @note should define sub functionality related to Dcs -+*/ -+ LOG_MINOR_DCS_EDID_EMULATOR = 0, -+ LOG_MINOR_DCS_DONGLE_DETECTION, -+ -+/** -+* @brief defines minor category for DCP -+* -+* @note should define sub functionality related to Dcp -+*/ -+ LOG_MINOR_DCP_GAMMA_GRPH = 0, -+ LOG_MINOR_DCP_GAMMA_OVL, -+ LOG_MINOR_DCP_CSC_GRPH, -+ LOG_MINOR_DCP_CSC_OVL, -+ LOG_MINOR_DCP_SCALER, -+ LOG_MINOR_DCP_SCALER_TABLES, -+/** -+* @brief defines minor category for LogMajor_Bios -+* -+* @note define sub functionality related to BiosParser -+*/ -+ LOG_MINOR_BIOS_CMD_TABLE = 0, -+/** -+* @brief defines minor category for LogMajor_Bios -+* -+* @note define sub functionality related to BiosParser -+*/ -+ LOG_MINOR_REGISTER_INDEX = 0, -+/** -+* @brief defines minor category for info packets -+* -+*/ -+ LOG_MINOR_INFO_PACKETS_HDMI = 0, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_DSAT -+* -+* @note define sub functionality related to Display System Analysis Tool -+*/ -+ LOG_MINOR_DSAT_LOGGER = 0, -+ LOG_MINOR_DSAT_GET_EDID, -+ LOG_MINOR_DSAT_EDID_OVERRIDE, -+ LOG_MINOR_DSAT_SET_ADJUSTMENTS, -+ LOG_MINOR_DSAT_GET_ADJUSTMENTS, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_EC -+* -+* @note define sub functionality related to External components notifications -+*/ -+ LOG_MINOR_EC_PPLIB_NOTIFY = 0, -+ LOG_MINOR_EC_PPLIB_QUERY, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_BWM -+* -+* @note define sub functionality related to Bandwidth Manager -+*/ -+ LOG_MINOR_BWM_MODE_VALIDATION = 0, -+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, -+ -+/** -+* @brief define minor category for LogMajor_ModeEnum -+* -+* @note defines functionality mode enumeration trace -+*/ -+ LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES = 0, -+ LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, -+ LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, -+ LOG_MINOR_MODE_ENUM_TS_LIST, -+ LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, -+ LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, -+ -+/** -+* @brief defines minor category for LogMajor_I2C_AUX -+* -+* @note define sub functionality related to I2c and Aux Channel Log -+*/ -+ LOG_MINOR_I2C_AUX_LOG = 0, -+ LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, -+ LOG_MINOR_I2C_AUX_CFG, -+ -+/** -+* @brief defines minor category for LogMajor_LineBuffer -+* -+* @note define sub functionality related to LineBuffer -+*/ -+ LOG_MINOR_LINE_BUFFER_POWERGATING = 0, -+ -+/** -+* @brief defines minor category for LogMajor_HWSS -+* -+* @note define sub functionality related to HWSS -+*/ -+ LOG_MINOR_HWSS_TAPS_VALIDATION = 0, -+ -+/** -+* @brief defines minor category for LogMajor_Optimization -+* -+* @note define sub functionality related to Optimization -+*/ -+ LOG_MINOR_OPTMZ_GENERAL = 0, -+ LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE, -+ -+/** -+* @brief defines minor category for LogMajor_PerfMeasure -+* -+* @note define sub functionality related to Performance measurement dumps -+*/ -+ LOG_MINOR_PERF_MEASURE_GENERAL = 0, -+ LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, -+ -+/** -+* @brief defines minor category for LogMajor_Sync -+* -+* @note define sub functionality related to HW and SW Synchronization -+*/ -+ LOG_MINOR_SYNC_HW_CLOCK_ADJUST = 0, -+ LOG_MINOR_SYNC_TIMING, -+ -+/** -+* @brief defines minor category for LogMajor_Backlight -+* -+* @note define sub functionality related to backlight (including VariBright) -+*/ -+ LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS = 0, -+ LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, -+ LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, -+ LOG_MINOR_BACKLIGHT_INTERFACE, -+ LOG_MINOR_BACKLIGHT_LID, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_TM -+* -+* @note define sub functionality related to Topology Manager -+*/ -+ LOG_MINOR_TM_INFO = 0, -+ LOG_MINOR_TM_IFACE_TRACE, -+ LOG_MINOR_TM_RESOURCES, -+ LOG_MINOR_TM_ENCODER_CTL, -+ LOG_MINOR_TM_ENG_ASN, -+ LOG_MINOR_TM_CONTROLLER_ASN, -+ LOG_MINOR_TM_PWR_GATING, -+ LOG_MINOR_TM_BUILD_DSP_PATH, -+ LOG_MINOR_TM_DISPLAY_DETECT, -+ LOG_MINOR_TM_LINK_SRV, -+ LOG_MINOR_TM_NOT_IMPLEMENTED, -+ LOG_MINOR_TM_COFUNC_PATH, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_DISPLAY_SERVICE -+* -+* @note define sub functionality related to Display Service -+*/ -+ LOG_MINOR_DS_MODE_SETTING = 0, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_FEATURE_OVERRIDE -+* -+* @note define sub functionality related to features in adapter service -+*/ -+ LOG_MINOR_FEATURE_OVERRIDE = 0, -+ -+/** -+* @brief defines minor category for LOG_MAJOR_DETECTION -+* -+* @note define sub functionality related to detection -+*/ -+ LOG_MINOR_DETECTION_EDID_PARSER = 0, -+ LOG_MINOR_DETECTION_DP_CAPS, -+}; -+ -+union logger_flags { -+ struct { -+ uint32_t ENABLE_CONSOLE:1; /* Print to console */ -+ uint32_t ENABLE_BUFFER:1; /* Print to buffer */ -+ uint32_t RESERVED:30; -+ } bits; -+ uint32_t value; -+}; -+ -+struct log_entry { -+ -+ struct dal_logger *logger; -+ enum log_major major; -+ enum log_minor minor; -+ -+ char *buf; -+ uint32_t buf_offset; -+ uint32_t max_buf_bytes; -+}; -+ -+/** -+* Structure for enumerating LogMajors and LogMinors -+*/ -+ -+#define MAX_MAJOR_NAME_LEN 32 -+#define MAX_MINOR_NAME_LEN 32 -+ -+struct log_major_info { -+ enum log_major major; -+ char major_name[MAX_MAJOR_NAME_LEN]; -+}; -+ -+struct log_minor_info { -+ enum log_minor minor; -+ char minor_name[MAX_MINOR_NAME_LEN]; -+}; -+ -+#endif /* __DAL_LOGGER_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/mode_manager_types.h b/drivers/gpu/drm/amd/dal/include/mode_manager_types.h -new file mode 100644 -index 0000000..576b21f ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/mode_manager_types.h -@@ -0,0 +1,71 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_MODE_MANAGER_TYPES_H__ -+#define __DAL_MODE_MANAGER_TYPES_H__ -+ -+#include "bit_set.h" -+#include "dc_types.h" -+ -+static inline void stereo_3d_view_reset(struct stereo_3d_view *stereo_3d_view) -+{ -+ stereo_3d_view->view_3d_format = VIEW_3D_FORMAT_NONE; -+ stereo_3d_view->flags.raw = 0; -+} -+ -+bool dal_refresh_rate_is_equal( -+ const struct refresh_rate *lhs, -+ const struct refresh_rate *rhs); -+ -+bool dal_refresh_rate_less_than( -+ const struct refresh_rate *lhs, -+ const struct refresh_rate *rhs); -+ -+void refresh_rate_from_mode_info( -+ struct refresh_rate *, -+ const struct dc_mode_info *); -+bool dal_solution_less_than(const void *lhs, const void *rhs); -+bool dal_view_is_equal(const struct view *lhs, const struct view *rhs); -+ -+struct pixel_format_list { -+ uint32_t set; -+ struct bit_set_iterator_32 iter; -+}; -+ -+void dal_pixel_format_list_reset_iterator(struct pixel_format_list *pfl); -+void dal_pixel_format_list_zero_iterator(struct pixel_format_list *pfl); -+ -+void dal_pixel_format_list_construct( -+ struct pixel_format_list *pfl, -+ uint32_t mask); -+ -+uint32_t dal_pixel_format_list_next(struct pixel_format_list *pfl); -+ -+uint32_t dal_pixel_format_list_get_count( -+ const struct pixel_format_list *pfl); -+enum pixel_format dal_pixel_format_list_get_pixel_format( -+ const struct pixel_format_list *pfl); -+ -+#endif /* __DAL_MODE_MANAGER_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/mode_query_interface.h b/drivers/gpu/drm/amd/dal/include/mode_query_interface.h -new file mode 100644 -index 0000000..1d20e73 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/mode_query_interface.h -@@ -0,0 +1,93 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_MODE_QUERY_INTERFACE_H__ -+#define __DAL_MODE_QUERY_INTERFACE_H__ -+ -+#include "include/set_mode_types.h" -+#include "include/mode_manager_types.h" -+ -+enum query_option { -+ QUERY_OPTION_ALLOW_PAN, -+ QUERY_OPTION_ALLOW_PAN_NO_VIEW_RESTRICTION, -+ QUERY_OPTION_PAN_ON_LIMITED_RESOLUTION_DISP_PATH, -+ QUERY_OPTION_NO_PAN, -+ QUERY_OPTION_NO_PAN_NO_DISPLAY_VIEW_RESTRICTION, -+ QUERY_OPTION_3D_LIMITED_CANDIDATES, -+ QUERY_OPTION_TILED_DISPLAY_PREFERRED, -+ QUERY_OPTION_MAX, -+}; -+ -+struct topology { -+ uint32_t disp_path_num; -+ uint32_t display_index[MAX_COFUNC_PATH]; -+}; -+ -+struct path_mode; -+struct mode_query; -+ -+bool dal_mode_query_pin_path_mode( -+ struct mode_query *mq, -+ const struct path_mode *path_mode); -+ -+const struct render_mode *dal_mode_query_get_current_render_mode( -+ const struct mode_query *mq); -+ -+const struct stereo_3d_view *dal_mode_query_get_current_3d_view( -+ const struct mode_query *mq); -+ -+const struct refresh_rate *dal_mode_query_get_current_refresh_rate( -+ const struct mode_query *mq); -+ -+const struct path_mode_set *dal_mode_query_get_current_path_mode_set( -+ const struct mode_query *mq); -+ -+bool dal_mode_query_select_first(struct mode_query *mq); -+bool dal_mode_query_select_next_render_mode(struct mode_query *mq); -+ -+bool dal_mode_query_select_render_mode(struct mode_query *mq, -+ const struct render_mode *render_mode); -+ -+bool dal_mode_query_select_next_view_3d_format(struct mode_query *mq); -+bool dal_mode_query_select_view_3d_format( -+ struct mode_query *mq, -+ enum view_3d_format format); -+ -+bool dal_mode_query_select_refresh_rate(struct mode_query *mq, -+ const struct refresh_rate *refresh_rate); -+ -+bool dal_mode_query_select_refresh_rate_ex(struct mode_query *mq, -+ uint32_t refresh_rate, -+ bool interlaced); -+ -+bool dal_mode_query_select_next_scaling(struct mode_query *mq); -+ -+bool dal_mode_query_select_next_refresh_rate(struct mode_query *mq); -+ -+bool dal_mode_query_base_select_next_scaling(struct mode_query *mq); -+ -+void dal_mode_query_destroy(struct mode_query **mq); -+ -+#endif /* __DAL_MODE_QUERY_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/mode_timing_list_interface.h b/drivers/gpu/drm/amd/dal/include/mode_timing_list_interface.h -new file mode 100644 -index 0000000..a558fec ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/mode_timing_list_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_MODE_TIMING_LIST_INTERFACE_H__ -+#define __DAL_MODE_TIMING_LIST_INTERFACE_H__ -+ -+ -+struct mode_timing_filter; -+struct mode_timing_list; -+ -+struct mode_timing_list *dal_mode_timing_list_create( -+ struct dal_context *ctx, -+ uint32_t display_index, -+ const struct mode_timing_filter *mt_filter); -+ -+void dal_mode_timing_list_destroy(struct mode_timing_list **mtl); -+ -+ -+uint32_t dal_mode_timing_list_get_count( -+ const struct mode_timing_list *mode_timing_list); -+ -+const struct dc_mode_timing *dal_mode_timing_list_get_timing_at_index( -+ const struct mode_timing_list *mode_timing_list, -+ uint32_t index); -+ -+const struct dc_mode_timing *dal_mode_timing_list_get_single_selected_mode_timing( -+ const struct mode_timing_list *mode_timing_list); -+ -+#endif /*__DAL_MODE_TIMING_LIST_INTERFACE_H__*/ -diff --git a/drivers/gpu/drm/amd/dal/include/overlay_interface.h b/drivers/gpu/drm/amd/dal/include/overlay_interface.h -new file mode 100644 -index 0000000..c33bd73 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/overlay_interface.h -@@ -0,0 +1,137 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_OVERLAY_INTERFACE_H__ -+#define __DAL_OVERLAY_INTERFACE_H__ -+ -+#include "include/overlay_types.h" -+#include "include/display_service_types.h" -+ -+struct ds_overlay; -+struct path_mode_set; -+struct path_mode; -+struct view; -+ -+bool dal_ds_overlay_is_active( -+ struct ds_overlay *ovl, -+ uint32_t display_index); -+ -+uint32_t dal_ds_overlay_get_controller_handle( -+ struct ds_overlay *ovl, -+ uint32_t display_index); -+ -+enum ds_return dal_ds_overlay_alloc( -+ struct ds_overlay *ovl, -+ struct path_mode_set *path_mode_set, -+ uint32_t display_index, -+ struct view *view, -+ struct overlay_data *data); -+ -+enum ds_return dal_ds_overlay_validate( -+ struct ds_overlay *ovl, -+ struct path_mode_set *path_mode_set, -+ uint32_t display_index, -+ struct view *view, -+ struct overlay_data *data); -+ -+enum ds_return dal_ds_overlay_free( -+ struct ds_overlay *ovl, -+ struct path_mode_set *path_mode_set, -+ uint32_t display_index); -+ -+enum ds_return dal_ds_overlay_get_info( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum overlay_color_space *color_space, -+ enum overlay_backend_bpp *backend_bpp, -+ enum overlay_alloc_option *alloc_option, -+ enum overlay_format *surface_format); -+ -+enum ds_return dal_ds_overlay_set_otm( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ const struct path_mode *current_path_mode); -+ -+enum ds_return dal_ds_overlay_reset_otm( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ struct path_mode **saved_path_mode); -+ -+/**is in overlay theater mode*/ -+bool dal_ds_overlay_is_in_otm( -+ struct ds_overlay *ovl, -+ uint32_t display_index); -+ -+void dal_ds_overlay_set_matrix( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ const struct overlay_color_matrix *matrix); -+ -+void dal_ds_overlay_reset_matrix( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum overlay_csc_matrix_type type); -+ -+const struct overlay_color_matrix *dal_ds_overlay_get_matrix( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum overlay_csc_matrix_type type); -+ -+bool dal_ds_overlay_set_color_space( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum overlay_color_space space); -+ -+bool dal_ds_overlay_get_display_pixel_encoding( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum display_pixel_encoding *pixel_encoding); -+ -+bool dal_ds_overlay_set_display_pixel_encoding( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ enum display_pixel_encoding pixel_encoding); -+ -+bool dal_ds_overlay_reset_display_pixel_encoding( -+ struct ds_overlay *ovl, -+ uint32_t display_index); -+ -+/*After Set Overlay Theatre Mode (OTM) on a display path, -+ * saving the passed setting of Gpu scaling option for later restore*/ -+enum ds_return dal_ds_overlay_save_gpu_scaling_before_otm( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ int32_t timing_sel_before_otm); -+ -+/* After reset Overlay Theatre Mode (OTM) on a display path, -+ * returning the previous Gpu scaling option by SetOverlayTheatreMode*/ -+enum ds_return dal_ds_overlay_get_gpu_scaling_before_otm( -+ struct ds_overlay *ovl, -+ uint32_t display_index, -+ int32_t *timing_sel_before_otm); -+ -+uint32_t dal_ds_overlay_get_num_of_allowed(struct ds_overlay *ovl); -+ -+#endif /* __DAL_OVERLAY_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/overlay_types.h b/drivers/gpu/drm/amd/dal/include/overlay_types.h -new file mode 100644 -index 0000000..c001edf ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/overlay_types.h -@@ -0,0 +1,164 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_OVERLAY_TYPES_H__ -+#define __DAL_OVERLAY_TYPES_H__ -+ -+enum overlay_color_space { -+ OVERLAY_COLOR_SPACE_UNINITIALIZED, -+ OVERLAY_COLOR_SPACE_RGB, /* the first*/ -+ OVERLAY_COLOR_SPACE_BT601, -+ OVERLAY_COLOR_SPACE_BT709, /* the last*/ -+ OVERLAY_COLOR_SPACE_INVALID, -+ -+ /* flag the first and last*/ -+ OVERLAY_COLOR_SPACE_BEGIN = OVERLAY_COLOR_SPACE_RGB, -+ OVERLAY_COLOR_SPACE_END = OVERLAY_COLOR_SPACE_BT709, -+}; -+ -+enum overlay_backend_bpp { -+ OVERLAY_BACKENDBPP_UNINITIALIZED, -+ -+ OVERLAY_BACKEND_BPP_32_FULL_BANDWIDTH,/* the first*/ -+ OVERLAY_BACKEND_BPP_16_FULL_BANDWIDTH, -+ OVERLAY_BACKEND_BPP_32_HALF_BANDWIDTH,/* the last*/ -+ -+ OVERLAY_BACKEND_BPP_INVALID, -+ -+ /* flag the first and last*/ -+ OVERLAY_BACKEND_BPP_BEGIN = OVERLAY_BACKEND_BPP_32_FULL_BANDWIDTH, -+ OVERLAY_BACKEND_BPP_END = OVERLAY_BACKEND_BPP_32_HALF_BANDWIDTH, -+}; -+ -+enum overlay_alloc_option { -+ OVERLAY_ALLOC_OPTION_UNINITIALIZED, -+ -+ OVERLAY_ALLOC_OPTION_APPLY_OVERLAY_CSC, /* the first*/ -+ OVERLAY_ALLOC_OPTION_APPLY_DESKTOP_CSC, /* the last*/ -+ -+ OVERLAY_ALLOC_OPTION_INVALID, -+ -+ /* flag the first and last*/ -+ OVERLAY_ALLOC_OPTION_BEGIN = OVERLAY_ALLOC_OPTION_APPLY_OVERLAY_CSC, -+ OVERLAY_ALLOC_OPTION_END = OVERLAY_ALLOC_OPTION_APPLY_DESKTOP_CSC, -+}; -+ -+enum overlay_format { -+ OVERLAY_FORMAT_UNINITIALIZED, -+ OVERLAY_FORMAT_YUY2, -+ OVERLAY_FORMAT_UYVY, -+ OVERLAY_FORMAT_RGB565, -+ OVERLAY_FORMAT_RGB555, -+ OVERLAY_FORMAT_RGB32, -+ OVERLAY_FORMAT_YUV444, -+ OVERLAY_FORMAT_RGB32_2101010, -+ -+ OVERLAY_FORMAT_INVALID, -+ -+ /* flag the first and last*/ -+ OVERLAY_FORMAT_BEGIN = OVERLAY_FORMAT_YUY2, -+ OVERLAY_FORMAT_END = OVERLAY_FORMAT_RGB32_2101010, -+}; -+ -+enum display_pixel_encoding { -+ DISPLAY_PIXEL_ENCODING_UNDEFINED = 0, -+ DISPLAY_PIXEL_ENCODING_RGB, -+ DISPLAY_PIXEL_ENCODING_YCBCR422, -+ DISPLAY_PIXEL_ENCODING_YCBCR444 -+}; -+ -+union overlay_data_status { -+ uint32_t u32all; -+ struct { -+ uint32_t COLOR_SPACE_SET:1; -+ uint32_t BACKEND_BPP:1; -+ uint32_t ALLOC_OPTION:1; -+ uint32_t SURFACE_FORMAT:1; -+ uint32_t PIXEL_ENCODING:1; -+ uint32_t reserved:27; -+ -+ } bits; -+}; -+ -+struct overlay_data { -+ enum overlay_color_space color_space; -+ enum overlay_backend_bpp backend_bpp; -+ enum overlay_alloc_option alloc_option; -+ enum overlay_format surface_format; -+}; -+ -+enum overlay_csc_matrix_type { -+ OVERLAY_CSC_MATRIX_NOTDEFINED = 0, -+ OVERLAY_CSC_MATRIX_BT709, -+ OVERLAY_CSC_MATRIX_BT601, -+ OVERLAY_CSC_MATRIX_SMPTE240, -+ OVERLAY_CSC_MATRIX_SRGB, -+}; -+ -+#define DEFAULT_APP_MATRIX_DIVIDER 10000 -+#define MAX_OVL_MATRIX_COUNTS 2 -+#define OVL_BT709 0 -+#define OVL_BT601 1 -+ -+#define OVL_MATRIX_ITEM 9 -+#define OVL_MATRIX_OFFSET_ITEM 3 -+ -+struct overlay_color_matrix { -+ enum overlay_csc_matrix_type csc_matrix; -+/*3*3 Gamut Matrix (value is the real value * M_GAMUT_PRECISION_MULTIPLIER)*/ -+ int32_t matrix_settings[OVL_MATRIX_ITEM]; -+ int32_t offsets[OVL_MATRIX_OFFSET_ITEM]; -+}; -+ -+enum setup_adjustment_ovl_value_type { -+ SETUP_ADJUSTMENT_MIN, -+ SETUP_ADJUSTMENT_MAX, -+ SETUP_ADJUSTMENT_DEF, -+ SETUP_ADJUSTMENT_CURRENT, -+ SETUP_ADJUSTMENT_BUNDLE_MIN, -+ SETUP_ADJUSTMENT_BUNDLE_MAX, -+ SETUP_ADJUSTMENT_BUNDLE_DEF, -+ SETUP_ADJUSTMENT_BUNDLE_CURRENT -+}; -+ -+struct overlay_parameter { -+ union { -+ uint32_t u32all; -+ struct { -+ uint32_t VALID_OVL_COLOR_SPACE:1; -+ uint32_t VALID_VALUE_TYPE:1; -+ uint32_t VALID_OVL_SURFACE_FORMAT:1; -+ uint32_t CONFIG_IS_CHANGED:1; -+ uint32_t reserved:28; -+ -+ } bits; -+ }; -+ /*currently colorSpace here packed, continue this list*/ -+ enum overlay_color_space color_space; -+ enum setup_adjustment_ovl_value_type value_type; -+ enum overlay_format surface_format; -+}; -+ -+#endif /* OVERLAY_TYPES_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/include/path_mode_set_interface.h b/drivers/gpu/drm/amd/dal/include/path_mode_set_interface.h -new file mode 100644 -index 0000000..a277010 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/path_mode_set_interface.h -@@ -0,0 +1,107 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_PATH_MODE_SET_INTERFACE_H__ -+#define __DAL_PATH_MODE_SET_INTERFACE_H__ -+ -+/* Set of path modes */ -+struct path_mode_set { -+ union control_flags { -+ struct { -+ uint32_t KEEP_DISPLAY_POWERED_OFF:1; -+ uint32_t UNBLANCK_SOURCE_AFTER_SETMODE:1; -+ uint32_t NODE_FAULT_UNDERSCAN:1; -+ } bits; -+ -+ uint32_t all; -+ } control_flags; -+ -+ struct path_mode path_mode_set[MAX_COFUNC_PATH]; -+ uint32_t count; -+}; -+ -+/* Create path mode set */ -+struct path_mode_set *dal_pms_create(void); -+ -+/* Deallocate path mode set */ -+void dal_pms_destroy( -+ struct path_mode_set **pms); -+ -+/* Create a copy of given path mode set */ -+struct path_mode_set *dal_pms_copy( -+ const struct path_mode_set *copy); -+ -+/* Constructor for path mode set */ -+bool dal_pms_construct( -+ struct path_mode_set *set); -+ -+/* Add a path mode into the set */ -+bool dal_pms_add_path_mode( -+ struct path_mode_set *set, -+ const struct path_mode *path_mode); -+ -+/* Get number of path modes in the set */ -+uint32_t dal_pms_get_path_mode_num( -+ const struct path_mode_set *set); -+ -+/* Return the path mode at the index */ -+const struct path_mode *dal_pms_get_path_mode_at_index( -+ const struct path_mode_set *set, -+ uint32_t index); -+ -+/* Return the path mode for the given display index */ -+const struct path_mode *dal_pms_get_path_mode_for_display_index( -+ const struct path_mode_set *set, -+ uint32_t index); -+ -+/* Remove the path mode at index */ -+bool dal_pms_remove_path_mode_at_index( -+ struct path_mode_set *set, -+ uint32_t index); -+ -+/* Remove the given path mode if it is found in the set */ -+bool dal_pms_remove_path_mode( -+ struct path_mode_set *set, -+ struct path_mode *mode); -+ -+/* Add control flag to keep display powered off */ -+void dal_pms_keep_display_powered_off( -+ struct path_mode_set *set, -+ bool keep); -+ -+/* Return control flag if display needs to be kept powered off */ -+bool dal_pms_is_display_power_off_required( -+ const struct path_mode_set *set); -+ -+/* Add control flag to not use default underscan*/ -+void dal_pms_fallback_remove_default_underscan( -+ struct path_mode_set *set, -+ bool lean); -+ -+/* Return control flag if default underscan is not used */ -+bool dal_pms_is_fallback_no_default_underscan_enabled( -+ struct path_mode_set *set); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/plane_types.h b/drivers/gpu/drm/amd/dal/include/plane_types.h -new file mode 100644 -index 0000000..a2a8939 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/plane_types.h -@@ -0,0 +1,309 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_PLANE_TYPES_H__ -+#define __DAL_PLANE_TYPES_H__ -+ -+#include "scaler_types.h" -+ -+enum display_flip_mode { -+ DISPLAY_FLIP_MODE_VERTICAL = 0, -+ DISPLAY_FLIP_MODE_HORIZONTAL -+}; -+ -+/*rect or view */ -+struct rect_position { -+ uint32_t x; -+ uint32_t y; -+}; -+ -+union plane_config_change_flags { -+ struct { -+ uint32_t MIRROR_FLAGS:1; -+ uint32_t BLEND_FLAGS:1; -+ uint32_t COLORIMETRY:1; -+ uint32_t SCALING_RECTS:1; -+ -+ uint32_t SCALING_QUALITY:1; -+ uint32_t VIDEO_SCAN_FORMAT:1; -+ uint32_t STEREO_FORMAT:1; -+ uint32_t PLANE_SIZE:1; -+ -+ uint32_t TITLING_INFO:1; -+ uint32_t FORMAT:1; -+ uint32_t ROTATION:1; -+ -+ uint32_t RESERVED:21; -+ } bits; -+ uint32_t value; -+}; -+ -+ -+enum array_mode { -+ ARRAY_MODE_LINEAR_GENERAL = 0x00000000, -+ ARRAY_MODE_LINEAR_ALIGNED = 0x00000001, -+ ARRAY_MODE_1D_TILED_THIN1 = 0x00000002, -+ ARRAY_MODE_1D_TILED_THICK = 0x00000003, -+ ARRAY_MODE_2D_TILED_THIN1 = 0x00000004, -+ ARRAY_MODE_PRT_TILED_THIN1 = 0x00000005, -+ ARRAY_MODE_PRT_2D_TILED_THIN1 = 0x00000006, -+ ARRAY_MODE_2D_TILED_THICK = 0x00000007, -+ ARRAY_MODE_2D_TILED_X_THICK = 0x00000008, -+ ARRAY_MODE_PRT_TILED_THICK = 0x00000009, -+ ARRAY_MODE_PRT_2D_TILED_THICK = 0x0000000a, -+ ARRAY_MODE_PRT_3D_TILED_THIN1 = 0x0000000b, -+ ARRAY_MODE_3D_TILED_THIN1 = 0x0000000c, -+ ARRAY_MODE_3D_TILED_THICK = 0x0000000d, -+ ARRAY_MODE_3D_TILED_X_THICK = 0x0000000e, -+ ARRAY_MODE_PRT_3D_TILED_THICK = 0x0000000f -+}; -+ -+/* single enum for grph and video (both luma and chroma) */ -+enum tile_split { -+ TILE_SPLIT_64B = 0x00000000, -+ TILE_SPLIT_128B = 0x00000001, -+ TILE_SPLIT_256B = 0x00000002, -+ TILE_SPLIT_512B = 0x00000003, -+ TILE_SPLIT_1KB = 0x00000004, -+ TILE_SPLIT_2KB = 0x00000005, -+ TILE_SPLIT_4KB = 0x00000006 -+}; -+ -+/* single enum for grph and video (both luma and chroma)*/ -+enum macro_tile_aspect { -+ MACRO_TILE_ASPECT_1 = 0x00000000, -+ MACRO_TILE_ASPECT_2 = 0x00000001, -+ MACRO_TILE_ASPECT_4 = 0x00000002, -+ MACRO_TILE_ASPECT_8 = 0x00000003 -+}; -+ -+enum video_array_mode { -+ VIDEO_ARRAY_MODE_LINEAR_GENERAL = 0x00000000, -+ VIDEO_ARRAY_MODE_LINEAR_ALIGNED = 0x00000001, -+ VIDEO_ARRAY_MODE_1D_TILED_THIN1 = 0x00000002, -+ VIDEO_ARRAY_MODE_1D_TILED_THICK = 0x00000003, -+ VIDEO_ARRAY_MODE_2D_TILED_THIN1 = 0x00000004, -+ VIDEO_ARRAY_MODE_2D_TILED_THICK = 0x00000007, -+ VIDEO_ARRAY_MODE_3D_TILED_THIN1 = 0x0000000c, -+ VIDEO_ARRAY_MODE_3D_TILED_THICK = 0x0000000d -+}; -+ -+/* single enum for grph and video (both luma and chroma)*/ -+enum micro_tile_mode { -+ MICRO_TILE_MODE_DISPLAY = 0x00000000, -+ MICRO_TILE_MODE_THIN = 0x00000001, -+ MICRO_TILE_MODE_DEPTH = 0x00000002, -+ MICRO_TILE_MODE_ROTATED = 0x00000003 -+}; -+ -+/* KK: taken from addrlib*/ -+enum addr_pipe_config { -+ ADDR_PIPE_CONFIG_INVALID = 0, -+ /* 2 pipes */ -+ ADDR_PIPE_CONFIG_P2 = 1, -+ /* 4 pipes */ -+ ADDR_PIPE_CONFIG_P4_8x16 = 5, -+ ADDR_PIPE_CONFIG_P4_16x16 = 6, -+ ADDR_PIPE_CONFIG_P4_16x32 = 7, -+ ADDR_PIPE_CONFIG_P4_32x32 = 8, -+ /* 8 pipes*/ -+ ADDR_PIPE_CONFIG_P8_16x16_8x16 = 9, -+ ADDR_PIPE_CONFIG_P8_16x32_8x16 = 10, -+ ADDR_PIPE_CONFIG_P8_32x32_8x16 = 11, -+ ADDR_PIPE_CONFIG_P8_16x32_16x16 = 12, -+ ADDR_PIPE_CONFIG_P8_32x32_16x16 = 13, -+ ADDR_PIPE_CONFIG_P8_32x32_16x32 = 14, -+ ADDR_PIPE_CONFIG_P8_32x64_32x32 = 15, -+ /* 16 pipes */ -+ ADDR_PIPE_CONFIG_P16_32x32_8x16 = 17, -+ ADDR_PIPE_CONFIG_P16_32x32_16x16 = 18, -+ ADDR_PIPE_CONFIG_MAX = 19 -+}; -+ -+struct plane_surface_config { -+ uint32_t layer_index; -+ /*used in set operation*/ -+ bool enabled; -+ -+ union plane_size plane_size; -+ union plane_tiling_info tiling_info; -+ /* surface pixel format from display manager or fb*/ -+ enum surface_pixel_format format; -+ /*pixel format for DAL internal hardware programming*/ -+ enum pixel_format dal_pixel_format; -+ enum dc_rotation_angle rotation; -+}; -+ -+/* For Caps, maximum taps for each axis is returned*/ -+/* For Set, the requested taps will be used*/ -+struct plane_src_scaling_quality { -+ /* INVALID_TAP_VALUE indicates DAL -+ * decides considering aspect ratio -+ * & bandwidth -+ */ -+ uint32_t h_taps; -+ /* INVALID_TAP_VALUE indicates DAL -+ * decides considering aspect ratio -+ * & bandwidth -+ */ -+ uint32_t v_taps; -+ uint32_t h_taps_c; -+ uint32_t v_taps_c; -+}; -+ -+struct plane_mirror_flags { -+ union { -+ struct { -+ uint32_t vertical_mirror:1; -+ uint32_t horizontal_mirror:1; -+ uint32_t reserved:30; -+ } bits; -+ uint32_t value; -+ }; -+}; -+ -+/* Note some combinations are mutually exclusive*/ -+struct plane_blend_flags { -+ union { -+ struct { -+ uint32_t PER_PIXEL_ALPHA_BLEND:1; -+ uint32_t GLOBAL_ALPHA_BLEND:1; -+ uint32_t RESERVED:30; -+ } bits; -+ uint32_t value; -+ }; -+}; -+ -+enum plane_vid_scan_fmt { -+ PLANE_VID_SCAN_FMT_PROGRESSIVE = 0, -+ PLANE_VID_SCAN_FMT_INTERLACED_TOP_FIRST = 1, -+ PLANE_VID_SCAN_FMT_INTERLACED_BOTTOM_FIRST = 2 -+}; -+ -+ -+struct plane_attributes { -+ /*mirror options */ -+ struct plane_mirror_flags mirror_flags; -+ /*blending options*/ -+ struct plane_blend_flags blend_flags; -+ /*color space */ -+ struct plane_colorimetry colorimetry; -+ -+ struct rect src_rect; -+ struct rect dst_rect; -+ struct rect clip_rect; -+ struct scaling_taps scaling_quality; -+ /*progressive, interlaced*/ -+ enum plane_vid_scan_fmt video_scan_format; -+ enum plane_stereo_format stereo_format; -+}; -+ -+union address_flags { -+ struct { -+ /* always 1 for primary surface, used in get operation*/ -+ uint32_t ENABLE:1; -+ /* set 1 if returned address is from cache*/ -+ uint32_t ADDR_IS_PENDING:1; -+ /* currentFrameIsRightEye for stereo only*/ -+ uint32_t CURRENT_FRAME_IS_RIGHT_EYE:1; -+ uint32_t RESERVED:29; -+ } bits; -+ -+ uint32_t value; -+}; -+ -+struct address_info { -+ /* primary surface will be DAL_LAYER_INDEX_PRIMARY*/ -+ int32_t layer_index; -+ /*the flags to describe the address info*/ -+ union address_flags flags; -+ struct dc_plane_address address; -+}; -+ -+union plane_valid_mask { -+ struct { -+ /* set 1 if config is valid in DalPlane*/ -+ uint32_t SURFACE_CONFIG_IS_VALID:1; -+ /* set 1 if plane_attributes is valid in plane*/ -+ uint32_t PLANE_ATTRIBUTE_IS_VALID:1; -+ uint32_t RESERVED:30; -+ } bits; -+ uint32_t value; -+}; -+ -+union flip_valid_mask { -+ struct { -+ /* set 1 if flip_immediate is -+ * valid in plane_addr_flip_info -+ */ -+ uint32_t FLIP_VALID:1; -+ /* set 1 if addressInfo is -+ * valid in plane_addr_flip_info -+ */ -+ uint32_t ADDRESS_VALID:1; -+ uint32_t RESERVED:30; -+ } bits; -+ uint32_t value; -+}; -+ -+struct plane_addr_flip_info { -+ uint32_t display_index; -+ struct address_info address_info; -+ /* flip on vsync if false . When -+ * flip_immediate is true then -+ * update_duration is unused -+ */ -+ bool flip_immediate; -+ /* 48 Hz support for single and -+ * multi plane cases ,set 0 when -+ * it is unused. -+ */ -+ uint32_t update_duration; -+ union flip_valid_mask mask; -+}; -+ -+struct plane_config { -+ union plane_valid_mask mask; -+ uint32_t display_index; -+ struct plane_surface_config config; -+ struct plane_attributes attributes; -+ struct mp_scaling_data mp_scaling_data; -+ union plane_config_change_flags plane_change_flags; -+}; -+ -+struct plane_validate_config { -+ uint32_t display_index; -+ bool flip_immediate; -+ struct plane_surface_config config; -+ struct plane_attributes attributes; -+}; -+ -+struct view_port { -+ uint32_t display_index; -+ struct rect view_port_rect; -+}; -+ -+#endif -+ -diff --git a/drivers/gpu/drm/amd/dal/include/scaler_types.h b/drivers/gpu/drm/amd/dal/include/scaler_types.h -new file mode 100644 -index 0000000..db52dbc ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/scaler_types.h -@@ -0,0 +1,196 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_SCALER_TYPES_H__ -+#define __DAL_SCALER_TYPES_H__ -+ -+#include "signal_types.h" -+#include "fixed31_32.h" -+#include "dc_types.h" -+ -+enum pixel_type { -+ PIXEL_TYPE_30BPP = 1, -+ PIXEL_TYPE_20BPP -+}; -+ -+/*overscan or window*/ -+struct overscan_info { -+ uint32_t left; -+ uint32_t right; -+ uint32_t top; -+ uint32_t bottom; -+}; -+ -+struct mp_scaling_data { -+ struct rect viewport; -+ struct view dst_res; -+ struct overscan_info overscan; -+ struct scaling_taps taps; -+ struct scaling_ratios ratios; -+}; -+ -+struct scaler_validation_params { -+ uint32_t INTERLACED:1; -+ uint32_t CHROMA_SUB_SAMPLING:1; -+ -+ uint32_t line_buffer_size; -+ uint32_t display_clock; /* in KHz */ -+ uint32_t actual_pixel_clock; /* in KHz */ -+ struct view source_view; -+ struct view dest_view; -+ enum signal_type signal_type; -+ -+ struct scaling_taps taps_requested; -+ enum pixel_format pixel_format; -+ enum dc_rotation_angle rotation; -+}; -+ -+struct adjustment_factor { -+ int32_t adjust; /* Actual adjustment value * lDivider */ -+ uint32_t divider; -+}; -+ -+struct sharpness_adjustment { -+ int32_t sharpness; -+ bool enable_sharpening; -+}; -+ -+enum scaling_options { -+ SCALING_BYPASS = 0, -+ SCALING_ENABLE -+}; -+ -+/* same as Hw register */ -+enum filter_type { -+ FILTER_TYPE_V_LOW_PASS = 0x0, -+ FILTER_TYPE_V_HIGH_PASS = 0x1, -+ FILTER_TYPE_H_LUMA = 0x2, -+ FILTER_TYPE_H_CHROMA = 0x3 -+}; -+ -+/* Validation Result enumeration */ -+enum scaler_validation_code { -+ SCALER_VALIDATION_OK = 0, -+ SCALER_VALIDATION_INVALID_INPUT_PARAMETERS, -+ SCALER_VALIDATION_SCALING_RATIO_NOT_SUPPORTED, -+ SCALER_VALIDATION_SOURCE_VIEW_WIDTH_EXCEEDING_LIMIT, -+ SCALER_VALIDATION_DISPLAY_CLOCK_BELOW_PIXEL_CLOCK, -+ SCALER_VALIDATION_FAILURE_PREDEFINED_TAPS_NUMBER -+}; -+ -+ -+#define FILTER_TYPE_MASK 0x0000000FL -+#define TWO_TAPS 2 -+ -+struct init_int_and_frac { -+ uint32_t integer; -+ uint32_t fraction; -+}; -+ -+struct scl_ratios_inits { -+ uint32_t bottom_enable; -+ uint32_t h_int_scale_ratio; -+ uint32_t v_int_scale_ratio; -+ struct init_int_and_frac h_init; -+ struct init_int_and_frac v_init; -+ struct init_int_and_frac v_init_bottom; -+}; -+ -+union scaler_flags { -+ uint32_t raw; -+ struct { -+ uint32_t INTERLACED:1; -+ uint32_t DOUBLE_SCAN_MODE:1; -+ /* this one is legacy flag only used in DCE80 */ -+ uint32_t RGB_COLOR_SPACE:1; -+ uint32_t PIPE_LOCK_REQ:1; -+ /* 4 */ -+ uint32_t WIDE_DISPLAY:1; -+ uint32_t OTHER_PIPE:1; -+ uint32_t SHOULD_PROGRAM_VIEWPORT:1; -+ uint32_t SHOULD_UNLOCK:1; -+ /* 8 */ -+ uint32_t SHOULD_PROGRAM_ALPHA:1; -+ uint32_t SHOW_COLOURED_BORDER:1; -+ -+ uint32_t RESERVED:22; -+ } bits; -+}; -+ -+struct scaler_data { -+ struct view src_res; -+ struct view dst_res; -+ struct overscan_info overscan; -+ struct scaling_taps taps; -+ struct adjustment_factor scale_ratio_hp_factor; -+ struct adjustment_factor scale_ratio_lp_factor; -+ enum pixel_type pixel_type; /*legacy*/ -+ struct sharpness_adjustment sharp_gain; -+ -+ union scaler_flags flags; -+ int32_t h_sharpness; -+ int32_t v_sharpness; -+ -+ struct view src_res_wide_display; -+ struct view dst_res_wide_display; -+ -+ /* it is here because of the HW bug in NI (UBTS #269539) -+ causes glitches in this VBI signal. It shouldn't change after -+ initialization, kind of a const */ -+ const struct hw_crtc_timing *hw_crtc_timing; -+ -+ struct rect viewport; -+ -+ enum pixel_format dal_pixel_format;/*plane concept*/ -+ /*stereoformat TODO*/ -+ /*hwtotation TODO*/ -+ -+ const struct scaling_ratios *ratios; -+}; -+ -+enum bypass_type { -+ /* 00 - 00 - Manual Centering, Manual Replication */ -+ BYPASS_TYPE_MANUAL = 0, -+ /* 01 - 01 - Auto-Centering, No Replication */ -+ BYPASS_TYPE_AUTO_CENTER = 1, -+ /* 02 - 10 - Auto-Centering, Auto-Replication */ -+ BYPASS_TYPE_AUTO_REPLICATION = 3 -+}; -+ -+struct replication_factor { -+ uint32_t h_manual; -+ uint32_t v_manual; -+}; -+ -+enum ram_filter_type { -+ FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */ -+ FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */ -+ FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */ -+ FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */ -+ FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */ -+ FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */ -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/set_mode_params_interface.h b/drivers/gpu/drm/amd/dal/include/set_mode_params_interface.h -new file mode 100644 -index 0000000..e4f52c4 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/set_mode_params_interface.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 -+ * -+ */ -+ -+#ifndef __DAL_SET_MODE_PARAMS_INTERFACE_H__ -+#define __DAL_SET_MODE_PARAMS_INTERFACE_H__ -+ -+struct set_mode_params; -+ -+struct set_mode_params_init_data { -+ struct hw_sequencer *hws; -+ struct dal_context *ctx; -+ struct topology_mgr *tm; -+}; -+ -+struct view_stereo_3d_support dal_set_mode_params_get_stereo_3d_support( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ enum dc_timing_3d_format); -+ -+bool dal_set_mode_params_update_view_on_path( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ const struct view *vw); -+ -+bool dal_set_mode_params_update_mode_timing_on_path( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ const struct dc_mode_timing *mode_timing, -+ enum view_3d_format format); -+ -+bool dal_set_mode_params_update_scaling_on_path( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ enum scaling_transformation st); -+ -+bool dal_set_mode_params_update_pixel_format_on_path( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ enum pixel_format pf); -+ -+bool dal_set_mode_params_update_tiling_mode_on_path( -+ struct set_mode_params *smp, -+ uint32_t display_index, -+ enum tiling_mode tm); -+ -+bool dal_set_mode_params_is_path_mode_set_supported( -+ struct set_mode_params *smp); -+ -+bool dal_set_mode_params_is_path_mode_set_guaranteed( -+ struct set_mode_params *smp); -+ -+bool dal_set_mode_params_report_single_selected_timing( -+ struct set_mode_params *smp, -+ uint32_t display_index); -+ -+bool dal_set_mode_params_report_ce_mode_only( -+ struct set_mode_params *smp, -+ uint32_t display_index); -+ -+struct set_mode_params *dal_set_mode_params_create( -+ struct set_mode_params_init_data *init_data); -+ -+bool dal_set_mode_params_init_with_topology( -+ struct set_mode_params *smp, -+ const uint32_t display_indicies[], -+ uint32_t idx_num); -+ -+bool dal_set_mode_params_is_multiple_pixel_encoding_supported( -+ struct set_mode_params *smp, -+ uint32_t display_index); -+ -+enum dc_pixel_encoding dal_set_mode_params_get_default_pixel_format_preference( -+ struct set_mode_params *smp, -+ unsigned int display_index); -+ -+void dal_set_mode_params_destroy( -+ struct set_mode_params **set_mode_params); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/set_mode_types.h b/drivers/gpu/drm/amd/dal/include/set_mode_types.h -new file mode 100644 -index 0000000..3647815 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/set_mode_types.h -@@ -0,0 +1,285 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_SET_MODE_TYPES_H__ -+#define __DAL_SET_MODE_TYPES_H__ -+ -+#include "adjustment_types.h" -+#include "hw_adjustment_types.h" -+#include "include/plane_types.h" -+#include "dc_types.h" -+ -+/* Forward declaration */ -+struct dc_mode_timing; -+struct display_path; -+ -+/* State of stereo 3D for workstation */ -+enum ws_stereo_state { -+ WS_STEREO_STATE_INACTIVE = 0, -+ WS_STEREO_STATE_ACTIVE, -+ WS_STEREO_STATE_ACTIVE_MASTER -+}; -+ -+/* GTC group number */ -+enum gtc_group { -+ GTC_GROUP_DISABLED, -+ GTC_GROUP_1, -+ GTC_GROUP_2, -+ GTC_GROUP_3, -+ GTC_GROUP_4, -+ GTC_GROUP_5, -+ GTC_GROUP_6, -+ GTC_GROUP_MAX -+}; -+ -+/* Adjustment action*/ -+enum adjustment_action { -+ ADJUSTMENT_ACTION_UNDEFINED = 0, -+ ADJUSTMENT_ACTION_VALIDATE, -+ ADJUSTMENT_ACTION_SET_ADJUSTMENT -+}; -+ -+/* Type of adjustment parameters*/ -+enum adjustment_par_type { -+ ADJUSTMENT_PAR_TYPE_NONE = 0, -+ ADJUSTMENT_PAR_TYPE_TIMING, -+ ADJUSTMENT_PAR_TYPE_MODE -+}; -+ -+/* Method of validation */ -+enum validation_method { -+ VALIDATION_METHOD_STATIC = 0, -+ VALIDATION_METHOD_DYNAMIC -+}; -+ -+/* 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 -+}; -+ -+/* Active format */ -+enum active_format_info { -+ ACTIVE_FORMAT_NO_DATA = 0, -+ ACTIVE_FORMAT_VALID = 1 -+}; -+/* Bar info */ -+enum bar_info { -+ BAR_INFO_NOT_VALID = 0, -+ BAR_INFO_VERTICAL_VALID = 1, -+ BAR_INFO_HORIZONTAL_VALID = 2, -+ BAR_INFO_BOTH_VALID = 3 -+}; -+ -+/* Picture scaling */ -+enum picture_scaling { -+ PICTURE_SCALING_UNIFORM = 0, -+ PICTURE_SCALING_HORIZONTAL = 1, -+ PICTURE_SCALING_VERTICAL = 2, -+ PICTURE_SCALING_BOTH = 3 -+}; -+ -+/* Colorimetry */ -+enum colorimetry { -+ COLORIMETRY_NO_DATA = 0, -+ COLORIMETRY_ITU601 = 1, -+ COLORIMETRY_ITU709 = 2, -+ COLORIMETRY_EXTENDED = 3 -+}; -+ -+/* ColorimetryEx */ -+enum colorimetry_ex { -+ COLORIMETRY_EX_XVYCC601 = 0, -+ COLORIMETRY_EX_XVYCC709 = 1, -+ COLORIMETRY_EX_SYCC601 = 2, -+ COLORIMETRY_EX_ADOBEYCC601 = 3, -+ COLORIMETRY_EX_ADOBERGB = 4, -+ COLORIMETRY_EX_RESERVED5 = 5, -+ COLORIMETRY_EX_RESERVED6 = 6, -+ COLORIMETRY_EX_RESERVED7 = 7 -+}; -+ -+/* 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 -+}; -+ -+/* 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 -+}; -+ -+/* Rotation capability */ -+struct rotation_capability { -+ bool ROTATION_ANGLE_0_CAP:1; -+ bool ROTATION_ANGLE_90_CAP:1; -+ bool ROTATION_ANGLE_180_CAP:1; -+ bool ROTATION_ANGLE_270_CAP:1; -+}; -+ -+/* Underscan position and size */ -+struct ds_underscan_desc { -+ uint32_t x; -+ uint32_t y; -+ uint32_t width; -+ uint32_t height; -+}; -+ -+/* View, timing and other mode related information */ -+struct path_mode { -+ struct view view; -+ struct rect_position view_position; -+ enum view_3d_format view_3d_format; -+ const struct dc_mode_timing *mode_timing; -+ enum scaling_transformation scaling; -+ enum pixel_format pixel_format; -+ uint32_t display_path_index; -+ enum tiling_mode tiling_mode; -+ enum dc_rotation_angle rotation_angle; -+ bool is_tiling_rotated; -+ struct rotation_capability rotation_capability; -+}; -+ -+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; -+}; -+ -+ -+/* Adjustment parameter */ -+struct adjustment_parameters { -+ enum adjustment_par_type type; -+ struct { -+ enum adjustment_id ajd_id; -+ enum hw_adjustment_id adj_id_hw; -+ } timings; -+}; -+ -+/* Parameters for adjustments*/ -+struct adjustment_params { -+ enum adjustment_action action; -+ struct adjustment_parameters params; -+ const struct display_path *affected_path; -+}; -+ -+#pragma pack(pop) -+ -+#endif /* __DAL_SET_MODE_TYPES_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/signal_types.h b/drivers/gpu/drm/amd/dal/include/signal_types.h -new file mode 100644 -index 0000000..e95e821 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/signal_types.h -@@ -0,0 +1,58 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __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_COUNT = 9, -+ SIGNAL_TYPE_ALL = (1 << SIGNAL_TYPE_COUNT) - 1 -+}; -+ -+/* help functions for signal types manipulation */ -+bool dc_is_hdmi_signal(enum signal_type signal); -+bool dc_is_dp_sst_signal(enum signal_type signal); -+bool dc_is_dp_signal(enum signal_type signal); -+bool dc_is_dp_external_signal(enum signal_type signal); -+bool dc_is_analog_signal(enum signal_type signal); -+bool dc_is_embedded_signal(enum signal_type signal); -+bool dc_is_dvi_signal(enum signal_type signal); -+bool dc_is_dvi_single_link_signal(enum signal_type signal); -+bool dc_is_dual_link_signal(enum signal_type signal); -+bool dc_is_audio_capable_signal(enum signal_type signal); -+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal); -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h b/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h -new file mode 100644 -index 0000000..0d3e67c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h -@@ -0,0 +1,16 @@ -+/* -+ * stream_encoder_types.h -+ * -+ */ -+#include "encoder_interface.h" -+ -+#ifndef STREAM_ENCODER_TYPES_H_ -+#define STREAM_ENCODER_TYPES_H_ -+ -+struct stream_encoder { -+ enum engine_id id; -+ struct adapter_service *adapter_service; -+ struct dc_context *ctx; -+}; -+ -+#endif /* STREAM_ENCODER_TYPES_H_ */ -diff --git a/drivers/gpu/drm/amd/dal/include/timing_generator_types.h b/drivers/gpu/drm/amd/dal/include/timing_generator_types.h -new file mode 100644 -index 0000000..9c4d92d ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/timing_generator_types.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_TIMING_GENERATOR_TYPES_H__ -+#define __DAL_TIMING_GENERATOR_TYPES_H__ -+ -+#include "include/grph_csc_types.h" -+ -+/** -+ * These parameters are required as input when doing blanking/Unblanking -+*/ -+struct crtc_black_color { -+ uint32_t black_color_r_cr; -+ uint32_t black_color_g_y; -+ uint32_t black_color_b_cb; -+}; -+ -+/* Contains CRTC vertical/horizontal pixel counters */ -+struct crtc_position { -+ uint32_t vertical_count; -+ uint32_t horizontal_count; -+ uint32_t nominal_vcount; -+}; -+ -+/* -+ * Parameters to enable/disable stereo 3D mode on CRTC -+ * - rightEyePolarity: if true, '0' means left eye image and '1' means right -+ * eye image. -+ * if false, '0' means right eye image and '1' means left eye image -+ * - framePacked: true when HDMI 1.4a FramePacking 3D format -+ * enabled/disabled -+ */ -+struct crtc_stereo_parameters { -+ uint8_t PROGRAM_STEREO:1; -+ uint8_t PROGRAM_POLARITY:1; -+ uint8_t RIGHT_EYE_POLARITY:1; -+ uint8_t FRAME_PACKED:1; -+}; -+ -+struct crtc_stereo_status { -+ uint8_t ENABLED:1; -+ uint8_t CURRENT_FRAME_IS_RIGHT_EYE:1; -+ uint8_t CURRENT_FRAME_IS_ODD_FIELD:1; -+ uint8_t FRAME_PACKED:1; -+ uint8_t PENDING_RESET:1; -+}; -+ -+enum dcp_gsl_purpose { -+ DCP_GSL_PURPOSE_SURFACE_FLIP = 0, -+ DCP_GSL_PURPOSE_STEREO3D_PHASE, -+ DCP_GSL_PURPOSE_UNDEFINED -+}; -+ -+struct dcp_gsl_params { -+ enum sync_source gsl_group; -+ enum dcp_gsl_purpose gsl_purpose; -+ bool timing_server; -+ bool overlay_present; -+ bool gsl_paused; -+}; -+ -+struct vbi_end_signal_setup { -+ uint32_t minimum_interval_in_us; /* microseconds */ -+ uint32_t pixel_clock; /* in KHz */ -+ bool scaler_enabled; -+ bool interlace; -+ uint32_t src_height; -+ uint32_t overscan_top; -+ uint32_t overscan_bottom; -+ uint32_t v_total; -+ uint32_t v_addressable; -+ uint32_t h_total; -+}; -+ -+#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 -+}; -+ -+struct timing_generator { -+ uint32_t *regs; -+ struct bios_parser *bp; -+ enum controller_id controller_id; -+ struct dc_context *ctx; -+ 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; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h b/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h -new file mode 100644 -index 0000000..16e3521 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/timing_list_query_interface.h -@@ -0,0 +1,69 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 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_LIST_QUERY_INTERFACE_H__ -+#define __DAL_TIMING_LIST_QUERY_INTERFACE_H__ -+ -+/* External dependencies */ -+#include "include/dcs_interface.h" -+ -+/* Forward declarations */ -+struct dal; -+struct dal_timing_list_query; -+ -+enum timing_support_level { -+ TIMING_SUPPORT_LEVEL_UNDEFINED, -+ /* assumed to be guaranteed supported by display, -+ * usually one timing is marked as native */ -+ TIMING_SUPPORT_LEVEL_NATIVE, -+ /* user wants DAL to drive this timing as if Display supports it */ -+ TIMING_SUPPORT_LEVEL_GUARANTEED, -+ /* user wants DAL to drive this timing even if display -+ * may not support it */ -+ TIMING_SUPPORT_LEVEL_NOT_GUARANTEED -+}; -+ -+struct timing_list_query_init_data { -+ struct dal *dal; /* an instance of DAL */ -+ struct timing_service *timing_srv; -+ struct dcs *dcs; -+ uint32_t display_index; -+}; -+ -+struct dal_timing_list_query *dal_timing_list_query_create( -+ struct timing_list_query_init_data *init_data); -+ -+void dal_timing_list_query_destroy(struct dal_timing_list_query **tlsq); -+ -+/* Get count of mode timings in the list. */ -+uint32_t dal_timing_list_query_get_mode_timing_count( -+ const struct dal_timing_list_query *tlsq); -+ -+const struct dc_mode_timing *dal_timing_list_query_get_mode_timing_at_index( -+ const struct dal_timing_list_query *tlsq, -+ uint32_t index); -+ -+ -+#endif /* __DAL_TIMING_LIST_QUERY_INTERFACE_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/vector.h b/drivers/gpu/drm/amd/dal/include/vector.h -new file mode 100644 -index 0000000..8233b7c ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/vector.h -@@ -0,0 +1,150 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_VECTOR_H__ -+#define __DAL_VECTOR_H__ -+ -+struct vector { -+ uint8_t *container; -+ uint32_t struct_size; -+ uint32_t count; -+ uint32_t capacity; -+ struct dc_context *ctx; -+}; -+ -+bool dal_vector_construct( -+ struct vector *vector, -+ struct dc_context *ctx, -+ uint32_t capacity, -+ uint32_t struct_size); -+ -+struct vector *dal_vector_create( -+ struct dc_context *ctx, -+ uint32_t capacity, -+ uint32_t struct_size); -+ -+/* 'initial_value' is optional. If initial_value not supplied, -+ * each "structure" in the vector will contain zeros by default. */ -+struct vector *dal_vector_presized_create( -+ struct dc_context *ctx, -+ uint32_t size, -+ void *initial_value, -+ uint32_t struct_size); -+ -+void dal_vector_destruct( -+ struct vector *vector); -+ -+void dal_vector_destroy( -+ struct vector **vector); -+ -+uint32_t dal_vector_get_count( -+ const struct vector *vector); -+ -+/* dal_vector_insert_at -+ * reallocate container if necessary -+ * then shell items at right and insert -+ * return if the container modified -+ * do not check that index belongs to container -+ * since the function is private and index is going to be calculated -+ * either with by function or as get_count+1 */ -+bool dal_vector_insert_at( -+ struct vector *vector, -+ const void *what, -+ uint32_t position); -+ -+bool dal_vector_append( -+ struct vector *vector, -+ const void *item); -+ -+/* operator[] */ -+void *dal_vector_at_index( -+ const struct vector *vector, -+ uint32_t index); -+ -+void dal_vector_set_at_index( -+ const struct vector *vector, -+ const void *what, -+ uint32_t index); -+ -+/* create a clone (copy) of a vector */ -+struct vector *dal_vector_clone( -+ const struct vector *vector_other); -+ -+/* dal_vector_remove_at_index -+ * Shifts elements on the right from remove position to the left, -+ * removing an element at position by overwrite means*/ -+bool dal_vector_remove_at_index( -+ struct vector *vector, -+ uint32_t index); -+ -+uint32_t dal_vector_capacity(const struct vector *vector); -+ -+bool dal_vector_reserve(struct vector *vector, uint32_t capacity); -+ -+void dal_vector_clear(struct vector *vector); -+ -+/*************************************************************************** -+ * Macro definitions of TYPE-SAFE versions of vector set/get functions. -+ ***************************************************************************/ -+ -+#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \ -+ static bool vector_type##_vector_insert_at( \ -+ struct vector *vector, \ -+ type_t what, \ -+ uint32_t position) \ -+{ \ -+ return dal_vector_insert_at(vector, what, position); \ -+} -+ -+#define DAL_VECTOR_APPEND(vector_type, type_t) \ -+ static bool vector_type##_vector_append( \ -+ struct vector *vector, \ -+ type_t item) \ -+{ \ -+ return dal_vector_append(vector, item); \ -+} -+ -+/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by -+ * "checkcommit" as *return type*. -+ * For uniformity reasons "type_t" is used for all type-safe macro -+ * definitions here. */ -+#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \ -+ static type_t vector_type##_vector_at_index( \ -+ const struct vector *vector, \ -+ uint32_t index) \ -+{ \ -+ return dal_vector_at_index(vector, index); \ -+} -+ -+#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \ -+ static void vector_type##_vector_set_at_index( \ -+ const struct vector *vector, \ -+ type_t what, \ -+ uint32_t index) \ -+{ \ -+ dal_vector_set_at_index(vector, what, index); \ -+} -+ -+#endif /* __DAL_VECTOR_H__ */ -diff --git a/drivers/gpu/drm/amd/dal/include/video_csc_types.h b/drivers/gpu/drm/amd/dal/include/video_csc_types.h -new file mode 100644 -index 0000000..c229f5a ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/video_csc_types.h -@@ -0,0 +1,135 @@ -+/* -+ * Copyright 2012-15 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: AMD -+ * -+ */ -+ -+#ifndef __DAL_VIDEO_CSC_TYPES_H__ -+#define __DAL_VIDEO_CSC_TYPES_H__ -+ -+#include "video_gamma_types.h" -+ -+enum ovl_alpha_blending_mode { -+ OVL_ALPHA_PER_PIXEL_GRPH_ALPHA_MODE = 0, -+ OVL_ALPHA_PER_PIXEL_OVL_ALPHA_MODE -+}; -+ -+enum ovl_color_space { -+ OVL_COLOR_SPACE_UNKNOWN = 0, -+ OVL_COLOR_SPACE_RGB, -+ OVL_COLOR_SPACE_YUV601, -+ OVL_COLOR_SPACE_YUV709 -+}; -+ -+enum ovl_surface_format { -+ OVL_SURFACE_FORMAT_UNKNOWN = 0, -+ OVL_SURFACE_FORMAT_YUY2, -+ OVL_SURFACE_FORMAT_UYVY, -+ OVL_SURFACE_FORMAT_RGB565, -+ OVL_SURFACE_FORMAT_RGB555, -+ OVL_SURFACE_FORMAT_RGB32, -+ OVL_SURFACE_FORMAT_YUV444, -+ OVL_SURFACE_FORMAT_RGB32_2101010 -+}; -+ -+struct ovl_color_adjust_option { -+ uint32_t ALLOW_OVL_RGB_ADJUST:1; -+ uint32_t ALLOW_OVL_TEMPERATURE:1; -+ uint32_t FULL_RANGE:1; /* 0 for limited range it'is default for YUV */ -+ uint32_t OVL_MATRIX:1; -+ uint32_t RESERVED:28; -+}; -+ -+struct overlay_adjust_item { -+ int32_t adjust; /* InInteger */ -+ int32_t adjust_divider; -+}; -+ -+enum overlay_csc_adjust_type { -+ OVERLAY_CSC_ADJUST_TYPE_BYPASS = 0, -+ OVERLAY_CSC_ADJUST_TYPE_HW, /* without adjustments */ -+ OVERLAY_CSC_ADJUST_TYPE_SW /* use adjustments */ -+}; -+ -+enum overlay_gamut_adjust_type { -+ OVERLAY_GAMUT_ADJUST_TYPE_BYPASS = 0, -+ OVERLAY_GAMUT_ADJUST_TYPE_SW /* use adjustments */ -+}; -+ -+#define TEMPERATURE_MATRIX_SIZE 9 -+#define MAXTRIX_SIZE TEMPERATURE_MAXTRIX_SIZE -+#define MAXTRIX_SIZE_WITH_OFFSET 12 -+ -+/* overlay adjustment input */ -+union ovl_csc_flag { -+ uint32_t u_all; -+ struct { -+ uint32_t CONFIG_IS_CHANGED:1; -+ uint32_t RESERVED:31; -+ } bits; -+}; -+ -+struct ovl_csc_adjustment { -+ enum ovl_color_space ovl_cs; -+ struct ovl_color_adjust_option ovl_option; -+ enum dc_color_depth display_color_depth; -+ uint32_t lb_color_depth; -+ enum pixel_format desktop_surface_pixel_format; -+ enum ovl_surface_format ovl_sf; -+ /* API adjustment */ -+ struct overlay_adjust_item overlay_brightness; -+ struct overlay_adjust_item overlay_gamma; -+ struct overlay_adjust_item overlay_contrast; -+ struct overlay_adjust_item overlay_saturation; -+ struct overlay_adjust_item overlay_hue; /* unit in degree from API. */ -+ int32_t f_temperature[TEMPERATURE_MATRIX_SIZE]; -+ uint32_t temperature_divider; -+ /* OEM/Application matrix related. */ -+ int32_t matrix[MAXTRIX_SIZE_WITH_OFFSET]; -+ uint32_t matrix_divider; -+ -+ /* DCE50 parameters */ -+ struct regamma_lut regamma; -+ enum overlay_gamma_adjust adjust_gamma_type; -+ enum overlay_csc_adjust_type adjust_csc_type; -+ enum overlay_gamut_adjust_type adjust_gamut_type; -+ union ovl_csc_flag flag; -+ -+}; -+ -+enum ovl_csc_adjust_item { -+ OVERLAY_BRIGHTNESS = 0, -+ OVERLAY_GAMMA, -+ OVERLAY_CONTRAST, -+ OVERLAY_SATURATION, -+ OVERLAY_HUE, -+ OVERLAY_ALPHA, -+ OVERLAY_ALPHA_PER_PIX, -+ OVERLAY_COLOR_TEMPERATURE -+}; -+ -+struct input_csc_matrix { -+ enum color_space color_space; -+ uint16_t regval[12]; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h -new file mode 100644 -index 0000000..dc294b6 ---- /dev/null -+++ b/drivers/gpu/drm/amd/dal/include/video_gamma_types.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_VIDEO_GAMMA_TYPES_H__ -+#define __DAL_VIDEO_GAMMA_TYPES_H__ -+ -+#include "set_mode_types.h" -+ -+enum overlay_gamma_adjust { -+ OVERLAY_GAMMA_ADJUST_BYPASS, -+ OVERLAY_GAMMA_ADJUST_HW, /* without adjustments */ -+ OVERLAY_GAMMA_ADJUST_SW /* use adjustments */ -+ -+}; -+ -+union video_gamma_flag { -+ struct { -+ uint32_t CONFIG_IS_CHANGED:1; -+ uint32_t RESERVED:31; -+ } bits; -+ uint32_t u_all; -+}; -+ -+struct overlay_gamma_parameters { -+ union video_gamma_flag flag; -+ int32_t ovl_gamma_cont; -+ enum overlay_gamma_adjust adjust_type; -+ enum pixel_format desktop_surface; -+ struct regamma_lut regamma; -+ -+ /* here we grow with parameters if necessary */ -+}; -+ -+#endif --- -2.7.4 - |