File Index
Files and directories
Sign in
FILE

irq_service_dcn351.c

File preview with syntax highlighting.

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