FILE
irq_service_dcn401.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
1// SPDX-License-Identifier: MIT 2// 3// Copyright 2024 Advanced Micro Devices, Inc. 4 5#include "dm_services.h" 6#include "include/logger_interface.h" 7#include "../dce110/irq_service_dce110.h" 8 9#include "dcn/dcn_4_1_0_offset.h" 10#include "dcn/dcn_4_1_0_sh_mask.h" 11 12#include "irq_service_dcn401.h" 13 14#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" 15 16#define DCN_BASE__INST0_SEG2 0x000034C0 17 18static enum dc_irq_source to_dal_irq_source_dcn401( 19 struct irq_service *irq_service, 20 uint32_t src_id, 21 uint32_t ext_id) 22{ 23 switch (src_id) { 24 case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: 25 return DC_IRQ_SOURCE_VBLANK1; 26 case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: 27 return DC_IRQ_SOURCE_VBLANK2; 28 case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP: 29 return DC_IRQ_SOURCE_VBLANK3; 30 case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP: 31 return DC_IRQ_SOURCE_VBLANK4; 32 case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP: 33 return DC_IRQ_SOURCE_VBLANK5; 34 case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: 35 return DC_IRQ_SOURCE_VBLANK6; 36 case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL: 37 return DC_IRQ_SOURCE_DC1_VLINE0; 38 case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL: 39 return DC_IRQ_SOURCE_DC2_VLINE0; 40 case DCN_1_0__SRCID__OTG3_VERTICAL_INTERRUPT0_CONTROL: 41 return DC_IRQ_SOURCE_DC3_VLINE0; 42 case DCN_1_0__SRCID__OTG4_VERTICAL_INTERRUPT0_CONTROL: 43 return DC_IRQ_SOURCE_DC4_VLINE0; 44 case DCN_1_0__SRCID__OTG5_VERTICAL_INTERRUPT0_CONTROL: 45 return DC_IRQ_SOURCE_DC5_VLINE0; 46 case DCN_1_0__SRCID__OTG6_VERTICAL_INTERRUPT0_CONTROL: 47 return DC_IRQ_SOURCE_DC6_VLINE0; 48 case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: 49 return DC_IRQ_SOURCE_PFLIP1; 50 case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: 51 return DC_IRQ_SOURCE_PFLIP2; 52 case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT: 53 return DC_IRQ_SOURCE_PFLIP3; 54 case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT: 55 return DC_IRQ_SOURCE_PFLIP4; 56 case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT: 57 return DC_IRQ_SOURCE_PFLIP5; 58 case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT: 59 return DC_IRQ_SOURCE_PFLIP6; 60 case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 61 return DC_IRQ_SOURCE_VUPDATE1; 62 case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 63 return DC_IRQ_SOURCE_VUPDATE2; 64 case DCN_1_0__SRCID__OTG2_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 65 return DC_IRQ_SOURCE_VUPDATE3; 66 case DCN_1_0__SRCID__OTG3_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 67 return DC_IRQ_SOURCE_VUPDATE4; 68 case DCN_1_0__SRCID__OTG4_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 69 return DC_IRQ_SOURCE_VUPDATE5; 70 case DCN_1_0__SRCID__OTG5_IHC_V_UPDATE_NO_LOCK_INTERRUPT: 71 return DC_IRQ_SOURCE_VUPDATE6; 72 case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT: 73 return DC_IRQ_SOURCE_DMCUB_OUTBOX; 74 75 case DCN_1_0__SRCID__DC_HPD1_INT: 76 /* generic src_id for all HPD and HPDRX interrupts */ 77 switch (ext_id) { 78 case DCN_1_0__CTXID__DC_HPD1_INT: 79 return DC_IRQ_SOURCE_HPD1; 80 case DCN_1_0__CTXID__DC_HPD2_INT: 81 return DC_IRQ_SOURCE_HPD2; 82 case DCN_1_0__CTXID__DC_HPD3_INT: 83 return DC_IRQ_SOURCE_HPD3; 84 case DCN_1_0__CTXID__DC_HPD4_INT: 85 return DC_IRQ_SOURCE_HPD4; 86 case DCN_1_0__CTXID__DC_HPD5_INT: 87 return DC_IRQ_SOURCE_HPD5; 88 case DCN_1_0__CTXID__DC_HPD6_INT: 89 return DC_IRQ_SOURCE_HPD6; 90 case DCN_1_0__CTXID__DC_HPD1_RX_INT: 91 return DC_IRQ_SOURCE_HPD1RX; 92 case DCN_1_0__CTXID__DC_HPD2_RX_INT: 93 return DC_IRQ_SOURCE_HPD2RX; 94 case DCN_1_0__CTXID__DC_HPD3_RX_INT: 95 return DC_IRQ_SOURCE_HPD3RX; 96 case DCN_1_0__CTXID__DC_HPD4_RX_INT: 97 return DC_IRQ_SOURCE_HPD4RX; 98 case DCN_1_0__CTXID__DC_HPD5_RX_INT: 99 return DC_IRQ_SOURCE_HPD5RX; 100 case DCN_1_0__CTXID__DC_HPD6_RX_INT: 101 return DC_IRQ_SOURCE_HPD6RX; 102 default: 103 return DC_IRQ_SOURCE_INVALID; 104 } 105 break; 106 107 default: 108 return DC_IRQ_SOURCE_INVALID; 109 } 110} 111 112static struct irq_source_info_funcs hpd_irq_info_funcs = { 113 .set = NULL, 114 .ack = hpd0_ack 115}; 116 117static struct irq_source_info_funcs hpd_rx_irq_info_funcs = { 118 .set = NULL, 119 .ack = NULL 120}; 121 122static struct irq_source_info_funcs pflip_irq_info_funcs = { 123 .set = NULL, 124 .ack = NULL 125}; 126 127static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { 128 .set = NULL, 129 .ack = NULL 130}; 131 132static struct irq_source_info_funcs vblank_irq_info_funcs = { 133 .set = NULL, 134 .ack = NULL 135}; 136 137static struct irq_source_info_funcs outbox_irq_info_funcs = { 138 .set = NULL, 139 .ack = NULL 140}; 141 142static struct irq_source_info_funcs vline0_irq_info_funcs = { 143 .set = NULL, 144 .ack = NULL 145}; 146 147static struct irq_source_info_funcs vline1_irq_info_funcs = { 148 .set = NULL, 149 .ack = NULL 150}; 151 152static struct irq_source_info_funcs vline2_irq_info_funcs = { 153 .set = NULL, 154 .ack = NULL 155}; 156 157#undef BASE_INNER 158#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg 159 160/* compile time expand base address. */ 161#define BASE(seg) \ 162 BASE_INNER(seg) 163 164#define SRI(reg_name, block, id)\ 165 BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ 166 reg ## block ## id ## _ ## reg_name 167 168#define SRI_DMUB(reg_name)\ 169 BASE(reg ## reg_name ## _BASE_IDX) + \ 170 reg ## reg_name 171 172#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ 173 .enable_reg = SRI(reg1, block, reg_num),\ 174 .enable_mask = \ 175 block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ 176 .enable_value = {\ 177 block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ 178 ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ 179 },\ 180 .ack_reg = SRI(reg2, block, reg_num),\ 181 .ack_mask = \ 182 block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ 183 .ack_value = \ 184 block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ 185 186#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ 187 .enable_reg = SRI_DMUB(reg1),\ 188 .enable_mask = \ 189 reg1 ## __ ## mask1 ## _MASK,\ 190 .enable_value = {\ 191 reg1 ## __ ## mask1 ## _MASK,\ 192 ~reg1 ## __ ## mask1 ## _MASK \ 193 },\ 194 .ack_reg = SRI_DMUB(reg2),\ 195 .ack_mask = \ 196 reg2 ## __ ## mask2 ## _MASK,\ 197 .ack_value = \ 198 reg2 ## __ ## mask2 ## _MASK \ 199 200#define hpd_int_entry(reg_num)\ 201 [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ 202 IRQ_REG_ENTRY(HPD, reg_num,\ 203 DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ 204 DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ 205 .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ 206 .funcs = &hpd_irq_info_funcs\ 207 } 208 209#define hpd_rx_int_entry(reg_num)\ 210 [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ 211 IRQ_REG_ENTRY(HPD, reg_num,\ 212 DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ 213 DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ 214 .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ 215 .funcs = &hpd_rx_irq_info_funcs\ 216 } 217#define pflip_int_entry(reg_num)\ 218 [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ 219 IRQ_REG_ENTRY(HUBPREQ, reg_num,\ 220 DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ 221 DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ 222 .funcs = &pflip_irq_info_funcs\ 223 } 224 225#define vblank_int_entry(reg_num)\ 226 [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ 227 IRQ_REG_ENTRY(OTG, reg_num,\ 228 OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ 229 OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ 230 .funcs = &vblank_irq_info_funcs\ 231 } 232/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic 233 * of DCE's DC_IRQ_SOURCE_VUPDATEx. 234 */ 235#define vupdate_no_lock_int_entry(reg_num)\ 236 [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ 237 IRQ_REG_ENTRY(OTG, reg_num,\ 238 OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\ 239 OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\ 240 .funcs = &vupdate_no_lock_irq_info_funcs\ 241 } 242 243#define vline0_int_entry(reg_num)\ 244 [DC_IRQ_SOURCE_DC1_VLINE0 + reg_num] = {\ 245 IRQ_REG_ENTRY(OTG, reg_num,\ 246 OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE,\ 247 OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_CLEAR),\ 248 .funcs = &vline0_irq_info_funcs\ 249 } 250#define vline1_int_entry(reg_num)\ 251 [DC_IRQ_SOURCE_DC1_VLINE1 + reg_num] = {\ 252 IRQ_REG_ENTRY(OTG, reg_num,\ 253 OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE,\ 254 OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_CLEAR),\ 255 .funcs = &vline1_irq_info_funcs\ 256 } 257#define vline2_int_entry(reg_num)\ 258 [DC_IRQ_SOURCE_DC1_VLINE2 + reg_num] = {\ 259 IRQ_REG_ENTRY(OTG, reg_num,\ 260 OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE,\ 261 OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_CLEAR),\ 262 .funcs = &vline2_irq_info_funcs\ 263 } 264#define dmub_outbox_int_entry()\ 265 [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\ 266 IRQ_REG_ENTRY_DMUB(\ 267 DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\ 268 DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\ 269 .funcs = &outbox_irq_info_funcs\ 270 } 271 272#define dummy_irq_entry() \ 273 {\ 274 .funcs = &dummy_irq_info_funcs\ 275 } 276 277#define i2c_int_entry(reg_num) \ 278 [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() 279 280#define dp_sink_int_entry(reg_num) \ 281 [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() 282 283#define gpio_pad_int_entry(reg_num) \ 284 [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() 285 286#define dc_underflow_int_entry(reg_num) \ 287 [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() 288 289static struct irq_source_info_funcs dummy_irq_info_funcs = { 290 .set = dal_irq_service_dummy_set, 291 .ack = dal_irq_service_dummy_ack 292}; 293 294static const struct irq_source_info 295irq_source_info_dcn401[DAL_IRQ_SOURCES_NUMBER] = { 296 [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), 297 hpd_int_entry(0), 298 hpd_int_entry(1), 299 hpd_int_entry(2), 300 hpd_int_entry(3), 301 hpd_rx_int_entry(0), 302 hpd_rx_int_entry(1), 303 hpd_rx_int_entry(2), 304 hpd_rx_int_entry(3), 305 i2c_int_entry(1), 306 i2c_int_entry(2), 307 i2c_int_entry(3), 308 i2c_int_entry(4), 309 i2c_int_entry(5), 310 i2c_int_entry(6), 311 dp_sink_int_entry(1), 312 dp_sink_int_entry(2), 313 dp_sink_int_entry(3), 314 dp_sink_int_entry(4), 315 dp_sink_int_entry(5), 316 dp_sink_int_entry(6), 317 [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), 318 pflip_int_entry(0), 319 pflip_int_entry(1), 320 pflip_int_entry(2), 321 pflip_int_entry(3), 322 [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), 323 [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), 324 [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), 325 gpio_pad_int_entry(0), 326 gpio_pad_int_entry(1), 327 gpio_pad_int_entry(2), 328 gpio_pad_int_entry(3), 329 gpio_pad_int_entry(4), 330 gpio_pad_int_entry(5), 331 gpio_pad_int_entry(6), 332 gpio_pad_int_entry(7), 333 gpio_pad_int_entry(8), 334 gpio_pad_int_entry(9), 335 gpio_pad_int_entry(10), 336 gpio_pad_int_entry(11), 337 gpio_pad_int_entry(12), 338 gpio_pad_int_entry(13), 339 gpio_pad_int_entry(14), 340 gpio_pad_int_entry(15), 341 gpio_pad_int_entry(16), 342 gpio_pad_int_entry(17), 343 gpio_pad_int_entry(18), 344 gpio_pad_int_entry(19), 345 gpio_pad_int_entry(20), 346 gpio_pad_int_entry(21), 347 gpio_pad_int_entry(22), 348 gpio_pad_int_entry(23), 349 gpio_pad_int_entry(24), 350 gpio_pad_int_entry(25), 351 gpio_pad_int_entry(26), 352 gpio_pad_int_entry(27), 353 gpio_pad_int_entry(28), 354 gpio_pad_int_entry(29), 355 gpio_pad_int_entry(30), 356 dc_underflow_int_entry(1), 357 dc_underflow_int_entry(2), 358 dc_underflow_int_entry(3), 359 dc_underflow_int_entry(4), 360 dc_underflow_int_entry(5), 361 dc_underflow_int_entry(6), 362 [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), 363 [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), 364 vblank_int_entry(0), 365 vblank_int_entry(1), 366 vblank_int_entry(2), 367 vblank_int_entry(3), 368 [DC_IRQ_SOURCE_DC5_VLINE1] = dummy_irq_entry(), 369 [DC_IRQ_SOURCE_DC6_VLINE1] = dummy_irq_entry(), 370 dmub_outbox_int_entry(), 371 vupdate_no_lock_int_entry(0), 372 vupdate_no_lock_int_entry(1), 373 vupdate_no_lock_int_entry(2), 374 vupdate_no_lock_int_entry(3), 375 vline0_int_entry(0), 376 vline0_int_entry(1), 377 vline0_int_entry(2), 378 vline0_int_entry(3), 379 vline1_int_entry(0), 380 vline1_int_entry(1), 381 vline1_int_entry(2), 382 vline1_int_entry(3), 383 vline2_int_entry(0), 384 vline2_int_entry(1), 385 vline2_int_entry(2), 386 vline2_int_entry(3), 387}; 388 389static const struct irq_service_funcs irq_service_funcs_dcn401 = { 390 .to_dal_irq_source = to_dal_irq_source_dcn401 391}; 392 393static void dcn401_irq_construct( 394 struct irq_service *irq_service, 395 struct irq_service_init_data *init_data) 396{ 397 dal_irq_service_construct(irq_service, init_data); 398 399 irq_service->info = irq_source_info_dcn401; 400 irq_service->funcs = &irq_service_funcs_dcn401; 401} 402 403struct irq_service *dal_irq_service_dcn401_create( 404 struct irq_service_init_data *init_data) 405{ 406 struct irq_service *irq_service = kzalloc(sizeof(*irq_service), 407 GFP_KERNEL); 408 409 if (!irq_service) 410 return NULL; 411 412 dcn401_irq_construct(irq_service, init_data); 413 return irq_service; 414}
~/
Read-only file preview.