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

drm/amd/display: dc/dce: add initial DCE6 support (v10)

[Why]
DCE6 chipsets have a lot in common with DCE8, let's start from this

[How]
DCE6 targets are added replicating existing DCE8 implementation.

NOTE: dce_8_0_{d,sh_mask}.h headers used instead of dce_6_0_{d,sh_mask}.h
initial build prototype due to missing DCE6 macros/registers/masks
DCE6 specific macros/registers/masks will be added with later commits

(v2b) removed dce_version cases in dc/dce/dce_clock_source.c and
updated dce60 due to following kernel 5.0 commits:
24f7dd7 ("drm/amd/display: move pplib/smu notification to dccg block")
9566b67 ("drm/amd/display: remove safe_to_lower flag from dc, use 2 functions instead")
4244381 ("drm/amd/display: clean up base dccg struct")
4c5e8b5 ("drm/amd/display: split dccg clock manager into asic folders")
84e7fc0 ("drm/amd/display: rename dccg to clk_mgr")
77f6916 ("drm/amd/display: Remove duplicate header")
9f7ddbe ("drm/amd/display: fix optimize_bandwidth func pointer for dce80")
4ece61a ("drm/amd/display: set clocks to 0 on suspend on dce80")

(v3b) updated dce60 due to following kernel 5.1 commits:
380604e ("drm/amd/display: Use 100 Hz precision for pipe pixel clocks")
32e6136 ("drm/amd/display: Fix 64-bit division for 32-bit builds")
1877ccf ("drm/amd/display: Change from aux_engine to dce_aux")
c69dffa ("drm/amd/display: fix eDP fast bootup for pre-raven asic")

(v4b) updated dce60 due to following kernel 5.2 commits:
e5c4197 ("drm/amd/display: Add plane capabilities to dc_caps")
813d20d ("drm/amd/display: Fix multi-thread writing to 1 state")
ea36ad3 ("drm/amd/display: expand plane caps to include fp16 and scaling capability")
afcd526 ("drm/amd/display: Add fast_validate parameter")

(v5b) updated dce60 due to following kernel 5.3 commits:
e7e10c4 ("drm/amd/display: stop external access to internal optc sync params")
78cc70b ("drm/amd/display: Engine-specific encoder allocation")
dc88b4a ("drm/amd/display: make clk mgr soc specific")
4fc4dca ("drm/amd: drop use of drmp.h in os_types.h")

(v6b) updated dce60 due to following kernel 5.4 commits:
54a9bcb ("drm/amd/display: Fix a typo - dce_aduio_mask --> dce_audio_mask")
9adc805 ("drm/amd/display: make firmware info only load once during dc_bios create")

(v7b) updated dce60 due to following kernel 5.5 commits:
cabe144 ("drm/amd/display: memory leak")
8276dd8 ("drm/amd/display: update register field access mechanism")
f6040a4 ("drm/amd/display: configurable aux timeout support")
bf7f5ac ("drm/amd/display: map TRANSMITTER_UNIPHY_x to LINK_REGS_x")

(v8b) updated dce60 due to following kernel 5.6 commits:
d9e3267 ("drm/amd/display: cleanup of construct and destruct funcs")
f42ea55 ("drm/amd/display: add separate of private hwss functions")

(v9b) updated dce60 due to following kernel 5.8 commits:
bba8289 ("drm/amd/display: code clean up in dce80_hw_sequencer.c")
904fb6e ("drm/amd/display: move panel power seq to new panel struct")
d4caa72 ("drm/amd/display: change from panel to panel cntl")

(v10) Fix up PLL handling for DCE6:
DCE6.0 supports 2 PLLs. DCE6.1 supports 3 PLLs. (Alex)

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Mauro Rossi <issor.oruam@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Mauro Rossi and committed by
Alex Deucher
7c15fd86 f233c098

