Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Add DAC_LoadDetection to BIOS parser (v2)

DAC_LoadDetection can be used to determine whether something
is connected to an analog connector by determining if there is
an analog load. This causes visible flickering on displays, so
we only resort to using this when the connected display doesn't
have an EDID.

For reference, see the legacy display code:
amdgpu_atombios_encoder_dac_load_detect

v2:
Only clear corresponding bit from BIOS_SCRATCH_0.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Timur Kristóf and committed by
Alex Deucher
d75e45b8 7f1d1c2f

+155
+50
drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
··· 780 780 return bp->cmd_tbl.dig_encoder_control(bp, cntl); 781 781 } 782 782 783 + static enum bp_result bios_parser_dac_load_detection( 784 + struct dc_bios *dcb, 785 + enum engine_id engine_id, 786 + enum dal_device_type device_type, 787 + uint32_t enum_id) 788 + { 789 + struct bios_parser *bp = BP_FROM_DCB(dcb); 790 + struct dc_context *ctx = dcb->ctx; 791 + struct bp_load_detection_parameters bp_params = {0}; 792 + enum bp_result bp_result; 793 + uint32_t bios_0_scratch; 794 + uint32_t device_id_mask = 0; 795 + 796 + bp_params.engine_id = engine_id; 797 + bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id); 798 + 799 + if (engine_id != ENGINE_ID_DACA && 800 + engine_id != ENGINE_ID_DACB) 801 + return BP_RESULT_UNSUPPORTED; 802 + 803 + if (!bp->cmd_tbl.dac_load_detection) 804 + return BP_RESULT_UNSUPPORTED; 805 + 806 + if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 807 + device_id_mask = ATOM_S0_CRT1_MASK; 808 + else if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 809 + device_id_mask = ATOM_S0_CRT2_MASK; 810 + else 811 + return BP_RESULT_UNSUPPORTED; 812 + 813 + /* BIOS will write the detected devices to BIOS_SCRATCH_0, clear corresponding bit */ 814 + bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 815 + bios_0_scratch &= ~device_id_mask; 816 + dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); 817 + 818 + bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); 819 + 820 + if (bp_result != BP_RESULT_OK) 821 + return bp_result; 822 + 823 + bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 824 + 825 + if (bios_0_scratch & device_id_mask) 826 + return BP_RESULT_OK; 827 + 828 + return BP_RESULT_FAILURE; 829 + } 830 + 783 831 static enum bp_result bios_parser_adjust_pixel_clock( 784 832 struct dc_bios *dcb, 785 833 struct bp_adjust_pixel_clock_parameters *bp_params) ··· 2911 2863 .select_crtc_source = bios_parser_select_crtc_source, 2912 2864 2913 2865 .encoder_control = bios_parser_encoder_control, 2866 + 2867 + .dac_load_detection = bios_parser_dac_load_detection, 2914 2868 2915 2869 .transmitter_control = bios_parser_transmitter_control, 2916 2870
+92
drivers/gpu/drm/amd/display/dc/bios/command_table.c
··· 54 54 static void init_adjust_display_pll(struct bios_parser *bp); 55 55 static void init_select_crtc_source(struct bios_parser *bp); 56 56 static void init_dac_encoder_control(struct bios_parser *bp); 57 + static void init_dac_load_detection(struct bios_parser *bp); 57 58 static void init_dac_output_control(struct bios_parser *bp); 58 59 static void init_set_crtc_timing(struct bios_parser *bp); 59 60 static void init_enable_crtc(struct bios_parser *bp); ··· 73 72 init_adjust_display_pll(bp); 74 73 init_select_crtc_source(bp); 75 74 init_dac_encoder_control(bp); 75 + init_dac_load_detection(bp); 76 76 init_dac_output_control(bp); 77 77 init_set_crtc_timing(bp); 78 78 init_enable_crtc(bp); ··· 1899 1897 dac_standard); 1900 1898 1901 1899 if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params)) 1900 + result = BP_RESULT_OK; 1901 + 1902 + return result; 1903 + } 1904 + 1905 + /******************************************************************************* 1906 + ******************************************************************************** 1907 + ** 1908 + ** DAC LOAD DETECTION 1909 + ** 1910 + ******************************************************************************** 1911 + *******************************************************************************/ 1912 + 1913 + static enum bp_result dac_load_detection_v1( 1914 + struct bios_parser *bp, 1915 + struct bp_load_detection_parameters *bp_params); 1916 + 1917 + static enum bp_result dac_load_detection_v3( 1918 + struct bios_parser *bp, 1919 + struct bp_load_detection_parameters *bp_params); 1920 + 1921 + static void init_dac_load_detection(struct bios_parser *bp) 1922 + { 1923 + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) { 1924 + case 1: 1925 + case 2: 1926 + bp->cmd_tbl.dac_load_detection = dac_load_detection_v1; 1927 + break; 1928 + case 3: 1929 + default: 1930 + bp->cmd_tbl.dac_load_detection = dac_load_detection_v3; 1931 + break; 1932 + } 1933 + } 1934 + 1935 + static void dac_load_detect_prepare_params( 1936 + struct _DAC_LOAD_DETECTION_PS_ALLOCATION *params, 1937 + enum engine_id engine_id, 1938 + uint16_t device_id, 1939 + uint8_t misc) 1940 + { 1941 + uint8_t dac_type = ENGINE_ID_DACA; 1942 + 1943 + if (engine_id == ENGINE_ID_DACB) 1944 + dac_type = ATOM_DAC_B; 1945 + 1946 + params->sDacload.usDeviceID = cpu_to_le16(device_id); 1947 + params->sDacload.ucDacType = dac_type; 1948 + params->sDacload.ucMisc = misc; 1949 + } 1950 + 1951 + static enum bp_result dac_load_detection_v1( 1952 + struct bios_parser *bp, 1953 + struct bp_load_detection_parameters *bp_params) 1954 + { 1955 + enum bp_result result = BP_RESULT_FAILURE; 1956 + DAC_LOAD_DETECTION_PS_ALLOCATION params; 1957 + 1958 + dac_load_detect_prepare_params( 1959 + &params, 1960 + bp_params->engine_id, 1961 + bp_params->device_id, 1962 + 0); 1963 + 1964 + if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params)) 1965 + result = BP_RESULT_OK; 1966 + 1967 + return result; 1968 + } 1969 + 1970 + static enum bp_result dac_load_detection_v3( 1971 + struct bios_parser *bp, 1972 + struct bp_load_detection_parameters *bp_params) 1973 + { 1974 + enum bp_result result = BP_RESULT_FAILURE; 1975 + DAC_LOAD_DETECTION_PS_ALLOCATION params; 1976 + 1977 + uint8_t misc = 0; 1978 + 1979 + if (bp_params->device_id == ATOM_DEVICE_CV_SUPPORT || 1980 + bp_params->device_id == ATOM_DEVICE_TV1_SUPPORT) 1981 + misc = DAC_LOAD_MISC_YPrPb; 1982 + 1983 + dac_load_detect_prepare_params( 1984 + &params, 1985 + bp_params->engine_id, 1986 + bp_params->device_id, 1987 + misc); 1988 + 1989 + if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params)) 1902 1990 result = BP_RESULT_OK; 1903 1991 1904 1992 return result;
+3
drivers/gpu/drm/amd/display/dc/bios/command_table.h
··· 71 71 enum bp_result (*dac2_output_control)( 72 72 struct bios_parser *bp, 73 73 bool enable); 74 + enum bp_result (*dac_load_detection)( 75 + struct bios_parser *bp, 76 + struct bp_load_detection_parameters *bp_params); 74 77 enum bp_result (*set_crtc_timing)( 75 78 struct bios_parser *bp, 76 79 struct bp_hw_crtc_timing_parameters *bp_params);
+5
drivers/gpu/drm/amd/display/dc/dc_bios_types.h
··· 97 97 enum bp_result (*encoder_control)( 98 98 struct dc_bios *bios, 99 99 struct bp_encoder_control *cntl); 100 + enum bp_result (*dac_load_detection)( 101 + struct dc_bios *bios, 102 + enum engine_id engine_id, 103 + enum dal_device_type device_type, 104 + uint32_t enum_id); 100 105 enum bp_result (*transmitter_control)( 101 106 struct dc_bios *bios, 102 107 struct bp_transmitter_control *cntl);
+5
drivers/gpu/drm/amd/display/include/bios_parser_types.h
··· 162 162 bool single_pll_mode; 163 163 }; 164 164 165 + struct bp_load_detection_parameters { 166 + enum engine_id engine_id; 167 + uint16_t device_id; 168 + }; 169 + 165 170 struct bp_hw_crtc_timing_parameters { 166 171 enum controller_id controller_id; 167 172 /* horizontal part */