File Index
Files and directories
Sign in
FILE

irq_service_dcn315.c

File preview with syntax highlighting.

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