+1994
+4
drivers/gpu/drm/amd/display/dc/Makefile
··· 43 43 DC_LIBS += dce100 44 44 DC_LIBS += dce80 45 45 46 + ifdef CONFIG_DRM_AMD_DC_SI 47 + DC_LIBS += dce60 48 + endif 49 + 46 50 ifdef CONFIG_DRM_AMD_DC_HDCP 47 51 DC_LIBS += hdcp 48 52 endif
+34
drivers/gpu/drm/amd/display/dc/dce60/Makefile
··· 1 + # 2 + # Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + # 4 + # Permission is hereby granted, free of charge, to any person obtaining a 5 + # copy of this software and associated documentation files (the "Software"), 6 + # to deal in the Software without restriction, including without limitation 7 + # the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + # and/or sell copies of the Software, and to permit persons to whom the 9 + # Software is furnished to do so, subject to the following conditions: 10 + # 11 + # The above copyright notice and this permission notice shall be included in 12 + # all copies or substantial portions of the Software. 13 + # 14 + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + # OTHER DEALINGS IN THE SOFTWARE. 21 + # 22 + # 23 + # Makefile for the 'controller' sub-component of DAL. 24 + # It provides the control and status of HW CRTC block. 25 + 26 + DCE60 = dce60_timing_generator.o dce60_hw_sequencer.o \ 27 + dce60_resource.o 28 + 29 + AMD_DAL_DCE60 = $(addprefix $(AMDDALPATH)/dc/dce60/,$(DCE60)) 30 + 31 + AMD_DISPLAY_FILES += $(AMD_DAL_DCE60) 32 + 33 + 34 +
+54
drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #include "dm_services.h" 27 + #include "dc.h" 28 + #include "core_types.h" 29 + #include "dce60_hw_sequencer.h" 30 + 31 + #include "dce/dce_hwseq.h" 32 + #include "dce110/dce110_hw_sequencer.h" 33 + #include "dce100/dce100_hw_sequencer.h" 34 + 35 + /* include DCE8 register header files */ 36 + #include "dce/dce_6_0_d.h" 37 + #include "dce/dce_6_0_sh_mask.h" 38 + 39 + /******************************************************************************* 40 + * Private definitions 41 + ******************************************************************************/ 42 + 43 + /***************************PIPE_CONTROL***********************************/ 44 + 45 + void dce60_hw_sequencer_construct(struct dc *dc) 46 + { 47 + dce110_hw_sequencer_construct(dc); 48 + 49 + dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; 50 + dc->hwss.pipe_control_lock = dce_pipe_control_lock; 51 + dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; 52 + dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; 53 + } 54 +
+37
drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef __DC_HWSS_DCE60_H__ 27 + #define __DC_HWSS_DCE60_H__ 28 + 29 + #include "core_types.h" 30 + #include "hw_sequencer_private.h" 31 + 32 + struct dc; 33 + 34 + void dce60_hw_sequencer_construct(struct dc *dc); 35 + 36 + #endif /* __DC_HWSS_DCE60_H__ */ 37 +
+1532
drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #include <linux/slab.h> 27 + 28 + #include "dce/dce_8_0_d.h" 29 + #include "dce/dce_8_0_sh_mask.h" 30 + 31 + #include "dm_services.h" 32 + 33 + #include "link_encoder.h" 34 + #include "stream_encoder.h" 35 + 36 + #include "resource.h" 37 + #include "include/irq_service_interface.h" 38 + #include "irq/dce60/irq_service_dce60.h" 39 + #include "dce110/dce110_timing_generator.h" 40 + #include "dce110/dce110_resource.h" 41 + #include "dce60/dce60_timing_generator.h" 42 + #include "dce/dce_mem_input.h" 43 + #include "dce/dce_link_encoder.h" 44 + #include "dce/dce_stream_encoder.h" 45 + #include "dce/dce_ipp.h" 46 + #include "dce/dce_transform.h" 47 + #include "dce/dce_opp.h" 48 + #include "dce/dce_clock_source.h" 49 + #include "dce/dce_audio.h" 50 + #include "dce/dce_hwseq.h" 51 + #include "dce60/dce60_hw_sequencer.h" 52 + #include "dce100/dce100_resource.h" 53 + #include "dce/dce_panel_cntl.h" 54 + 55 + #include "reg_helper.h" 56 + 57 + #include "dce/dce_dmcu.h" 58 + #include "dce/dce_aux.h" 59 + #include "dce/dce_abm.h" 60 + #include "dce/dce_i2c.h" 61 + /* TODO remove this include */ 62 + 63 + #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT 64 + #include "gmc/gmc_6_0_d.h" 65 + #include "gmc/gmc_6_0_sh_mask.h" 66 + #endif 67 + 68 + #ifndef mmDP_DPHY_INTERNAL_CTRL 69 + #define mmDP_DPHY_INTERNAL_CTRL 0x1CDE 70 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE 71 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE 72 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE 73 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE 74 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE 75 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE 76 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE 77 + #endif 78 + 79 + 80 + #ifndef mmBIOS_SCRATCH_2 81 + #define mmBIOS_SCRATCH_2 0x05CB 82 + #define mmBIOS_SCRATCH_3 0x05CC 83 + #define mmBIOS_SCRATCH_6 0x05CF 84 + #endif 85 + 86 + #ifndef mmDP_DPHY_FAST_TRAINING 87 + #define mmDP_DPHY_FAST_TRAINING 0x1CCE 88 + #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE 89 + #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE 90 + #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE 91 + #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE 92 + #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE 93 + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE 94 + #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE 95 + #endif 96 + 97 + 98 + #ifndef mmHPD_DC_HPD_CONTROL 99 + #define mmHPD_DC_HPD_CONTROL 0x189A 100 + #define mmHPD0_DC_HPD_CONTROL 0x189A 101 + #define mmHPD1_DC_HPD_CONTROL 0x18A2 102 + #define mmHPD2_DC_HPD_CONTROL 0x18AA 103 + #define mmHPD3_DC_HPD_CONTROL 0x18B2 104 + #define mmHPD4_DC_HPD_CONTROL 0x18BA 105 + #define mmHPD5_DC_HPD_CONTROL 0x18C2 106 + #endif 107 + 108 + #define DCE11_DIG_FE_CNTL 0x4a00 109 + #define DCE11_DIG_BE_CNTL 0x4a47 110 + #define DCE11_DP_SEC 0x4ac3 111 + 112 + static const struct dce110_timing_generator_offsets dce60_tg_offsets[] = { 113 + { 114 + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), 115 + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), 116 + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL 117 + - mmDPG_WATERMARK_MASK_CONTROL), 118 + }, 119 + { 120 + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), 121 + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), 122 + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL 123 + - mmDPG_WATERMARK_MASK_CONTROL), 124 + }, 125 + { 126 + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), 127 + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), 128 + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL 129 + - mmDPG_WATERMARK_MASK_CONTROL), 130 + }, 131 + { 132 + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), 133 + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), 134 + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL 135 + - mmDPG_WATERMARK_MASK_CONTROL), 136 + }, 137 + { 138 + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), 139 + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), 140 + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL 141 + - mmDPG_WATERMARK_MASK_CONTROL), 142 + }, 143 + { 144 + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), 145 + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), 146 + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL 147 + - mmDPG_WATERMARK_MASK_CONTROL), 148 + } 149 + }; 150 + 151 + /* set register offset */ 152 + #define SR(reg_name)\ 153 + .reg_name = mm ## reg_name 154 + 155 + /* set register offset with instance */ 156 + #define SRI(reg_name, block, id)\ 157 + .reg_name = mm ## block ## id ## _ ## reg_name 158 + 159 + #define ipp_regs(id)\ 160 + [id] = {\ 161 + IPP_COMMON_REG_LIST_DCE_BASE(id)\ 162 + } 163 + 164 + static const struct dce_ipp_registers ipp_regs[] = { 165 + ipp_regs(0), 166 + ipp_regs(1), 167 + ipp_regs(2), 168 + ipp_regs(3), 169 + ipp_regs(4), 170 + ipp_regs(5) 171 + }; 172 + 173 + static const struct dce_ipp_shift ipp_shift = { 174 + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 175 + }; 176 + 177 + static const struct dce_ipp_mask ipp_mask = { 178 + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 179 + }; 180 + 181 + #define transform_regs(id)\ 182 + [id] = {\ 183 + XFM_COMMON_REG_LIST_DCE80(id)\ 184 + } 185 + 186 + static const struct dce_transform_registers xfm_regs[] = { 187 + transform_regs(0), 188 + transform_regs(1), 189 + transform_regs(2), 190 + transform_regs(3), 191 + transform_regs(4), 192 + transform_regs(5) 193 + }; 194 + 195 + static const struct dce_transform_shift xfm_shift = { 196 + XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) 197 + }; 198 + 199 + static const struct dce_transform_mask xfm_mask = { 200 + XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) 201 + }; 202 + 203 + #define aux_regs(id)\ 204 + [id] = {\ 205 + AUX_REG_LIST(id)\ 206 + } 207 + 208 + static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { 209 + aux_regs(0), 210 + aux_regs(1), 211 + aux_regs(2), 212 + aux_regs(3), 213 + aux_regs(4), 214 + aux_regs(5) 215 + }; 216 + 217 + #define hpd_regs(id)\ 218 + [id] = {\ 219 + HPD_REG_LIST(id)\ 220 + } 221 + 222 + static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { 223 + hpd_regs(0), 224 + hpd_regs(1), 225 + hpd_regs(2), 226 + hpd_regs(3), 227 + hpd_regs(4), 228 + hpd_regs(5) 229 + }; 230 + 231 + #define link_regs(id)\ 232 + [id] = {\ 233 + LE_DCE80_REG_LIST(id)\ 234 + } 235 + 236 + static const struct dce110_link_enc_registers link_enc_regs[] = { 237 + link_regs(0), 238 + link_regs(1), 239 + link_regs(2), 240 + link_regs(3), 241 + link_regs(4), 242 + link_regs(5), 243 + link_regs(6), 244 + }; 245 + 246 + #define stream_enc_regs(id)\ 247 + [id] = {\ 248 + SE_COMMON_REG_LIST_DCE_BASE(id),\ 249 + .AFMT_CNTL = 0,\ 250 + } 251 + 252 + static const struct dce110_stream_enc_registers stream_enc_regs[] = { 253 + stream_enc_regs(0), 254 + stream_enc_regs(1), 255 + stream_enc_regs(2), 256 + stream_enc_regs(3), 257 + stream_enc_regs(4), 258 + stream_enc_regs(5), 259 + stream_enc_regs(6) 260 + }; 261 + 262 + static const struct dce_stream_encoder_shift se_shift = { 263 + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) 264 + }; 265 + 266 + static const struct dce_stream_encoder_mask se_mask = { 267 + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) 268 + }; 269 + 270 + static const struct dce_panel_cntl_registers panel_cntl_regs[] = { 271 + { DCE_PANEL_CNTL_REG_LIST() } 272 + }; 273 + 274 + static const struct dce_panel_cntl_shift panel_cntl_shift = { 275 + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) 276 + }; 277 + 278 + static const struct dce_panel_cntl_mask panel_cntl_mask = { 279 + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) 280 + }; 281 + 282 + #define opp_regs(id)\ 283 + [id] = {\ 284 + OPP_DCE_80_REG_LIST(id),\ 285 + } 286 + 287 + static const struct dce_opp_registers opp_regs[] = { 288 + opp_regs(0), 289 + opp_regs(1), 290 + opp_regs(2), 291 + opp_regs(3), 292 + opp_regs(4), 293 + opp_regs(5) 294 + }; 295 + 296 + static const struct dce_opp_shift opp_shift = { 297 + OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) 298 + }; 299 + 300 + static const struct dce_opp_mask opp_mask = { 301 + OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) 302 + }; 303 + 304 + static const struct dce110_aux_registers_shift aux_shift = { 305 + DCE10_AUX_MASK_SH_LIST(__SHIFT) 306 + }; 307 + 308 + static const struct dce110_aux_registers_mask aux_mask = { 309 + DCE10_AUX_MASK_SH_LIST(_MASK) 310 + }; 311 + 312 + #define aux_engine_regs(id)\ 313 + [id] = {\ 314 + AUX_COMMON_REG_LIST(id), \ 315 + .AUX_RESET_MASK = 0 \ 316 + } 317 + 318 + static const struct dce110_aux_registers aux_engine_regs[] = { 319 + aux_engine_regs(0), 320 + aux_engine_regs(1), 321 + aux_engine_regs(2), 322 + aux_engine_regs(3), 323 + aux_engine_regs(4), 324 + aux_engine_regs(5) 325 + }; 326 + 327 + #define audio_regs(id)\ 328 + [id] = {\ 329 + AUD_COMMON_REG_LIST(id)\ 330 + } 331 + 332 + static const struct dce_audio_registers audio_regs[] = { 333 + audio_regs(0), 334 + audio_regs(1), 335 + audio_regs(2), 336 + audio_regs(3), 337 + audio_regs(4), 338 + audio_regs(5), 339 + audio_regs(6), 340 + }; 341 + 342 + static const struct dce_audio_shift audio_shift = { 343 + AUD_COMMON_MASK_SH_LIST(__SHIFT) 344 + }; 345 + 346 + static const struct dce_audio_mask audio_mask = { 347 + AUD_COMMON_MASK_SH_LIST(_MASK) 348 + }; 349 + 350 + #define clk_src_regs(id)\ 351 + [id] = {\ 352 + CS_COMMON_REG_LIST_DCE_80(id),\ 353 + } 354 + 355 + 356 + static const struct dce110_clk_src_regs clk_src_regs[] = { 357 + clk_src_regs(0), 358 + clk_src_regs(1), 359 + clk_src_regs(2) 360 + }; 361 + 362 + static const struct dce110_clk_src_shift cs_shift = { 363 + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 364 + }; 365 + 366 + static const struct dce110_clk_src_mask cs_mask = { 367 + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 368 + }; 369 + 370 + static const struct bios_registers bios_regs = { 371 + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, 372 + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 373 + }; 374 + 375 + static const struct resource_caps res_cap = { 376 + .num_timing_generator = 6, 377 + .num_audio = 6, 378 + .num_stream_encoder = 6, 379 + .num_pll = 2, 380 + .num_ddc = 6, 381 + }; 382 + 383 + static const struct resource_caps res_cap_61 = { 384 + .num_timing_generator = 4, 385 + .num_audio = 6, 386 + .num_stream_encoder = 6, 387 + .num_pll = 3, 388 + .num_ddc = 6, 389 + }; 390 + 391 + static const struct resource_caps res_cap_64 = { 392 + .num_timing_generator = 2, 393 + .num_audio = 2, 394 + .num_stream_encoder = 2, 395 + .num_pll = 2, 396 + .num_ddc = 2, 397 + }; 398 + 399 + static const struct dc_plane_cap plane_cap = { 400 + .type = DC_PLANE_TYPE_DCE_RGB, 401 + 402 + .pixel_format_support = { 403 + .argb8888 = true, 404 + .nv12 = false, 405 + .fp16 = false 406 + }, 407 + 408 + .max_upscale_factor = { 409 + .argb8888 = 16000, 410 + .nv12 = 1, 411 + .fp16 = 1 412 + }, 413 + 414 + .max_downscale_factor = { 415 + .argb8888 = 250, 416 + .nv12 = 1, 417 + .fp16 = 1 418 + } 419 + }; 420 + 421 + static const struct dce_dmcu_registers dmcu_regs = { 422 + DMCU_DCE80_REG_LIST() 423 + }; 424 + 425 + static const struct dce_dmcu_shift dmcu_shift = { 426 + DMCU_MASK_SH_LIST_DCE80(__SHIFT) 427 + }; 428 + 429 + static const struct dce_dmcu_mask dmcu_mask = { 430 + DMCU_MASK_SH_LIST_DCE80(_MASK) 431 + }; 432 + static const struct dce_abm_registers abm_regs = { 433 + ABM_DCE110_COMMON_REG_LIST() 434 + }; 435 + 436 + static const struct dce_abm_shift abm_shift = { 437 + ABM_MASK_SH_LIST_DCE110(__SHIFT) 438 + }; 439 + 440 + static const struct dce_abm_mask abm_mask = { 441 + ABM_MASK_SH_LIST_DCE110(_MASK) 442 + }; 443 + 444 + #define CTX ctx 445 + #define REG(reg) mm ## reg 446 + 447 + #ifndef mmCC_DC_HDMI_STRAPS 448 + #define mmCC_DC_HDMI_STRAPS 0x1918 449 + #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 450 + #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 451 + #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 452 + #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 453 + #endif 454 + 455 + static int map_transmitter_id_to_phy_instance( 456 + enum transmitter transmitter) 457 + { 458 + switch (transmitter) { 459 + case TRANSMITTER_UNIPHY_A: 460 + return 0; 461 + break; 462 + case TRANSMITTER_UNIPHY_B: 463 + return 1; 464 + break; 465 + case TRANSMITTER_UNIPHY_C: 466 + return 2; 467 + break; 468 + case TRANSMITTER_UNIPHY_D: 469 + return 3; 470 + break; 471 + case TRANSMITTER_UNIPHY_E: 472 + return 4; 473 + break; 474 + case TRANSMITTER_UNIPHY_F: 475 + return 5; 476 + break; 477 + case TRANSMITTER_UNIPHY_G: 478 + return 6; 479 + break; 480 + default: 481 + ASSERT(0); 482 + return 0; 483 + } 484 + } 485 + 486 + static void read_dce_straps( 487 + struct dc_context *ctx, 488 + struct resource_straps *straps) 489 + { 490 + REG_GET_2(CC_DC_HDMI_STRAPS, 491 + HDMI_DISABLE, &straps->hdmi_disable, 492 + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); 493 + 494 + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); 495 + } 496 + 497 + static struct audio *create_audio( 498 + struct dc_context *ctx, unsigned int inst) 499 + { 500 + return dce_audio_create(ctx, inst, 501 + &audio_regs[inst], &audio_shift, &audio_mask); 502 + } 503 + 504 + static struct timing_generator *dce60_timing_generator_create( 505 + struct dc_context *ctx, 506 + uint32_t instance, 507 + const struct dce110_timing_generator_offsets *offsets) 508 + { 509 + struct dce110_timing_generator *tg110 = 510 + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); 511 + 512 + if (!tg110) 513 + return NULL; 514 + 515 + dce60_timing_generator_construct(tg110, ctx, instance, offsets); 516 + return &tg110->base; 517 + } 518 + 519 + static struct output_pixel_processor *dce60_opp_create( 520 + struct dc_context *ctx, 521 + uint32_t inst) 522 + { 523 + struct dce110_opp *opp = 524 + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); 525 + 526 + if (!opp) 527 + return NULL; 528 + 529 + dce110_opp_construct(opp, 530 + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); 531 + return &opp->base; 532 + } 533 + 534 + struct dce_aux *dce60_aux_engine_create( 535 + struct dc_context *ctx, 536 + uint32_t inst) 537 + { 538 + struct aux_engine_dce110 *aux_engine = 539 + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); 540 + 541 + if (!aux_engine) 542 + return NULL; 543 + 544 + dce110_aux_engine_construct(aux_engine, ctx, inst, 545 + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, 546 + &aux_engine_regs[inst], 547 + &aux_mask, 548 + &aux_shift, 549 + ctx->dc->caps.extended_aux_timeout_support); 550 + 551 + return &aux_engine->base; 552 + } 553 + #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } 554 + 555 + static const struct dce_i2c_registers i2c_hw_regs[] = { 556 + i2c_inst_regs(1), 557 + i2c_inst_regs(2), 558 + i2c_inst_regs(3), 559 + i2c_inst_regs(4), 560 + i2c_inst_regs(5), 561 + i2c_inst_regs(6), 562 + }; 563 + 564 + static const struct dce_i2c_shift i2c_shifts = { 565 + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 566 + }; 567 + 568 + static const struct dce_i2c_mask i2c_masks = { 569 + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 570 + }; 571 + 572 + struct dce_i2c_hw *dce60_i2c_hw_create( 573 + struct dc_context *ctx, 574 + uint32_t inst) 575 + { 576 + struct dce_i2c_hw *dce_i2c_hw = 577 + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); 578 + 579 + if (!dce_i2c_hw) 580 + return NULL; 581 + 582 + dce_i2c_hw_construct(dce_i2c_hw, ctx, inst, 583 + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); 584 + 585 + return dce_i2c_hw; 586 + } 587 + 588 + struct dce_i2c_sw *dce60_i2c_sw_create( 589 + struct dc_context *ctx) 590 + { 591 + struct dce_i2c_sw *dce_i2c_sw = 592 + kzalloc(sizeof(struct dce_i2c_sw), GFP_KERNEL); 593 + 594 + if (!dce_i2c_sw) 595 + return NULL; 596 + 597 + dce_i2c_sw_construct(dce_i2c_sw, ctx); 598 + 599 + return dce_i2c_sw; 600 + } 601 + static struct stream_encoder *dce60_stream_encoder_create( 602 + enum engine_id eng_id, 603 + struct dc_context *ctx) 604 + { 605 + struct dce110_stream_encoder *enc110 = 606 + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); 607 + 608 + if (!enc110) 609 + return NULL; 610 + 611 + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, 612 + &stream_enc_regs[eng_id], 613 + &se_shift, &se_mask); 614 + return &enc110->base; 615 + } 616 + 617 + #define SRII(reg_name, block, id)\ 618 + .reg_name[id] = mm ## block ## id ## _ ## reg_name 619 + 620 + static const struct dce_hwseq_registers hwseq_reg = { 621 + HWSEQ_DCE8_REG_LIST() 622 + }; 623 + 624 + static const struct dce_hwseq_shift hwseq_shift = { 625 + HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) 626 + }; 627 + 628 + static const struct dce_hwseq_mask hwseq_mask = { 629 + HWSEQ_DCE8_MASK_SH_LIST(_MASK) 630 + }; 631 + 632 + static struct dce_hwseq *dce60_hwseq_create( 633 + struct dc_context *ctx) 634 + { 635 + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); 636 + 637 + if (hws) { 638 + hws->ctx = ctx; 639 + hws->regs = &hwseq_reg; 640 + hws->shifts = &hwseq_shift; 641 + hws->masks = &hwseq_mask; 642 + } 643 + return hws; 644 + } 645 + 646 + static const struct resource_create_funcs res_create_funcs = { 647 + .read_dce_straps = read_dce_straps, 648 + .create_audio = create_audio, 649 + .create_stream_encoder = dce60_stream_encoder_create, 650 + .create_hwseq = dce60_hwseq_create, 651 + }; 652 + 653 + #define mi_inst_regs(id) { \ 654 + MI_DCE8_REG_LIST(id), \ 655 + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ 656 + } 657 + static const struct dce_mem_input_registers mi_regs[] = { 658 + mi_inst_regs(0), 659 + mi_inst_regs(1), 660 + mi_inst_regs(2), 661 + mi_inst_regs(3), 662 + mi_inst_regs(4), 663 + mi_inst_regs(5), 664 + }; 665 + 666 + static const struct dce_mem_input_shift mi_shifts = { 667 + MI_DCE8_MASK_SH_LIST(__SHIFT), 668 + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT 669 + }; 670 + 671 + static const struct dce_mem_input_mask mi_masks = { 672 + MI_DCE8_MASK_SH_LIST(_MASK), 673 + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK 674 + }; 675 + 676 + static struct mem_input *dce60_mem_input_create( 677 + struct dc_context *ctx, 678 + uint32_t inst) 679 + { 680 + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), 681 + GFP_KERNEL); 682 + 683 + if (!dce_mi) { 684 + BREAK_TO_DEBUGGER(); 685 + return NULL; 686 + } 687 + 688 + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); 689 + dce_mi->wa.single_head_rdreq_dmif_limit = 2; 690 + return &dce_mi->base; 691 + } 692 + 693 + static void dce60_transform_destroy(struct transform **xfm) 694 + { 695 + kfree(TO_DCE_TRANSFORM(*xfm)); 696 + *xfm = NULL; 697 + } 698 + 699 + static struct transform *dce60_transform_create( 700 + struct dc_context *ctx, 701 + uint32_t inst) 702 + { 703 + struct dce_transform *transform = 704 + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); 705 + 706 + if (!transform) 707 + return NULL; 708 + 709 + dce_transform_construct(transform, ctx, inst, 710 + &xfm_regs[inst], &xfm_shift, &xfm_mask); 711 + transform->prescaler_on = false; 712 + return &transform->base; 713 + } 714 + 715 + static const struct encoder_feature_support link_enc_feature = { 716 + .max_hdmi_deep_color = COLOR_DEPTH_121212, 717 + .max_hdmi_pixel_clock = 297000, 718 + .flags.bits.IS_HBR2_CAPABLE = true, 719 + .flags.bits.IS_TPS3_CAPABLE = true 720 + }; 721 + 722 + struct link_encoder *dce60_link_encoder_create( 723 + const struct encoder_init_data *enc_init_data) 724 + { 725 + struct dce110_link_encoder *enc110 = 726 + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); 727 + int link_regs_id; 728 + 729 + if (!enc110) 730 + return NULL; 731 + 732 + link_regs_id = 733 + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); 734 + 735 + dce110_link_encoder_construct(enc110, 736 + enc_init_data, 737 + &link_enc_feature, 738 + &link_enc_regs[link_regs_id], 739 + &link_enc_aux_regs[enc_init_data->channel - 1], 740 + &link_enc_hpd_regs[enc_init_data->hpd_source]); 741 + return &enc110->base; 742 + } 743 + 744 + static struct panel_cntl *dce60_panel_cntl_create(const struct panel_cntl_init_data *init_data) 745 + { 746 + struct dce_panel_cntl *panel_cntl = 747 + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); 748 + 749 + if (!panel_cntl) 750 + return NULL; 751 + 752 + dce_panel_cntl_construct(panel_cntl, 753 + init_data, 754 + &panel_cntl_regs[init_data->inst], 755 + &panel_cntl_shift, 756 + &panel_cntl_mask); 757 + 758 + return &panel_cntl->base; 759 + } 760 + 761 + struct clock_source *dce60_clock_source_create( 762 + struct dc_context *ctx, 763 + struct dc_bios *bios, 764 + enum clock_source_id id, 765 + const struct dce110_clk_src_regs *regs, 766 + bool dp_clk_src) 767 + { 768 + struct dce110_clk_src *clk_src = 769 + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); 770 + 771 + if (!clk_src) 772 + return NULL; 773 + 774 + if (dce110_clk_src_construct(clk_src, ctx, bios, id, 775 + regs, &cs_shift, &cs_mask)) { 776 + clk_src->base.dp_clk_src = dp_clk_src; 777 + return &clk_src->base; 778 + } 779 + 780 + kfree(clk_src); 781 + BREAK_TO_DEBUGGER(); 782 + return NULL; 783 + } 784 + 785 + void dce60_clock_source_destroy(struct clock_source **clk_src) 786 + { 787 + kfree(TO_DCE110_CLK_SRC(*clk_src)); 788 + *clk_src = NULL; 789 + } 790 + 791 + static struct input_pixel_processor *dce60_ipp_create( 792 + struct dc_context *ctx, uint32_t inst) 793 + { 794 + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); 795 + 796 + if (!ipp) { 797 + BREAK_TO_DEBUGGER(); 798 + return NULL; 799 + } 800 + 801 + dce_ipp_construct(ipp, ctx, inst, 802 + &ipp_regs[inst], &ipp_shift, &ipp_mask); 803 + return &ipp->base; 804 + } 805 + 806 + static void dce60_resource_destruct(struct dce110_resource_pool *pool) 807 + { 808 + unsigned int i; 809 + 810 + for (i = 0; i < pool->base.pipe_count; i++) { 811 + if (pool->base.opps[i] != NULL) 812 + dce110_opp_destroy(&pool->base.opps[i]); 813 + 814 + if (pool->base.transforms[i] != NULL) 815 + dce60_transform_destroy(&pool->base.transforms[i]); 816 + 817 + if (pool->base.ipps[i] != NULL) 818 + dce_ipp_destroy(&pool->base.ipps[i]); 819 + 820 + if (pool->base.mis[i] != NULL) { 821 + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); 822 + pool->base.mis[i] = NULL; 823 + } 824 + 825 + if (pool->base.timing_generators[i] != NULL) { 826 + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); 827 + pool->base.timing_generators[i] = NULL; 828 + } 829 + } 830 + 831 + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 832 + if (pool->base.engines[i] != NULL) 833 + dce110_engine_destroy(&pool->base.engines[i]); 834 + if (pool->base.hw_i2cs[i] != NULL) { 835 + kfree(pool->base.hw_i2cs[i]); 836 + pool->base.hw_i2cs[i] = NULL; 837 + } 838 + if (pool->base.sw_i2cs[i] != NULL) { 839 + kfree(pool->base.sw_i2cs[i]); 840 + pool->base.sw_i2cs[i] = NULL; 841 + } 842 + } 843 + 844 + for (i = 0; i < pool->base.stream_enc_count; i++) { 845 + if (pool->base.stream_enc[i] != NULL) 846 + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); 847 + } 848 + 849 + for (i = 0; i < pool->base.clk_src_count; i++) { 850 + if (pool->base.clock_sources[i] != NULL) { 851 + dce60_clock_source_destroy(&pool->base.clock_sources[i]); 852 + } 853 + } 854 + 855 + if (pool->base.abm != NULL) 856 + dce_abm_destroy(&pool->base.abm); 857 + 858 + if (pool->base.dmcu != NULL) 859 + dce_dmcu_destroy(&pool->base.dmcu); 860 + 861 + if (pool->base.dp_clock_source != NULL) 862 + dce60_clock_source_destroy(&pool->base.dp_clock_source); 863 + 864 + for (i = 0; i < pool->base.audio_count; i++) { 865 + if (pool->base.audios[i] != NULL) { 866 + dce_aud_destroy(&pool->base.audios[i]); 867 + } 868 + } 869 + 870 + if (pool->base.irqs != NULL) { 871 + dal_irq_service_destroy(&pool->base.irqs); 872 + } 873 + } 874 + 875 + bool dce60_validate_bandwidth( 876 + struct dc *dc, 877 + struct dc_state *context, 878 + bool fast_validate) 879 + { 880 + int i; 881 + bool at_least_one_pipe = false; 882 + 883 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 884 + if (context->res_ctx.pipe_ctx[i].stream) 885 + at_least_one_pipe = true; 886 + } 887 + 888 + if (at_least_one_pipe) { 889 + /* TODO implement when needed but for now hardcode max value*/ 890 + context->bw_ctx.bw.dce.dispclk_khz = 681000; 891 + context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; 892 + } else { 893 + context->bw_ctx.bw.dce.dispclk_khz = 0; 894 + context->bw_ctx.bw.dce.yclk_khz = 0; 895 + } 896 + 897 + return true; 898 + } 899 + 900 + static bool dce60_validate_surface_sets( 901 + struct dc_state *context) 902 + { 903 + int i; 904 + 905 + for (i = 0; i < context->stream_count; i++) { 906 + if (context->stream_status[i].plane_count == 0) 907 + continue; 908 + 909 + if (context->stream_status[i].plane_count > 1) 910 + return false; 911 + 912 + if (context->stream_status[i].plane_states[0]->format 913 + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 914 + return false; 915 + } 916 + 917 + return true; 918 + } 919 + 920 + enum dc_status dce60_validate_global( 921 + struct dc *dc, 922 + struct dc_state *context) 923 + { 924 + if (!dce60_validate_surface_sets(context)) 925 + return DC_FAIL_SURFACE_VALIDATE; 926 + 927 + return DC_OK; 928 + } 929 + 930 + static void dce60_destroy_resource_pool(struct resource_pool **pool) 931 + { 932 + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); 933 + 934 + dce60_resource_destruct(dce110_pool); 935 + kfree(dce110_pool); 936 + *pool = NULL; 937 + } 938 + 939 + static const struct resource_funcs dce60_res_pool_funcs = { 940 + .destroy = dce60_destroy_resource_pool, 941 + .link_enc_create = dce60_link_encoder_create, 942 + .panel_cntl_create = dce60_panel_cntl_create, 943 + .validate_bandwidth = dce60_validate_bandwidth, 944 + .validate_plane = dce100_validate_plane, 945 + .add_stream_to_ctx = dce100_add_stream_to_ctx, 946 + .validate_global = dce60_validate_global, 947 + .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link 948 + }; 949 + 950 + static bool dce60_construct( 951 + uint8_t num_virtual_links, 952 + struct dc *dc, 953 + struct dce110_resource_pool *pool) 954 + { 955 + unsigned int i; 956 + struct dc_context *ctx = dc->ctx; 957 + struct dc_bios *bp; 958 + 959 + ctx->dc_bios->regs = &bios_regs; 960 + 961 + pool->base.res_cap = &res_cap; 962 + pool->base.funcs = &dce60_res_pool_funcs; 963 + 964 + 965 + /************************************************* 966 + * Resource + asic cap harcoding * 967 + *************************************************/ 968 + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; 969 + pool->base.pipe_count = res_cap.num_timing_generator; 970 + pool->base.timing_generator_count = res_cap.num_timing_generator; 971 + dc->caps.max_downscale_ratio = 200; 972 + dc->caps.i2c_speed_in_khz = 40; 973 + dc->caps.max_cursor_size = 128; 974 + dc->caps.dual_link_dvi = true; 975 + dc->caps.extended_aux_timeout_support = false; 976 + 977 + /************************************************* 978 + * Create resources * 979 + *************************************************/ 980 + 981 + bp = ctx->dc_bios; 982 + 983 + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { 984 + pool->base.dp_clock_source = 985 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); 986 + 987 + pool->base.clock_sources[0] = 988 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); 989 + pool->base.clock_sources[1] = 990 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); 991 + pool->base.clk_src_count = 2; 992 + 993 + } else { 994 + pool->base.dp_clock_source = 995 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); 996 + 997 + pool->base.clock_sources[0] = 998 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); 999 + pool->base.clk_src_count = 1; 1000 + } 1001 + 1002 + if (pool->base.dp_clock_source == NULL) { 1003 + dm_error("DC: failed to create dp clock source!\n"); 1004 + BREAK_TO_DEBUGGER(); 1005 + goto res_create_fail; 1006 + } 1007 + 1008 + for (i = 0; i < pool->base.clk_src_count; i++) { 1009 + if (pool->base.clock_sources[i] == NULL) { 1010 + dm_error("DC: failed to create clock sources!\n"); 1011 + BREAK_TO_DEBUGGER(); 1012 + goto res_create_fail; 1013 + } 1014 + } 1015 + 1016 + pool->base.dmcu = dce_dmcu_create(ctx, 1017 + &dmcu_regs, 1018 + &dmcu_shift, 1019 + &dmcu_mask); 1020 + if (pool->base.dmcu == NULL) { 1021 + dm_error("DC: failed to create dmcu!\n"); 1022 + BREAK_TO_DEBUGGER(); 1023 + goto res_create_fail; 1024 + } 1025 + 1026 + pool->base.abm = dce_abm_create(ctx, 1027 + &abm_regs, 1028 + &abm_shift, 1029 + &abm_mask); 1030 + if (pool->base.abm == NULL) { 1031 + dm_error("DC: failed to create abm!\n"); 1032 + BREAK_TO_DEBUGGER(); 1033 + goto res_create_fail; 1034 + } 1035 + 1036 + { 1037 + struct irq_service_init_data init_data; 1038 + init_data.ctx = dc->ctx; 1039 + pool->base.irqs = dal_irq_service_dce60_create(&init_data); 1040 + if (!pool->base.irqs) 1041 + goto res_create_fail; 1042 + } 1043 + 1044 + for (i = 0; i < pool->base.pipe_count; i++) { 1045 + pool->base.timing_generators[i] = dce60_timing_generator_create( 1046 + ctx, i, &dce60_tg_offsets[i]); 1047 + if (pool->base.timing_generators[i] == NULL) { 1048 + BREAK_TO_DEBUGGER(); 1049 + dm_error("DC: failed to create tg!\n"); 1050 + goto res_create_fail; 1051 + } 1052 + 1053 + pool->base.mis[i] = dce60_mem_input_create(ctx, i); 1054 + if (pool->base.mis[i] == NULL) { 1055 + BREAK_TO_DEBUGGER(); 1056 + dm_error("DC: failed to create memory input!\n"); 1057 + goto res_create_fail; 1058 + } 1059 + 1060 + pool->base.ipps[i] = dce60_ipp_create(ctx, i); 1061 + if (pool->base.ipps[i] == NULL) { 1062 + BREAK_TO_DEBUGGER(); 1063 + dm_error("DC: failed to create input pixel processor!\n"); 1064 + goto res_create_fail; 1065 + } 1066 + 1067 + pool->base.transforms[i] = dce60_transform_create(ctx, i); 1068 + if (pool->base.transforms[i] == NULL) { 1069 + BREAK_TO_DEBUGGER(); 1070 + dm_error("DC: failed to create transform!\n"); 1071 + goto res_create_fail; 1072 + } 1073 + 1074 + pool->base.opps[i] = dce60_opp_create(ctx, i); 1075 + if (pool->base.opps[i] == NULL) { 1076 + BREAK_TO_DEBUGGER(); 1077 + dm_error("DC: failed to create output pixel processor!\n"); 1078 + goto res_create_fail; 1079 + } 1080 + } 1081 + 1082 + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 1083 + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); 1084 + if (pool->base.engines[i] == NULL) { 1085 + BREAK_TO_DEBUGGER(); 1086 + dm_error( 1087 + "DC:failed to create aux engine!!\n"); 1088 + goto res_create_fail; 1089 + } 1090 + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); 1091 + if (pool->base.hw_i2cs[i] == NULL) { 1092 + BREAK_TO_DEBUGGER(); 1093 + dm_error( 1094 + "DC:failed to create i2c engine!!\n"); 1095 + goto res_create_fail; 1096 + } 1097 + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); 1098 + if (pool->base.sw_i2cs[i] == NULL) { 1099 + BREAK_TO_DEBUGGER(); 1100 + dm_error( 1101 + "DC:failed to create sw i2c!!\n"); 1102 + goto res_create_fail; 1103 + } 1104 + } 1105 + 1106 + dc->caps.max_planes = pool->base.pipe_count; 1107 + 1108 + for (i = 0; i < dc->caps.max_planes; ++i) 1109 + dc->caps.planes[i] = plane_cap; 1110 + 1111 + dc->caps.disable_dp_clk_share = true; 1112 + 1113 + if (!resource_construct(num_virtual_links, dc, &pool->base, 1114 + &res_create_funcs)) 1115 + goto res_create_fail; 1116 + 1117 + /* Create hardware sequencer */ 1118 + dce60_hw_sequencer_construct(dc); 1119 + 1120 + return true; 1121 + 1122 + res_create_fail: 1123 + dce60_resource_destruct(pool); 1124 + return false; 1125 + } 1126 + 1127 + struct resource_pool *dce60_create_resource_pool( 1128 + uint8_t num_virtual_links, 1129 + struct dc *dc) 1130 + { 1131 + struct dce110_resource_pool *pool = 1132 + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); 1133 + 1134 + if (!pool) 1135 + return NULL; 1136 + 1137 + if (dce60_construct(num_virtual_links, dc, pool)) 1138 + return &pool->base; 1139 + 1140 + BREAK_TO_DEBUGGER(); 1141 + return NULL; 1142 + } 1143 + 1144 + static bool dce61_construct( 1145 + uint8_t num_virtual_links, 1146 + struct dc *dc, 1147 + struct dce110_resource_pool *pool) 1148 + { 1149 + unsigned int i; 1150 + struct dc_context *ctx = dc->ctx; 1151 + struct dc_bios *bp; 1152 + 1153 + ctx->dc_bios->regs = &bios_regs; 1154 + 1155 + pool->base.res_cap = &res_cap_61; 1156 + pool->base.funcs = &dce60_res_pool_funcs; 1157 + 1158 + 1159 + /************************************************* 1160 + * Resource + asic cap harcoding * 1161 + *************************************************/ 1162 + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; 1163 + pool->base.pipe_count = res_cap_61.num_timing_generator; 1164 + pool->base.timing_generator_count = res_cap_61.num_timing_generator; 1165 + dc->caps.max_downscale_ratio = 200; 1166 + dc->caps.i2c_speed_in_khz = 40; 1167 + dc->caps.max_cursor_size = 128; 1168 + dc->caps.is_apu = true; 1169 + 1170 + /************************************************* 1171 + * Create resources * 1172 + *************************************************/ 1173 + 1174 + bp = ctx->dc_bios; 1175 + 1176 + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { 1177 + pool->base.dp_clock_source = 1178 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); 1179 + 1180 + pool->base.clock_sources[0] = 1181 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); 1182 + pool->base.clock_sources[1] = 1183 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); 1184 + pool->base.clock_sources[2] = 1185 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); 1186 + pool->base.clk_src_count = 3; 1187 + 1188 + } else { 1189 + pool->base.dp_clock_source = 1190 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); 1191 + 1192 + pool->base.clock_sources[0] = 1193 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); 1194 + pool->base.clock_sources[1] = 1195 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); 1196 + pool->base.clk_src_count = 2; 1197 + } 1198 + 1199 + if (pool->base.dp_clock_source == NULL) { 1200 + dm_error("DC: failed to create dp clock source!\n"); 1201 + BREAK_TO_DEBUGGER(); 1202 + goto res_create_fail; 1203 + } 1204 + 1205 + for (i = 0; i < pool->base.clk_src_count; i++) { 1206 + if (pool->base.clock_sources[i] == NULL) { 1207 + dm_error("DC: failed to create clock sources!\n"); 1208 + BREAK_TO_DEBUGGER(); 1209 + goto res_create_fail; 1210 + } 1211 + } 1212 + 1213 + pool->base.dmcu = dce_dmcu_create(ctx, 1214 + &dmcu_regs, 1215 + &dmcu_shift, 1216 + &dmcu_mask); 1217 + if (pool->base.dmcu == NULL) { 1218 + dm_error("DC: failed to create dmcu!\n"); 1219 + BREAK_TO_DEBUGGER(); 1220 + goto res_create_fail; 1221 + } 1222 + 1223 + pool->base.abm = dce_abm_create(ctx, 1224 + &abm_regs, 1225 + &abm_shift, 1226 + &abm_mask); 1227 + if (pool->base.abm == NULL) { 1228 + dm_error("DC: failed to create abm!\n"); 1229 + BREAK_TO_DEBUGGER(); 1230 + goto res_create_fail; 1231 + } 1232 + 1233 + { 1234 + struct irq_service_init_data init_data; 1235 + init_data.ctx = dc->ctx; 1236 + pool->base.irqs = dal_irq_service_dce60_create(&init_data); 1237 + if (!pool->base.irqs) 1238 + goto res_create_fail; 1239 + } 1240 + 1241 + for (i = 0; i < pool->base.pipe_count; i++) { 1242 + pool->base.timing_generators[i] = dce60_timing_generator_create( 1243 + ctx, i, &dce60_tg_offsets[i]); 1244 + if (pool->base.timing_generators[i] == NULL) { 1245 + BREAK_TO_DEBUGGER(); 1246 + dm_error("DC: failed to create tg!\n"); 1247 + goto res_create_fail; 1248 + } 1249 + 1250 + pool->base.mis[i] = dce60_mem_input_create(ctx, i); 1251 + if (pool->base.mis[i] == NULL) { 1252 + BREAK_TO_DEBUGGER(); 1253 + dm_error("DC: failed to create memory input!\n"); 1254 + goto res_create_fail; 1255 + } 1256 + 1257 + pool->base.ipps[i] = dce60_ipp_create(ctx, i); 1258 + if (pool->base.ipps[i] == NULL) { 1259 + BREAK_TO_DEBUGGER(); 1260 + dm_error("DC: failed to create input pixel processor!\n"); 1261 + goto res_create_fail; 1262 + } 1263 + 1264 + pool->base.transforms[i] = dce60_transform_create(ctx, i); 1265 + if (pool->base.transforms[i] == NULL) { 1266 + BREAK_TO_DEBUGGER(); 1267 + dm_error("DC: failed to create transform!\n"); 1268 + goto res_create_fail; 1269 + } 1270 + 1271 + pool->base.opps[i] = dce60_opp_create(ctx, i); 1272 + if (pool->base.opps[i] == NULL) { 1273 + BREAK_TO_DEBUGGER(); 1274 + dm_error("DC: failed to create output pixel processor!\n"); 1275 + goto res_create_fail; 1276 + } 1277 + } 1278 + 1279 + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 1280 + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); 1281 + if (pool->base.engines[i] == NULL) { 1282 + BREAK_TO_DEBUGGER(); 1283 + dm_error( 1284 + "DC:failed to create aux engine!!\n"); 1285 + goto res_create_fail; 1286 + } 1287 + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); 1288 + if (pool->base.hw_i2cs[i] == NULL) { 1289 + BREAK_TO_DEBUGGER(); 1290 + dm_error( 1291 + "DC:failed to create i2c engine!!\n"); 1292 + goto res_create_fail; 1293 + } 1294 + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); 1295 + if (pool->base.sw_i2cs[i] == NULL) { 1296 + BREAK_TO_DEBUGGER(); 1297 + dm_error( 1298 + "DC:failed to create sw i2c!!\n"); 1299 + goto res_create_fail; 1300 + } 1301 + } 1302 + 1303 + dc->caps.max_planes = pool->base.pipe_count; 1304 + 1305 + for (i = 0; i < dc->caps.max_planes; ++i) 1306 + dc->caps.planes[i] = plane_cap; 1307 + 1308 + dc->caps.disable_dp_clk_share = true; 1309 + 1310 + if (!resource_construct(num_virtual_links, dc, &pool->base, 1311 + &res_create_funcs)) 1312 + goto res_create_fail; 1313 + 1314 + /* Create hardware sequencer */ 1315 + dce60_hw_sequencer_construct(dc); 1316 + 1317 + return true; 1318 + 1319 + res_create_fail: 1320 + dce60_resource_destruct(pool); 1321 + return false; 1322 + } 1323 + 1324 + struct resource_pool *dce61_create_resource_pool( 1325 + uint8_t num_virtual_links, 1326 + struct dc *dc) 1327 + { 1328 + struct dce110_resource_pool *pool = 1329 + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); 1330 + 1331 + if (!pool) 1332 + return NULL; 1333 + 1334 + if (dce61_construct(num_virtual_links, dc, pool)) 1335 + return &pool->base; 1336 + 1337 + BREAK_TO_DEBUGGER(); 1338 + return NULL; 1339 + } 1340 + 1341 + static bool dce64_construct( 1342 + uint8_t num_virtual_links, 1343 + struct dc *dc, 1344 + struct dce110_resource_pool *pool) 1345 + { 1346 + unsigned int i; 1347 + struct dc_context *ctx = dc->ctx; 1348 + struct dc_bios *bp; 1349 + 1350 + ctx->dc_bios->regs = &bios_regs; 1351 + 1352 + pool->base.res_cap = &res_cap_64; 1353 + pool->base.funcs = &dce60_res_pool_funcs; 1354 + 1355 + 1356 + /************************************************* 1357 + * Resource + asic cap harcoding * 1358 + *************************************************/ 1359 + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; 1360 + pool->base.pipe_count = res_cap_64.num_timing_generator; 1361 + pool->base.timing_generator_count = res_cap_64.num_timing_generator; 1362 + dc->caps.max_downscale_ratio = 200; 1363 + dc->caps.i2c_speed_in_khz = 40; 1364 + dc->caps.max_cursor_size = 128; 1365 + dc->caps.is_apu = true; 1366 + 1367 + /************************************************* 1368 + * Create resources * 1369 + *************************************************/ 1370 + 1371 + bp = ctx->dc_bios; 1372 + 1373 + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { 1374 + pool->base.dp_clock_source = 1375 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); 1376 + 1377 + pool->base.clock_sources[0] = 1378 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); 1379 + pool->base.clock_sources[1] = 1380 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); 1381 + pool->base.clk_src_count = 2; 1382 + 1383 + } else { 1384 + pool->base.dp_clock_source = 1385 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); 1386 + 1387 + pool->base.clock_sources[0] = 1388 + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); 1389 + pool->base.clk_src_count = 1; 1390 + } 1391 + 1392 + if (pool->base.dp_clock_source == NULL) { 1393 + dm_error("DC: failed to create dp clock source!\n"); 1394 + BREAK_TO_DEBUGGER(); 1395 + goto res_create_fail; 1396 + } 1397 + 1398 + for (i = 0; i < pool->base.clk_src_count; i++) { 1399 + if (pool->base.clock_sources[i] == NULL) { 1400 + dm_error("DC: failed to create clock sources!\n"); 1401 + BREAK_TO_DEBUGGER(); 1402 + goto res_create_fail; 1403 + } 1404 + } 1405 + 1406 + pool->base.dmcu = dce_dmcu_create(ctx, 1407 + &dmcu_regs, 1408 + &dmcu_shift, 1409 + &dmcu_mask); 1410 + if (pool->base.dmcu == NULL) { 1411 + dm_error("DC: failed to create dmcu!\n"); 1412 + BREAK_TO_DEBUGGER(); 1413 + goto res_create_fail; 1414 + } 1415 + 1416 + pool->base.abm = dce_abm_create(ctx, 1417 + &abm_regs, 1418 + &abm_shift, 1419 + &abm_mask); 1420 + if (pool->base.abm == NULL) { 1421 + dm_error("DC: failed to create abm!\n"); 1422 + BREAK_TO_DEBUGGER(); 1423 + goto res_create_fail; 1424 + } 1425 + 1426 + { 1427 + struct irq_service_init_data init_data; 1428 + init_data.ctx = dc->ctx; 1429 + pool->base.irqs = dal_irq_service_dce60_create(&init_data); 1430 + if (!pool->base.irqs) 1431 + goto res_create_fail; 1432 + } 1433 + 1434 + for (i = 0; i < pool->base.pipe_count; i++) { 1435 + pool->base.timing_generators[i] = dce60_timing_generator_create( 1436 + ctx, i, &dce60_tg_offsets[i]); 1437 + if (pool->base.timing_generators[i] == NULL) { 1438 + BREAK_TO_DEBUGGER(); 1439 + dm_error("DC: failed to create tg!\n"); 1440 + goto res_create_fail; 1441 + } 1442 + 1443 + pool->base.mis[i] = dce60_mem_input_create(ctx, i); 1444 + if (pool->base.mis[i] == NULL) { 1445 + BREAK_TO_DEBUGGER(); 1446 + dm_error("DC: failed to create memory input!\n"); 1447 + goto res_create_fail; 1448 + } 1449 + 1450 + pool->base.ipps[i] = dce60_ipp_create(ctx, i); 1451 + if (pool->base.ipps[i] == NULL) { 1452 + BREAK_TO_DEBUGGER(); 1453 + dm_error("DC: failed to create input pixel processor!\n"); 1454 + goto res_create_fail; 1455 + } 1456 + 1457 + pool->base.transforms[i] = dce60_transform_create(ctx, i); 1458 + if (pool->base.transforms[i] == NULL) { 1459 + BREAK_TO_DEBUGGER(); 1460 + dm_error("DC: failed to create transform!\n"); 1461 + goto res_create_fail; 1462 + } 1463 + 1464 + pool->base.opps[i] = dce60_opp_create(ctx, i); 1465 + if (pool->base.opps[i] == NULL) { 1466 + BREAK_TO_DEBUGGER(); 1467 + dm_error("DC: failed to create output pixel processor!\n"); 1468 + goto res_create_fail; 1469 + } 1470 + } 1471 + 1472 + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 1473 + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); 1474 + if (pool->base.engines[i] == NULL) { 1475 + BREAK_TO_DEBUGGER(); 1476 + dm_error( 1477 + "DC:failed to create aux engine!!\n"); 1478 + goto res_create_fail; 1479 + } 1480 + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); 1481 + if (pool->base.hw_i2cs[i] == NULL) { 1482 + BREAK_TO_DEBUGGER(); 1483 + dm_error( 1484 + "DC:failed to create i2c engine!!\n"); 1485 + goto res_create_fail; 1486 + } 1487 + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); 1488 + if (pool->base.sw_i2cs[i] == NULL) { 1489 + BREAK_TO_DEBUGGER(); 1490 + dm_error( 1491 + "DC:failed to create sw i2c!!\n"); 1492 + goto res_create_fail; 1493 + } 1494 + } 1495 + 1496 + dc->caps.max_planes = pool->base.pipe_count; 1497 + 1498 + for (i = 0; i < dc->caps.max_planes; ++i) 1499 + dc->caps.planes[i] = plane_cap; 1500 + 1501 + dc->caps.disable_dp_clk_share = true; 1502 + 1503 + if (!resource_construct(num_virtual_links, dc, &pool->base, 1504 + &res_create_funcs)) 1505 + goto res_create_fail; 1506 + 1507 + /* Create hardware sequencer */ 1508 + dce60_hw_sequencer_construct(dc); 1509 + 1510 + return true; 1511 + 1512 + res_create_fail: 1513 + dce60_resource_destruct(pool); 1514 + return false; 1515 + } 1516 + 1517 + struct resource_pool *dce64_create_resource_pool( 1518 + uint8_t num_virtual_links, 1519 + struct dc *dc) 1520 + { 1521 + struct dce110_resource_pool *pool = 1522 + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); 1523 + 1524 + if (!pool) 1525 + return NULL; 1526 + 1527 + if (dce64_construct(num_virtual_links, dc, pool)) 1528 + return &pool->base; 1529 + 1530 + BREAK_TO_DEBUGGER(); 1531 + return NULL; 1532 + }
+47
drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef __DC_RESOURCE_DCE60_H__ 27 + #define __DC_RESOURCE_DCE60_H__ 28 + 29 + #include "core_types.h" 30 + 31 + struct dc; 32 + struct resource_pool; 33 + 34 + struct resource_pool *dce60_create_resource_pool( 35 + uint8_t num_virtual_links, 36 + struct dc *dc); 37 + 38 + struct resource_pool *dce61_create_resource_pool( 39 + uint8_t num_virtual_links, 40 + struct dc *dc); 41 + 42 + struct resource_pool *dce64_create_resource_pool( 43 + uint8_t num_virtual_links, 44 + struct dc *dc); 45 + 46 + #endif /* __DC_RESOURCE_DCE60_H__ */ 47 +
+247
drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #include "dm_services.h" 27 + 28 + /* include DCE6 register header files */ 29 + #include "dce/dce_6_0_d.h" 30 + #include "dce/dce_6_0_sh_mask.h" 31 + 32 + #include "dc_types.h" 33 + 34 + #include "include/grph_object_id.h" 35 + #include "include/logger_interface.h" 36 + #include "../dce110/dce110_timing_generator.h" 37 + #include "dce60_timing_generator.h" 38 + 39 + #include "timing_generator.h" 40 + 41 + enum black_color_format { 42 + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, /* used as index in array */ 43 + BLACK_COLOR_FORMAT_RGB_LIMITED, 44 + BLACK_COLOR_FORMAT_YUV_TV, 45 + BLACK_COLOR_FORMAT_YUV_CV, 46 + BLACK_COLOR_FORMAT_YUV_SUPER_AA, 47 + 48 + BLACK_COLOR_FORMAT_COUNT 49 + }; 50 + 51 + static const struct dce110_timing_generator_offsets reg_offsets[] = { 52 + { 53 + .crtc = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 54 + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 55 + }, 56 + { 57 + .crtc = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 58 + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 59 + }, 60 + { 61 + .crtc = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 62 + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 63 + }, 64 + { 65 + .crtc = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 66 + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 67 + }, 68 + { 69 + .crtc = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 70 + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 71 + }, 72 + { 73 + .crtc = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), 74 + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), 75 + } 76 + }; 77 + 78 + #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 79 + 80 + #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) 81 + #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) 82 + 83 + #define CRTC_REG(reg) (reg + tg110->offsets.crtc) 84 + #define DCP_REG(reg) (reg + tg110->offsets.dcp) 85 + #define DMIF_REG(reg) (reg + tg110->offsets.dmif) 86 + 87 + static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_100hz) 88 + { 89 + uint64_t pix_dur; 90 + uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 91 + + DCE110TG_FROM_TG(tg)->offsets.dmif; 92 + uint32_t value = dm_read_reg(tg->ctx, addr); 93 + 94 + if (pix_clk_100hz == 0) 95 + return; 96 + 97 + pix_dur = div_u64(10000000000ull, pix_clk_100hz); 98 + 99 + set_reg_field_value( 100 + value, 101 + pix_dur, 102 + DPG_PIPE_ARBITRATION_CONTROL1, 103 + PIXEL_DURATION); 104 + 105 + dm_write_reg(tg->ctx, addr, value); 106 + } 107 + 108 + static void program_timing(struct timing_generator *tg, 109 + const struct dc_crtc_timing *timing, 110 + int vready_offset, 111 + int vstartup_start, 112 + int vupdate_offset, 113 + int vupdate_width, 114 + const enum signal_type signal, 115 + bool use_vbios) 116 + { 117 + if (!use_vbios) 118 + program_pix_dur(tg, timing->pix_clk_100hz); 119 + 120 + dce110_tg_program_timing(tg, timing, 0, 0, 0, 0, 0, use_vbios); 121 + } 122 + 123 + static void dce60_timing_generator_enable_advanced_request( 124 + struct timing_generator *tg, 125 + bool enable, 126 + const struct dc_crtc_timing *timing) 127 + { 128 + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 129 + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); 130 + uint32_t value = dm_read_reg(tg->ctx, addr); 131 + 132 + if (enable) { 133 + set_reg_field_value( 134 + value, 135 + 0, 136 + CRTC_START_LINE_CONTROL, 137 + CRTC_LEGACY_REQUESTOR_EN); 138 + } else { 139 + set_reg_field_value( 140 + value, 141 + 1, 142 + CRTC_START_LINE_CONTROL, 143 + CRTC_LEGACY_REQUESTOR_EN); 144 + } 145 + 146 + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { 147 + set_reg_field_value( 148 + value, 149 + 3, 150 + CRTC_START_LINE_CONTROL, 151 + CRTC_ADVANCED_START_LINE_POSITION); 152 + set_reg_field_value( 153 + value, 154 + 0, 155 + CRTC_START_LINE_CONTROL, 156 + CRTC_PREFETCH_EN); 157 + } else { 158 + set_reg_field_value( 159 + value, 160 + 4, 161 + CRTC_START_LINE_CONTROL, 162 + CRTC_ADVANCED_START_LINE_POSITION); 163 + set_reg_field_value( 164 + value, 165 + 1, 166 + CRTC_START_LINE_CONTROL, 167 + CRTC_PREFETCH_EN); 168 + } 169 + 170 + set_reg_field_value( 171 + value, 172 + 1, 173 + CRTC_START_LINE_CONTROL, 174 + CRTC_PROGRESSIVE_START_LINE_EARLY); 175 + 176 + set_reg_field_value( 177 + value, 178 + 1, 179 + CRTC_START_LINE_CONTROL, 180 + CRTC_INTERLACE_START_LINE_EARLY); 181 + 182 + dm_write_reg(tg->ctx, addr, value); 183 + } 184 + 185 + static const struct timing_generator_funcs dce60_tg_funcs = { 186 + .validate_timing = dce110_tg_validate_timing, 187 + .program_timing = program_timing, 188 + .enable_crtc = dce110_timing_generator_enable_crtc, 189 + .disable_crtc = dce110_timing_generator_disable_crtc, 190 + .is_counter_moving = dce110_timing_generator_is_counter_moving, 191 + .get_position = dce110_timing_generator_get_position, 192 + .get_frame_count = dce110_timing_generator_get_vblank_counter, 193 + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, 194 + .set_early_control = dce110_timing_generator_set_early_control, 195 + .wait_for_state = dce110_tg_wait_for_state, 196 + .set_blank = dce110_tg_set_blank, 197 + .is_blanked = dce110_tg_is_blanked, 198 + .set_colors = dce110_tg_set_colors, 199 + .set_overscan_blank_color = 200 + dce110_timing_generator_set_overscan_color_black, 201 + .set_blank_color = dce110_timing_generator_program_blank_color, 202 + .disable_vga = dce110_timing_generator_disable_vga, 203 + .did_triggered_reset_occur = 204 + dce110_timing_generator_did_triggered_reset_occur, 205 + .setup_global_swap_lock = 206 + dce110_timing_generator_setup_global_swap_lock, 207 + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, 208 + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, 209 + .tear_down_global_swap_lock = 210 + dce110_timing_generator_tear_down_global_swap_lock, 211 + .set_drr = dce110_timing_generator_set_drr, 212 + .set_static_screen_control = 213 + dce110_timing_generator_set_static_screen_control, 214 + .set_test_pattern = dce110_timing_generator_set_test_pattern, 215 + .arm_vert_intr = dce110_arm_vert_intr, 216 + 217 + /* DCE6.0 overrides */ 218 + .enable_advanced_request = 219 + dce60_timing_generator_enable_advanced_request, 220 + .configure_crc = dce110_configure_crc, 221 + .get_crc = dce110_get_crc, 222 + }; 223 + 224 + void dce60_timing_generator_construct( 225 + struct dce110_timing_generator *tg110, 226 + struct dc_context *ctx, 227 + uint32_t instance, 228 + const struct dce110_timing_generator_offsets *offsets) 229 + { 230 + tg110->controller_id = CONTROLLER_ID_D0 + instance; 231 + tg110->base.inst = instance; 232 + tg110->offsets = *offsets; 233 + tg110->derived_offsets = reg_offsets[instance]; 234 + 235 + tg110->base.funcs = &dce60_tg_funcs; 236 + 237 + tg110->base.ctx = ctx; 238 + tg110->base.bp = ctx->dc_bios; 239 + 240 + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; 241 + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; 242 + 243 + tg110->min_h_blank = 56; 244 + tg110->min_h_front_porch = 4; 245 + tg110->min_h_back_porch = 4; 246 + } 247 +
+39
drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h
··· 1 + /* 2 + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef __DC_TIMING_GENERATOR_DCE60_H__ 27 + #define __DC_TIMING_GENERATOR_DCE60_H__ 28 + 29 + #include "timing_generator.h" 30 + #include "../include/grph_object_id.h" 31 + 32 + /* DCE6.0 implementation inherits from DCE11.0 */ 33 + void dce60_timing_generator_construct( 34 + struct dce110_timing_generator *tg, 35 + struct dc_context *ctx, 36 + uint32_t instance, 37 + const struct dce110_timing_generator_offsets *offsets); 38 + 39 + #endif /* __DC_TIMING_GENERATOR_DCE60_H__ */