File Index
Files and directories
Sign in
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 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.