irq_service_dce110.c revision 1.1
1198090Srdivacky/* 2198090Srdivacky * Copyright 2012-15 Advanced Micro Devices, Inc. 3198090Srdivacky * 4198090Srdivacky * Permission is hereby granted, free of charge, to any person obtaining a 5198090Srdivacky * copy of this software and associated documentation files (the "Software"), 6198090Srdivacky * to deal in the Software without restriction, including without limitation 7198090Srdivacky * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8198090Srdivacky * and/or sell copies of the Software, and to permit persons to whom the 9198090Srdivacky * Software is furnished to do so, subject to the following conditions: 10198090Srdivacky * 11198090Srdivacky * The above copyright notice and this permission notice shall be included in 12198090Srdivacky * all copies or substantial portions of the Software. 13198090Srdivacky * 14198090Srdivacky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15198090Srdivacky * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16198090Srdivacky * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17288943Sdim * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18234353Sdim * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19249423Sdim * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20234353Sdim * OTHER DEALINGS IN THE SOFTWARE. 21198090Srdivacky * 22198090Srdivacky * Authors: AMD 23234353Sdim * 24234353Sdim */ 25208599Srdivacky 26208599Srdivacky#include "dm_services.h" 27234353Sdim 28234353Sdim#include "include/logger_interface.h" 29234353Sdim 30234353Sdim#include "irq_service_dce110.h" 31198396Srdivacky 32261991Sdim#include "dce/dce_11_0_d.h" 33261991Sdim#include "dce/dce_11_0_sh_mask.h" 34261991Sdim 35261991Sdim#include "ivsrcid/ivsrcid_vislands30.h" 36198090Srdivacky 37198090Srdivacky#include "dc.h" 38198090Srdivacky#include "core_types.h" 39208599Srdivacky#define DC_LOGGER \ 40207618Srdivacky irq_service->ctx->logger 41207618Srdivacky 42261991Sdimstatic bool hpd_ack(struct irq_service *irq_service, 43261991Sdim const struct irq_source_info *info) 44207618Srdivacky{ 45198090Srdivacky uint32_t addr = info->status_reg; 46198396Srdivacky uint32_t value = dm_read_reg(irq_service->ctx, addr); 47212904Sdim uint32_t current_status = get_reg_field_value(value, 48226633Sdim DC_HPD_INT_STATUS, 49198396Srdivacky DC_HPD_SENSE_DELAYED); 50261991Sdim 51212904Sdim dal_irq_service_ack_generic(irq_service, info); 52212904Sdim 53261991Sdim value = dm_read_reg(irq_service->ctx, info->enable_reg); 54261991Sdim 55198090Srdivacky set_reg_field_value(value, current_status ? 0 : 1, 56208599Srdivacky DC_HPD_INT_CONTROL, 57198090Srdivacky DC_HPD_INT_POLARITY); 58261991Sdim 59198090Srdivacky dm_write_reg(irq_service->ctx, info->enable_reg, value); 60276479Sdim 61198090Srdivacky return true; 62198396Srdivacky} 63261991Sdim 64261991Sdimstatic const struct irq_source_info_funcs hpd_irq_info_funcs = { 65261991Sdim .set = NULL, 66261991Sdim .ack = hpd_ack 67226633Sdim}; 68198396Srdivacky 69261991Sdimstatic const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { 70261991Sdim .set = NULL, 71198090Srdivacky .ack = NULL 72198090Srdivacky}; 73261991Sdim 74261991Sdimstatic const struct irq_source_info_funcs pflip_irq_info_funcs = { 75198090Srdivacky .set = NULL, 76198396Srdivacky .ack = NULL 77261991Sdim}; 78261991Sdim 79198090Srdivackystatic const struct irq_source_info_funcs vblank_irq_info_funcs = { 80198396Srdivacky .set = dce110_vblank_set, 81261991Sdim .ack = NULL 82261991Sdim}; 83198090Srdivacky 84261991Sdim#define hpd_int_entry(reg_num)\ 85261991Sdim [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ 86261991Sdim .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ 87198090Srdivacky .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ 88261991Sdim .enable_value = {\ 89198090Srdivacky DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ 90198090Srdivacky ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ 91198090Srdivacky },\ 92198090Srdivacky .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ 93198090Srdivacky .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ 94261991Sdim .ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ 95198090Srdivacky .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ 96198090Srdivacky .funcs = &hpd_irq_info_funcs\ 97198090Srdivacky } 98198090Srdivacky 99198090Srdivacky#define hpd_rx_int_entry(reg_num)\ 100198090Srdivacky [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ 101198090Srdivacky .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ 102198396Srdivacky .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ 103261991Sdim .enable_value = {\ 104261991Sdim DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ 105261991Sdim ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ 106261991Sdim .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ 107261991Sdim .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ 108261991Sdim .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ 109261991Sdim .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ 110198090Srdivacky .funcs = &hpd_rx_irq_info_funcs\ 111198396Srdivacky } 112261991Sdim#define pflip_int_entry(reg_num)\ 113261991Sdim [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ 114261991Sdim .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ 115261991Sdim .enable_mask =\ 116212904Sdim GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ 117212904Sdim .enable_value = {\ 118212904Sdim GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ 119198090Srdivacky ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ 120198090Srdivacky .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ 121207618Srdivacky .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ 122288943Sdim .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ 123288943Sdim .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ 124198090Srdivacky .funcs = &pflip_irq_info_funcs\ 125261991Sdim } 126261991Sdim 127261991Sdim#define vupdate_int_entry(reg_num)\ 128261991Sdim [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ 129218893Sdim .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ 130218893Sdim .enable_mask =\ 131218893Sdim CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ 132218893Sdim .enable_value = {\ 133218893Sdim CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ 134218893Sdim ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ 135218893Sdim .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ 136218893Sdim .ack_mask =\ 137276479Sdim CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ 138218893Sdim .ack_value =\ 139288943Sdim CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ 140224145Sdim .funcs = &vblank_irq_info_funcs\ 141218893Sdim } 142276479Sdim 143261991Sdim#define vblank_int_entry(reg_num)\ 144261991Sdim [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ 145261991Sdim .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ 146261991Sdim .enable_mask =\ 147261991Sdim CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ 148218893Sdim .enable_value = {\ 149276479Sdim CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ 150261991Sdim ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ 151261991Sdim .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ 152261991Sdim .ack_mask =\ 153261991Sdim CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ 154218893Sdim .ack_value =\ 155234353Sdim CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ 156276479Sdim .funcs = &vblank_irq_info_funcs,\ 157261991Sdim .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ 158261991Sdim } 159218893Sdim 160218893Sdim#define dummy_irq_entry() \ 161276479Sdim {\ 162261991Sdim .funcs = &dummy_irq_info_funcs\ 163261991Sdim } 164218893Sdim 165218893Sdim#define i2c_int_entry(reg_num) \ 166198090Srdivacky [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() 167261991Sdim 168218893Sdim#define dp_sink_int_entry(reg_num) \ 169218893Sdim [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() 170218893Sdim 171261991Sdim#define gpio_pad_int_entry(reg_num) \ 172224145Sdim [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() 173224145Sdim 174218893Sdim#define dc_underflow_int_entry(reg_num) \ 175218893Sdim [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() 176198090Srdivacky 177198090Srdivackybool dal_irq_service_dummy_set(struct irq_service *irq_service, 178198090Srdivacky const struct irq_source_info *info, 179 bool enable) 180{ 181 DC_LOG_ERROR("%s: called for non-implemented irq source\n", 182 __func__); 183 return false; 184} 185 186bool dal_irq_service_dummy_ack(struct irq_service *irq_service, 187 const struct irq_source_info *info) 188{ 189 DC_LOG_ERROR("%s: called for non-implemented irq source\n", 190 __func__); 191 return false; 192} 193 194 195bool dce110_vblank_set(struct irq_service *irq_service, 196 const struct irq_source_info *info, 197 bool enable) 198{ 199 struct dc_context *dc_ctx = irq_service->ctx; 200 struct dc *core_dc = irq_service->ctx->dc; 201 enum dc_irq_source dal_irq_src = 202 dc_interrupt_to_irq_source(irq_service->ctx->dc, 203 info->src_id, 204 info->ext_id); 205 uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; 206 207 struct timing_generator *tg = 208 core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; 209 210 if (enable) { 211 if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) { 212 DC_ERROR("Failed to get VBLANK!\n"); 213 return false; 214 } 215 } 216 217 dal_irq_service_set_generic(irq_service, info, enable); 218 return true; 219} 220 221static const struct irq_source_info_funcs dummy_irq_info_funcs = { 222 .set = dal_irq_service_dummy_set, 223 .ack = dal_irq_service_dummy_ack 224}; 225 226static const struct irq_source_info 227irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { 228 [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), 229 hpd_int_entry(0), 230 hpd_int_entry(1), 231 hpd_int_entry(2), 232 hpd_int_entry(3), 233 hpd_int_entry(4), 234 hpd_int_entry(5), 235 hpd_rx_int_entry(0), 236 hpd_rx_int_entry(1), 237 hpd_rx_int_entry(2), 238 hpd_rx_int_entry(3), 239 hpd_rx_int_entry(4), 240 hpd_rx_int_entry(5), 241 i2c_int_entry(1), 242 i2c_int_entry(2), 243 i2c_int_entry(3), 244 i2c_int_entry(4), 245 i2c_int_entry(5), 246 i2c_int_entry(6), 247 dp_sink_int_entry(1), 248 dp_sink_int_entry(2), 249 dp_sink_int_entry(3), 250 dp_sink_int_entry(4), 251 dp_sink_int_entry(5), 252 dp_sink_int_entry(6), 253 [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), 254 pflip_int_entry(0), 255 pflip_int_entry(1), 256 pflip_int_entry(2), 257 pflip_int_entry(3), 258 pflip_int_entry(4), 259 pflip_int_entry(5), 260 [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), 261 gpio_pad_int_entry(0), 262 gpio_pad_int_entry(1), 263 gpio_pad_int_entry(2), 264 gpio_pad_int_entry(3), 265 gpio_pad_int_entry(4), 266 gpio_pad_int_entry(5), 267 gpio_pad_int_entry(6), 268 gpio_pad_int_entry(7), 269 gpio_pad_int_entry(8), 270 gpio_pad_int_entry(9), 271 gpio_pad_int_entry(10), 272 gpio_pad_int_entry(11), 273 gpio_pad_int_entry(12), 274 gpio_pad_int_entry(13), 275 gpio_pad_int_entry(14), 276 gpio_pad_int_entry(15), 277 gpio_pad_int_entry(16), 278 gpio_pad_int_entry(17), 279 gpio_pad_int_entry(18), 280 gpio_pad_int_entry(19), 281 gpio_pad_int_entry(20), 282 gpio_pad_int_entry(21), 283 gpio_pad_int_entry(22), 284 gpio_pad_int_entry(23), 285 gpio_pad_int_entry(24), 286 gpio_pad_int_entry(25), 287 gpio_pad_int_entry(26), 288 gpio_pad_int_entry(27), 289 gpio_pad_int_entry(28), 290 gpio_pad_int_entry(29), 291 gpio_pad_int_entry(30), 292 dc_underflow_int_entry(1), 293 dc_underflow_int_entry(2), 294 dc_underflow_int_entry(3), 295 dc_underflow_int_entry(4), 296 dc_underflow_int_entry(5), 297 dc_underflow_int_entry(6), 298 [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), 299 [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), 300 vupdate_int_entry(0), 301 vupdate_int_entry(1), 302 vupdate_int_entry(2), 303 vupdate_int_entry(3), 304 vupdate_int_entry(4), 305 vupdate_int_entry(5), 306 vblank_int_entry(0), 307 vblank_int_entry(1), 308 vblank_int_entry(2), 309 vblank_int_entry(3), 310 vblank_int_entry(4), 311 vblank_int_entry(5), 312 313}; 314 315enum dc_irq_source to_dal_irq_source_dce110( 316 struct irq_service *irq_service, 317 uint32_t src_id, 318 uint32_t ext_id) 319{ 320 switch (src_id) { 321 case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0: 322 return DC_IRQ_SOURCE_VBLANK1; 323 case VISLANDS30_IV_SRCID_D2_VERTICAL_INTERRUPT0: 324 return DC_IRQ_SOURCE_VBLANK2; 325 case VISLANDS30_IV_SRCID_D3_VERTICAL_INTERRUPT0: 326 return DC_IRQ_SOURCE_VBLANK3; 327 case VISLANDS30_IV_SRCID_D4_VERTICAL_INTERRUPT0: 328 return DC_IRQ_SOURCE_VBLANK4; 329 case VISLANDS30_IV_SRCID_D5_VERTICAL_INTERRUPT0: 330 return DC_IRQ_SOURCE_VBLANK5; 331 case VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0: 332 return DC_IRQ_SOURCE_VBLANK6; 333 case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: 334 return DC_IRQ_SOURCE_VUPDATE1; 335 case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: 336 return DC_IRQ_SOURCE_VUPDATE2; 337 case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT: 338 return DC_IRQ_SOURCE_VUPDATE3; 339 case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT: 340 return DC_IRQ_SOURCE_VUPDATE4; 341 case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT: 342 return DC_IRQ_SOURCE_VUPDATE5; 343 case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT: 344 return DC_IRQ_SOURCE_VUPDATE6; 345 case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP: 346 return DC_IRQ_SOURCE_PFLIP1; 347 case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP: 348 return DC_IRQ_SOURCE_PFLIP2; 349 case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP: 350 return DC_IRQ_SOURCE_PFLIP3; 351 case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP: 352 return DC_IRQ_SOURCE_PFLIP4; 353 case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP: 354 return DC_IRQ_SOURCE_PFLIP5; 355 case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP: 356 return DC_IRQ_SOURCE_PFLIP6; 357 358 case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A: 359 /* generic src_id for all HPD and HPDRX interrupts */ 360 switch (ext_id) { 361 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A: 362 return DC_IRQ_SOURCE_HPD1; 363 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B: 364 return DC_IRQ_SOURCE_HPD2; 365 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C: 366 return DC_IRQ_SOURCE_HPD3; 367 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D: 368 return DC_IRQ_SOURCE_HPD4; 369 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E: 370 return DC_IRQ_SOURCE_HPD5; 371 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F: 372 return DC_IRQ_SOURCE_HPD6; 373 case VISLANDS30_IV_EXTID_HPD_RX_A: 374 return DC_IRQ_SOURCE_HPD1RX; 375 case VISLANDS30_IV_EXTID_HPD_RX_B: 376 return DC_IRQ_SOURCE_HPD2RX; 377 case VISLANDS30_IV_EXTID_HPD_RX_C: 378 return DC_IRQ_SOURCE_HPD3RX; 379 case VISLANDS30_IV_EXTID_HPD_RX_D: 380 return DC_IRQ_SOURCE_HPD4RX; 381 case VISLANDS30_IV_EXTID_HPD_RX_E: 382 return DC_IRQ_SOURCE_HPD5RX; 383 case VISLANDS30_IV_EXTID_HPD_RX_F: 384 return DC_IRQ_SOURCE_HPD6RX; 385 default: 386 return DC_IRQ_SOURCE_INVALID; 387 } 388 break; 389 390 default: 391 return DC_IRQ_SOURCE_INVALID; 392 } 393} 394 395static const struct irq_service_funcs irq_service_funcs_dce110 = { 396 .to_dal_irq_source = to_dal_irq_source_dce110 397}; 398 399static void construct(struct irq_service *irq_service, 400 struct irq_service_init_data *init_data) 401{ 402 dal_irq_service_construct(irq_service, init_data); 403 404 irq_service->info = irq_source_info_dce110; 405 irq_service->funcs = &irq_service_funcs_dce110; 406} 407 408struct irq_service * 409dal_irq_service_dce110_create(struct irq_service_init_data *init_data) 410{ 411 struct irq_service *irq_service = kzalloc(sizeof(*irq_service), 412 GFP_KERNEL); 413 414 if (!irq_service) 415 return NULL; 416 417 construct(irq_service, init_data); 418 return irq_service; 419} 420