1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright (C) 2023 Loongson Technology Corporation Limited |
4 | */ |
5 | |
6 | #include <drm/drm_vblank.h> |
7 | |
8 | #include "lsdc_irq.h" |
9 | |
10 | /* |
11 | * For the DC in LS7A2000, clearing interrupt status is achieved by |
12 | * write "1" to LSDC_INT_REG. |
13 | * |
14 | * For the DC in LS7A1000, clear interrupt status is achieved by write "0" |
15 | * to LSDC_INT_REG. |
16 | * |
17 | * Two different hardware engineers modify it as their will. |
18 | */ |
19 | |
20 | irqreturn_t ls7a2000_dc_irq_handler(int irq, void *arg) |
21 | { |
22 | struct drm_device *ddev = arg; |
23 | struct lsdc_device *ldev = to_lsdc(ddev); |
24 | u32 val; |
25 | |
26 | /* Read the interrupt status */ |
27 | val = lsdc_rreg32(ldev, LSDC_INT_REG); |
28 | if ((val & INT_STATUS_MASK) == 0) { |
29 | drm_warn(ddev, "no interrupt occurs\n" ); |
30 | return IRQ_NONE; |
31 | } |
32 | |
33 | ldev->irq_status = val; |
34 | |
35 | /* write "1" to clear the interrupt status */ |
36 | lsdc_wreg32(ldev, LSDC_INT_REG, val); |
37 | |
38 | if (ldev->irq_status & INT_CRTC0_VSYNC) |
39 | drm_handle_vblank(dev: ddev, pipe: 0); |
40 | |
41 | if (ldev->irq_status & INT_CRTC1_VSYNC) |
42 | drm_handle_vblank(dev: ddev, pipe: 1); |
43 | |
44 | return IRQ_HANDLED; |
45 | } |
46 | |
47 | /* For the DC in LS7A1000 and LS2K1000 */ |
48 | irqreturn_t ls7a1000_dc_irq_handler(int irq, void *arg) |
49 | { |
50 | struct drm_device *ddev = arg; |
51 | struct lsdc_device *ldev = to_lsdc(ddev); |
52 | u32 val; |
53 | |
54 | /* Read the interrupt status */ |
55 | val = lsdc_rreg32(ldev, LSDC_INT_REG); |
56 | if ((val & INT_STATUS_MASK) == 0) { |
57 | drm_warn(ddev, "no interrupt occurs\n" ); |
58 | return IRQ_NONE; |
59 | } |
60 | |
61 | ldev->irq_status = val; |
62 | |
63 | /* write "0" to clear the interrupt status */ |
64 | val &= ~(INT_CRTC0_VSYNC | INT_CRTC1_VSYNC); |
65 | lsdc_wreg32(ldev, LSDC_INT_REG, val); |
66 | |
67 | if (ldev->irq_status & INT_CRTC0_VSYNC) |
68 | drm_handle_vblank(dev: ddev, pipe: 0); |
69 | |
70 | if (ldev->irq_status & INT_CRTC1_VSYNC) |
71 | drm_handle_vblank(dev: ddev, pipe: 1); |
72 | |
73 | return IRQ_HANDLED; |
74 | } |
75 | |