0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027
0028 #include "include/logger_interface.h"
0029
0030 #include "irq_service_dce110.h"
0031
0032 #include "dce/dce_11_0_d.h"
0033 #include "dce/dce_11_0_sh_mask.h"
0034
0035 #include "ivsrcid/ivsrcid_vislands30.h"
0036
0037 #include "dc.h"
0038 #include "core_types.h"
0039 #define DC_LOGGER \
0040 irq_service->ctx->logger
0041
0042 static bool hpd_ack(struct irq_service *irq_service,
0043 const struct irq_source_info *info)
0044 {
0045 uint32_t addr = info->status_reg;
0046 uint32_t value = dm_read_reg(irq_service->ctx, addr);
0047 uint32_t current_status = get_reg_field_value(value,
0048 DC_HPD_INT_STATUS,
0049 DC_HPD_SENSE_DELAYED);
0050
0051 dal_irq_service_ack_generic(irq_service, info);
0052
0053 value = dm_read_reg(irq_service->ctx, info->enable_reg);
0054
0055 set_reg_field_value(value, current_status ? 0 : 1,
0056 DC_HPD_INT_CONTROL,
0057 DC_HPD_INT_POLARITY);
0058
0059 dm_write_reg(irq_service->ctx, info->enable_reg, value);
0060
0061 return true;
0062 }
0063
0064 static const struct irq_source_info_funcs hpd_irq_info_funcs = {
0065 .set = NULL,
0066 .ack = hpd_ack
0067 };
0068
0069 static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = {
0070 .set = NULL,
0071 .ack = NULL
0072 };
0073
0074 static const struct irq_source_info_funcs pflip_irq_info_funcs = {
0075 .set = NULL,
0076 .ack = NULL
0077 };
0078
0079 static const struct irq_source_info_funcs vblank_irq_info_funcs = {
0080 .set = dce110_vblank_set,
0081 .ack = NULL
0082 };
0083
0084 static const struct irq_source_info_funcs vupdate_irq_info_funcs = {
0085 .set = NULL,
0086 .ack = NULL
0087 };
0088
0089 #define hpd_int_entry(reg_num)\
0090 [DC_IRQ_SOURCE_HPD1 + reg_num] = {\
0091 .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
0092 .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
0093 .enable_value = {\
0094 DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
0095 ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
0096 },\
0097 .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
0098 .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
0099 .ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
0100 .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
0101 .funcs = &hpd_irq_info_funcs\
0102 }
0103
0104 #define hpd_rx_int_entry(reg_num)\
0105 [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\
0106 .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
0107 .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
0108 .enable_value = {\
0109 DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
0110 ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
0111 .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
0112 .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
0113 .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
0114 .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
0115 .funcs = &hpd_rx_irq_info_funcs\
0116 }
0117 #define pflip_int_entry(reg_num)\
0118 [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\
0119 .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\
0120 .enable_mask =\
0121 GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
0122 .enable_value = {\
0123 GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
0124 ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
0125 .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
0126 .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
0127 .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
0128 .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\
0129 .funcs = &pflip_irq_info_funcs\
0130 }
0131
0132 #define vupdate_int_entry(reg_num)\
0133 [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
0134 .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\
0135 .enable_mask =\
0136 CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
0137 .enable_value = {\
0138 CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
0139 ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
0140 .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
0141 .ack_mask =\
0142 CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
0143 .ack_value =\
0144 CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
0145 .funcs = &vupdate_irq_info_funcs\
0146 }
0147
0148 #define vblank_int_entry(reg_num)\
0149 [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
0150 .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
0151 .enable_mask =\
0152 CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
0153 .enable_value = {\
0154 CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
0155 ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
0156 .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
0157 .ack_mask =\
0158 CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
0159 .ack_value =\
0160 CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
0161 .funcs = &vblank_irq_info_funcs,\
0162 .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\
0163 }
0164
0165 #define dummy_irq_entry() \
0166 {\
0167 .funcs = &dummy_irq_info_funcs\
0168 }
0169
0170 #define i2c_int_entry(reg_num) \
0171 [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry()
0172
0173 #define dp_sink_int_entry(reg_num) \
0174 [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry()
0175
0176 #define gpio_pad_int_entry(reg_num) \
0177 [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry()
0178
0179 #define dc_underflow_int_entry(reg_num) \
0180 [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
0181
0182 bool dal_irq_service_dummy_set(struct irq_service *irq_service,
0183 const struct irq_source_info *info,
0184 bool enable)
0185 {
0186 DC_LOG_ERROR("%s: called for non-implemented irq source, src_id=%u, ext_id=%u\n",
0187 __func__, info->src_id, info->ext_id);
0188
0189 return false;
0190 }
0191
0192 bool dal_irq_service_dummy_ack(struct irq_service *irq_service,
0193 const struct irq_source_info *info)
0194 {
0195 DC_LOG_ERROR("%s: called for non-implemented irq source, src_id=%u, ext_id=%u\n",
0196 __func__, info->src_id, info->ext_id);
0197
0198 return false;
0199 }
0200
0201
0202 bool dce110_vblank_set(struct irq_service *irq_service,
0203 const struct irq_source_info *info,
0204 bool enable)
0205 {
0206 struct dc_context *dc_ctx = irq_service->ctx;
0207 struct dc *dc = irq_service->ctx->dc;
0208 enum dc_irq_source dal_irq_src =
0209 dc_interrupt_to_irq_source(irq_service->ctx->dc,
0210 info->src_id,
0211 info->ext_id);
0212 uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK;
0213
0214 struct timing_generator *tg =
0215 dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg;
0216
0217 if (enable) {
0218 if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) {
0219 DC_ERROR("Failed to get VBLANK!\n");
0220 return false;
0221 }
0222 }
0223
0224 dal_irq_service_set_generic(irq_service, info, enable);
0225 return true;
0226 }
0227
0228 static const struct irq_source_info_funcs dummy_irq_info_funcs = {
0229 .set = dal_irq_service_dummy_set,
0230 .ack = dal_irq_service_dummy_ack
0231 };
0232
0233 static const struct irq_source_info
0234 irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = {
0235 [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
0236 hpd_int_entry(0),
0237 hpd_int_entry(1),
0238 hpd_int_entry(2),
0239 hpd_int_entry(3),
0240 hpd_int_entry(4),
0241 hpd_int_entry(5),
0242 hpd_rx_int_entry(0),
0243 hpd_rx_int_entry(1),
0244 hpd_rx_int_entry(2),
0245 hpd_rx_int_entry(3),
0246 hpd_rx_int_entry(4),
0247 hpd_rx_int_entry(5),
0248 i2c_int_entry(1),
0249 i2c_int_entry(2),
0250 i2c_int_entry(3),
0251 i2c_int_entry(4),
0252 i2c_int_entry(5),
0253 i2c_int_entry(6),
0254 dp_sink_int_entry(1),
0255 dp_sink_int_entry(2),
0256 dp_sink_int_entry(3),
0257 dp_sink_int_entry(4),
0258 dp_sink_int_entry(5),
0259 dp_sink_int_entry(6),
0260 [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(),
0261 pflip_int_entry(0),
0262 pflip_int_entry(1),
0263 pflip_int_entry(2),
0264 pflip_int_entry(3),
0265 pflip_int_entry(4),
0266 pflip_int_entry(5),
0267 [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
0268 gpio_pad_int_entry(0),
0269 gpio_pad_int_entry(1),
0270 gpio_pad_int_entry(2),
0271 gpio_pad_int_entry(3),
0272 gpio_pad_int_entry(4),
0273 gpio_pad_int_entry(5),
0274 gpio_pad_int_entry(6),
0275 gpio_pad_int_entry(7),
0276 gpio_pad_int_entry(8),
0277 gpio_pad_int_entry(9),
0278 gpio_pad_int_entry(10),
0279 gpio_pad_int_entry(11),
0280 gpio_pad_int_entry(12),
0281 gpio_pad_int_entry(13),
0282 gpio_pad_int_entry(14),
0283 gpio_pad_int_entry(15),
0284 gpio_pad_int_entry(16),
0285 gpio_pad_int_entry(17),
0286 gpio_pad_int_entry(18),
0287 gpio_pad_int_entry(19),
0288 gpio_pad_int_entry(20),
0289 gpio_pad_int_entry(21),
0290 gpio_pad_int_entry(22),
0291 gpio_pad_int_entry(23),
0292 gpio_pad_int_entry(24),
0293 gpio_pad_int_entry(25),
0294 gpio_pad_int_entry(26),
0295 gpio_pad_int_entry(27),
0296 gpio_pad_int_entry(28),
0297 gpio_pad_int_entry(29),
0298 gpio_pad_int_entry(30),
0299 dc_underflow_int_entry(1),
0300 dc_underflow_int_entry(2),
0301 dc_underflow_int_entry(3),
0302 dc_underflow_int_entry(4),
0303 dc_underflow_int_entry(5),
0304 dc_underflow_int_entry(6),
0305 [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
0306 [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
0307 vupdate_int_entry(0),
0308 vupdate_int_entry(1),
0309 vupdate_int_entry(2),
0310 vupdate_int_entry(3),
0311 vupdate_int_entry(4),
0312 vupdate_int_entry(5),
0313 vblank_int_entry(0),
0314 vblank_int_entry(1),
0315 vblank_int_entry(2),
0316 vblank_int_entry(3),
0317 vblank_int_entry(4),
0318 vblank_int_entry(5),
0319
0320 };
0321
0322 enum dc_irq_source to_dal_irq_source_dce110(
0323 struct irq_service *irq_service,
0324 uint32_t src_id,
0325 uint32_t ext_id)
0326 {
0327 switch (src_id) {
0328 case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
0329 return DC_IRQ_SOURCE_VBLANK1;
0330 case VISLANDS30_IV_SRCID_D2_VERTICAL_INTERRUPT0:
0331 return DC_IRQ_SOURCE_VBLANK2;
0332 case VISLANDS30_IV_SRCID_D3_VERTICAL_INTERRUPT0:
0333 return DC_IRQ_SOURCE_VBLANK3;
0334 case VISLANDS30_IV_SRCID_D4_VERTICAL_INTERRUPT0:
0335 return DC_IRQ_SOURCE_VBLANK4;
0336 case VISLANDS30_IV_SRCID_D5_VERTICAL_INTERRUPT0:
0337 return DC_IRQ_SOURCE_VBLANK5;
0338 case VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0:
0339 return DC_IRQ_SOURCE_VBLANK6;
0340 case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
0341 return DC_IRQ_SOURCE_VUPDATE1;
0342 case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT:
0343 return DC_IRQ_SOURCE_VUPDATE2;
0344 case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT:
0345 return DC_IRQ_SOURCE_VUPDATE3;
0346 case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT:
0347 return DC_IRQ_SOURCE_VUPDATE4;
0348 case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT:
0349 return DC_IRQ_SOURCE_VUPDATE5;
0350 case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT:
0351 return DC_IRQ_SOURCE_VUPDATE6;
0352 case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP:
0353 return DC_IRQ_SOURCE_PFLIP1;
0354 case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP:
0355 return DC_IRQ_SOURCE_PFLIP2;
0356 case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP:
0357 return DC_IRQ_SOURCE_PFLIP3;
0358 case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP:
0359 return DC_IRQ_SOURCE_PFLIP4;
0360 case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP:
0361 return DC_IRQ_SOURCE_PFLIP5;
0362 case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP:
0363 return DC_IRQ_SOURCE_PFLIP6;
0364
0365 case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A:
0366
0367 switch (ext_id) {
0368 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A:
0369 return DC_IRQ_SOURCE_HPD1;
0370 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B:
0371 return DC_IRQ_SOURCE_HPD2;
0372 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C:
0373 return DC_IRQ_SOURCE_HPD3;
0374 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D:
0375 return DC_IRQ_SOURCE_HPD4;
0376 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E:
0377 return DC_IRQ_SOURCE_HPD5;
0378 case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F:
0379 return DC_IRQ_SOURCE_HPD6;
0380 case VISLANDS30_IV_EXTID_HPD_RX_A:
0381 return DC_IRQ_SOURCE_HPD1RX;
0382 case VISLANDS30_IV_EXTID_HPD_RX_B:
0383 return DC_IRQ_SOURCE_HPD2RX;
0384 case VISLANDS30_IV_EXTID_HPD_RX_C:
0385 return DC_IRQ_SOURCE_HPD3RX;
0386 case VISLANDS30_IV_EXTID_HPD_RX_D:
0387 return DC_IRQ_SOURCE_HPD4RX;
0388 case VISLANDS30_IV_EXTID_HPD_RX_E:
0389 return DC_IRQ_SOURCE_HPD5RX;
0390 case VISLANDS30_IV_EXTID_HPD_RX_F:
0391 return DC_IRQ_SOURCE_HPD6RX;
0392 default:
0393 return DC_IRQ_SOURCE_INVALID;
0394 }
0395 break;
0396
0397 default:
0398 return DC_IRQ_SOURCE_INVALID;
0399 }
0400 }
0401
0402 static const struct irq_service_funcs irq_service_funcs_dce110 = {
0403 .to_dal_irq_source = to_dal_irq_source_dce110
0404 };
0405
0406 static void dce110_irq_construct(struct irq_service *irq_service,
0407 struct irq_service_init_data *init_data)
0408 {
0409 dal_irq_service_construct(irq_service, init_data);
0410
0411 irq_service->info = irq_source_info_dce110;
0412 irq_service->funcs = &irq_service_funcs_dce110;
0413 }
0414
0415 struct irq_service *
0416 dal_irq_service_dce110_create(struct irq_service_init_data *init_data)
0417 {
0418 struct irq_service *irq_service = kzalloc(sizeof(*irq_service),
0419 GFP_KERNEL);
0420
0421 if (!irq_service)
0422 return NULL;
0423
0424 dce110_irq_construct(irq_service, init_data);
0425 return irq_service;
0426 }