]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/gpu/drm/tidss/tidss_irq.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
4 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
7 #include <drm/drm_print.h>
9 #include "tidss_crtc.h"
10 #include "tidss_dispc.h"
11 #include "tidss_drv.h"
12 #include "tidss_irq.h"
13 #include "tidss_plane.h"
15 /* call with wait_lock and dispc runtime held */
16 static void tidss_irq_update(struct tidss_device
*tidss
)
18 assert_spin_locked(&tidss
->wait_lock
);
20 dispc_set_irqenable(tidss
->dispc
, tidss
->irq_mask
);
23 void tidss_irq_enable_vblank(struct drm_crtc
*crtc
)
25 struct drm_device
*ddev
= crtc
->dev
;
26 struct tidss_device
*tidss
= to_tidss(ddev
);
27 struct tidss_crtc
*tcrtc
= to_tidss_crtc(crtc
);
28 u32 hw_videoport
= tcrtc
->hw_videoport
;
31 spin_lock_irqsave(&tidss
->wait_lock
, flags
);
32 tidss
->irq_mask
|= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport
) |
33 DSS_IRQ_VP_VSYNC_ODD(hw_videoport
);
34 tidss_irq_update(tidss
);
35 spin_unlock_irqrestore(&tidss
->wait_lock
, flags
);
38 void tidss_irq_disable_vblank(struct drm_crtc
*crtc
)
40 struct drm_device
*ddev
= crtc
->dev
;
41 struct tidss_device
*tidss
= to_tidss(ddev
);
42 struct tidss_crtc
*tcrtc
= to_tidss_crtc(crtc
);
43 u32 hw_videoport
= tcrtc
->hw_videoport
;
46 spin_lock_irqsave(&tidss
->wait_lock
, flags
);
47 tidss
->irq_mask
&= ~(DSS_IRQ_VP_VSYNC_EVEN(hw_videoport
) |
48 DSS_IRQ_VP_VSYNC_ODD(hw_videoport
));
49 tidss_irq_update(tidss
);
50 spin_unlock_irqrestore(&tidss
->wait_lock
, flags
);
53 irqreturn_t
tidss_irq_handler(int irq
, void *arg
)
55 struct drm_device
*ddev
= (struct drm_device
*)arg
;
56 struct tidss_device
*tidss
= to_tidss(ddev
);
58 dispc_irq_t irqstatus
;
60 if (WARN_ON(!ddev
->irq_enabled
))
63 irqstatus
= dispc_read_and_clear_irqstatus(tidss
->dispc
);
65 for (id
= 0; id
< tidss
->num_crtcs
; id
++) {
66 struct drm_crtc
*crtc
= tidss
->crtcs
[id
];
67 struct tidss_crtc
*tcrtc
= to_tidss_crtc(crtc
);
68 u32 hw_videoport
= tcrtc
->hw_videoport
;
70 if (irqstatus
& (DSS_IRQ_VP_VSYNC_EVEN(hw_videoport
) |
71 DSS_IRQ_VP_VSYNC_ODD(hw_videoport
)))
72 tidss_crtc_vblank_irq(crtc
);
74 if (irqstatus
& (DSS_IRQ_VP_FRAME_DONE(hw_videoport
)))
75 tidss_crtc_framedone_irq(crtc
);
77 if (irqstatus
& DSS_IRQ_VP_SYNC_LOST(hw_videoport
))
78 tidss_crtc_error_irq(crtc
, irqstatus
);
81 if (irqstatus
& DSS_IRQ_DEVICE_OCP_ERR
)
82 dev_err_ratelimited(tidss
->dev
, "OCP error\n");
87 void tidss_irq_resume(struct tidss_device
*tidss
)
91 spin_lock_irqsave(&tidss
->wait_lock
, flags
);
92 tidss_irq_update(tidss
);
93 spin_unlock_irqrestore(&tidss
->wait_lock
, flags
);
96 void tidss_irq_preinstall(struct drm_device
*ddev
)
98 struct tidss_device
*tidss
= to_tidss(ddev
);
100 spin_lock_init(&tidss
->wait_lock
);
102 tidss_runtime_get(tidss
);
104 dispc_set_irqenable(tidss
->dispc
, 0);
105 dispc_read_and_clear_irqstatus(tidss
->dispc
);
107 tidss_runtime_put(tidss
);
110 int tidss_irq_postinstall(struct drm_device
*ddev
)
112 struct tidss_device
*tidss
= to_tidss(ddev
);
116 tidss_runtime_get(tidss
);
118 spin_lock_irqsave(&tidss
->wait_lock
, flags
);
120 tidss
->irq_mask
= DSS_IRQ_DEVICE_OCP_ERR
;
122 for (i
= 0; i
< tidss
->num_crtcs
; ++i
) {
123 struct tidss_crtc
*tcrtc
= to_tidss_crtc(tidss
->crtcs
[i
]);
125 tidss
->irq_mask
|= DSS_IRQ_VP_SYNC_LOST(tcrtc
->hw_videoport
);
127 tidss
->irq_mask
|= DSS_IRQ_VP_FRAME_DONE(tcrtc
->hw_videoport
);
130 tidss_irq_update(tidss
);
132 spin_unlock_irqrestore(&tidss
->wait_lock
, flags
);
134 tidss_runtime_put(tidss
);
139 void tidss_irq_uninstall(struct drm_device
*ddev
)
141 struct tidss_device
*tidss
= to_tidss(ddev
);
143 tidss_runtime_get(tidss
);
144 dispc_set_irqenable(tidss
->dispc
, 0);
145 tidss_runtime_put(tidss
);