1e559355aSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ad49f860SLiviu Dudau /*
3ad49f860SLiviu Dudau * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
4ad49f860SLiviu Dudau * Author: Liviu Dudau <Liviu.Dudau@arm.com>
5ad49f860SLiviu Dudau *
6ad49f860SLiviu Dudau * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
7ad49f860SLiviu Dudau * the difference between various versions of the hardware is being dealt with
8ad49f860SLiviu Dudau * in an attempt to provide to the rest of the driver code a unified view
9ad49f860SLiviu Dudau */
10ad49f860SLiviu Dudau
11c2e7f82dSMihail Atanassov #include <linux/clk.h>
12535d1b94SSam Ravnborg #include <linux/delay.h>
13ad49f860SLiviu Dudau #include <linux/types.h>
14ad49f860SLiviu Dudau #include <linux/io.h>
15535d1b94SSam Ravnborg
16ad49f860SLiviu Dudau #include <video/videomode.h>
17ad49f860SLiviu Dudau #include <video/display_timing.h>
18ad49f860SLiviu Dudau
19535d1b94SSam Ravnborg #include <drm/drm_fourcc.h>
20535d1b94SSam Ravnborg #include <drm/drm_vblank.h>
21535d1b94SSam Ravnborg #include <drm/drm_print.h>
22535d1b94SSam Ravnborg
23ad49f860SLiviu Dudau #include "malidp_drv.h"
24ad49f860SLiviu Dudau #include "malidp_hw.h"
258cbc5cafSBrian Starkey #include "malidp_mw.h"
26ad49f860SLiviu Dudau
271cb3cbe7SLiviu Dudau enum {
281cb3cbe7SLiviu Dudau MW_NOT_ENABLED = 0, /* SE writeback not enabled */
291cb3cbe7SLiviu Dudau MW_ONESHOT, /* SE in one-shot mode for writeback */
301cb3cbe7SLiviu Dudau MW_START, /* SE started writeback */
310735cfdfSLiviu Dudau MW_RESTART, /* SE will start another writeback after this one */
320735cfdfSLiviu Dudau MW_STOP, /* SE needs to stop after this writeback */
331cb3cbe7SLiviu Dudau };
341cb3cbe7SLiviu Dudau
356211b486SBrian Starkey static const struct malidp_format_id malidp500_de_formats[] = {
36ad49f860SLiviu Dudau /* fourcc, layers supporting the format, internal id */
3709368e32SLiviu Dudau { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 0 },
3809368e32SLiviu Dudau { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 1 },
39ad49f860SLiviu Dudau { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 2 },
40ad49f860SLiviu Dudau { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 3 },
4109368e32SLiviu Dudau { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 4 },
4209368e32SLiviu Dudau { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 5 },
43ad49f860SLiviu Dudau { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 6 },
44ad49f860SLiviu Dudau { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 7 },
45ad49f860SLiviu Dudau { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 8 },
46ad49f860SLiviu Dudau { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 9 },
47ad49f860SLiviu Dudau { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
48ad49f860SLiviu Dudau { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
49ad49f860SLiviu Dudau { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
50ad49f860SLiviu Dudau { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
5109368e32SLiviu Dudau { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
52ad49f860SLiviu Dudau { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
53ed893860SAyan Kumar Halder { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
54ed893860SAyan Kumar Halder /* These are supported with AFBC only */
55ed893860SAyan Kumar Halder { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
56ed893860SAyan Kumar Halder { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
57ed893860SAyan Kumar Halder { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
58ed893860SAyan Kumar Halder { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
59ad49f860SLiviu Dudau };
60ad49f860SLiviu Dudau
61ad49f860SLiviu Dudau #define MALIDP_ID(__group, __format) \
62ad49f860SLiviu Dudau ((((__group) & 0x7) << 3) | ((__format) & 0x7))
63ad49f860SLiviu Dudau
645e290226SAyan Kumar Halder #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
655e290226SAyan Kumar Halder
66ad49f860SLiviu Dudau #define MALIDP_COMMON_FORMATS \
67ad49f860SLiviu Dudau /* fourcc, layers supporting the format, internal id */ \
68a67bbbe2SBrian Starkey { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
69a67bbbe2SBrian Starkey { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
70a67bbbe2SBrian Starkey { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
71a67bbbe2SBrian Starkey { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
72ad49f860SLiviu Dudau { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
73ad49f860SLiviu Dudau { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
74ad49f860SLiviu Dudau { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
75ad49f860SLiviu Dudau { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
76a67bbbe2SBrian Starkey { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
77a67bbbe2SBrian Starkey { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
78a67bbbe2SBrian Starkey { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
79a67bbbe2SBrian Starkey { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
80a67bbbe2SBrian Starkey { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
81a67bbbe2SBrian Starkey { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
82ad49f860SLiviu Dudau { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
83ad49f860SLiviu Dudau { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
84ad49f860SLiviu Dudau { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
85ad49f860SLiviu Dudau { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
86ed893860SAyan Kumar Halder /* This is only supported with linear modifier */ \
87ed893860SAyan Kumar Halder { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
88ed893860SAyan Kumar Halder /* This is only supported with AFBC modifier */ \
89ed893860SAyan Kumar Halder { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
90ad49f860SLiviu Dudau { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
91ed893860SAyan Kumar Halder /* This is only supported with linear modifier */ \
92ad49f860SLiviu Dudau { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
93a67bbbe2SBrian Starkey { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
94ed893860SAyan Kumar Halder /* This is only supported with AFBC modifier */ \
95ed893860SAyan Kumar Halder { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
9655bc277dSAlexandru Gheorghe { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
97ed893860SAyan Kumar Halder /* This is only supported with linear modifier */ \
98ed893860SAyan Kumar Halder { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
99ed893860SAyan Kumar Halder /* This is only supported with AFBC modifier */ \
100ed893860SAyan Kumar Halder { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
101ed893860SAyan Kumar Halder { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
102ed893860SAyan Kumar Halder /* This is only supported with AFBC modifier */ \
103ed893860SAyan Kumar Halder { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
104ed893860SAyan Kumar Halder { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
105ad49f860SLiviu Dudau
1066211b486SBrian Starkey static const struct malidp_format_id malidp550_de_formats[] = {
107ad49f860SLiviu Dudau MALIDP_COMMON_FORMATS,
108ad49f860SLiviu Dudau };
109ad49f860SLiviu Dudau
11055bc277dSAlexandru Gheorghe static const struct malidp_format_id malidp650_de_formats[] = {
11155bc277dSAlexandru Gheorghe MALIDP_COMMON_FORMATS,
11255bc277dSAlexandru Gheorghe { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
11355bc277dSAlexandru Gheorghe };
11455bc277dSAlexandru Gheorghe
115ad49f860SLiviu Dudau static const struct malidp_layer malidp500_layers[] = {
1161f23a56aSJamie Fox /* id, base address, fb pointer address base, stride offset,
11766da13a5SLiviu Dudau * yuv2rgb matrix offset, mmu control register offset, rotation_features
1181f23a56aSJamie Fox */
1191f23a56aSJamie Fox { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
12054b4260aSAyan Kumar Halder MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
12154b4260aSAyan Kumar Halder MALIDP500_DE_LV_AD_CTRL },
1221f23a56aSJamie Fox { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
12354b4260aSAyan Kumar Halder MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
12454b4260aSAyan Kumar Halder MALIDP500_DE_LG1_AD_CTRL },
1251f23a56aSJamie Fox { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
12654b4260aSAyan Kumar Halder MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
12754b4260aSAyan Kumar Halder MALIDP500_DE_LG2_AD_CTRL },
128ad49f860SLiviu Dudau };
129ad49f860SLiviu Dudau
130ad49f860SLiviu Dudau static const struct malidp_layer malidp550_layers[] = {
1311f23a56aSJamie Fox /* id, base address, fb pointer address base, stride offset,
13266da13a5SLiviu Dudau * yuv2rgb matrix offset, mmu control register offset, rotation_features
1331f23a56aSJamie Fox */
1341f23a56aSJamie Fox { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
13554b4260aSAyan Kumar Halder MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
13654b4260aSAyan Kumar Halder MALIDP550_DE_LV1_AD_CTRL },
1371f23a56aSJamie Fox { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
13854b4260aSAyan Kumar Halder MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
13954b4260aSAyan Kumar Halder MALIDP550_DE_LG_AD_CTRL },
1401f23a56aSJamie Fox { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
14154b4260aSAyan Kumar Halder MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
14254b4260aSAyan Kumar Halder MALIDP550_DE_LV2_AD_CTRL },
1431f23a56aSJamie Fox { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
14454b4260aSAyan Kumar Halder MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
1451f23a56aSJamie Fox };
1461f23a56aSJamie Fox
1471f23a56aSJamie Fox static const struct malidp_layer malidp650_layers[] = {
1481f23a56aSJamie Fox /* id, base address, fb pointer address base, stride offset,
14966da13a5SLiviu Dudau * yuv2rgb matrix offset, mmu control register offset,
15066da13a5SLiviu Dudau * rotation_features
1511f23a56aSJamie Fox */
1521f23a56aSJamie Fox { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
1531f23a56aSJamie Fox MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
15454b4260aSAyan Kumar Halder MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
15554b4260aSAyan Kumar Halder MALIDP550_DE_LV1_AD_CTRL },
1561f23a56aSJamie Fox { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
15766da13a5SLiviu Dudau MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
15854b4260aSAyan Kumar Halder ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
1591f23a56aSJamie Fox { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
1601f23a56aSJamie Fox MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
16154b4260aSAyan Kumar Halder MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
16254b4260aSAyan Kumar Halder MALIDP550_DE_LV2_AD_CTRL },
1631f23a56aSJamie Fox { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
16466da13a5SLiviu Dudau MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
16554b4260aSAyan Kumar Halder ROTATE_NONE, 0 },
166ad49f860SLiviu Dudau };
167ad49f860SLiviu Dudau
1685e290226SAyan Kumar Halder const u64 malidp_format_modifiers[] = {
1695e290226SAyan Kumar Halder /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
1705e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
1715e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
1725e290226SAyan Kumar Halder
1735e290226SAyan Kumar Halder /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
1745e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
1755e290226SAyan Kumar Halder
1765e290226SAyan Kumar Halder /* All 8 or 10 bit YUV 444 formats. */
1775e290226SAyan Kumar Halder /* In DP550, 10 bit YUV 420 format also supported */
1785e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
1795e290226SAyan Kumar Halder
1805e290226SAyan Kumar Halder /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
1815e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
1825e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
1835e290226SAyan Kumar Halder
1845e290226SAyan Kumar Halder /* YUV 420, 422 P1 8, 10 bit formats */
1855e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
1865e290226SAyan Kumar Halder DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
1875e290226SAyan Kumar Halder
1885e290226SAyan Kumar Halder /* All formats */
1895e290226SAyan Kumar Halder DRM_FORMAT_MOD_LINEAR,
1905e290226SAyan Kumar Halder
1915e290226SAyan Kumar Halder DRM_FORMAT_MOD_INVALID
1925e290226SAyan Kumar Halder };
1935e290226SAyan Kumar Halder
19428ce675bSMihail Atanassov #define SE_N_SCALING_COEFFS 96
19528ce675bSMihail Atanassov static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
19628ce675bSMihail Atanassov [MALIDP_UPSCALING_COEFFS - 1] = {
19728ce675bSMihail Atanassov 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
19828ce675bSMihail Atanassov 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
19928ce675bSMihail Atanassov 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
20028ce675bSMihail Atanassov 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
20128ce675bSMihail Atanassov 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
20228ce675bSMihail Atanassov 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
20328ce675bSMihail Atanassov 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
20428ce675bSMihail Atanassov 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
20528ce675bSMihail Atanassov 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
20628ce675bSMihail Atanassov 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
20728ce675bSMihail Atanassov 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
20828ce675bSMihail Atanassov 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
20928ce675bSMihail Atanassov },
21028ce675bSMihail Atanassov [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
21128ce675bSMihail Atanassov 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
21228ce675bSMihail Atanassov 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
21328ce675bSMihail Atanassov 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
21428ce675bSMihail Atanassov 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
21528ce675bSMihail Atanassov 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
21628ce675bSMihail Atanassov 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
21728ce675bSMihail Atanassov 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
21828ce675bSMihail Atanassov 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
21928ce675bSMihail Atanassov 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
22028ce675bSMihail Atanassov 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
22128ce675bSMihail Atanassov 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
22228ce675bSMihail Atanassov 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
22328ce675bSMihail Atanassov },
22428ce675bSMihail Atanassov [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
22528ce675bSMihail Atanassov 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
22628ce675bSMihail Atanassov 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
22728ce675bSMihail Atanassov 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
22828ce675bSMihail Atanassov 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
22928ce675bSMihail Atanassov 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
23028ce675bSMihail Atanassov 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
23128ce675bSMihail Atanassov 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
23228ce675bSMihail Atanassov 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
23328ce675bSMihail Atanassov 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
23428ce675bSMihail Atanassov 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
23528ce675bSMihail Atanassov 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
23628ce675bSMihail Atanassov 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
23728ce675bSMihail Atanassov },
23828ce675bSMihail Atanassov [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
23928ce675bSMihail Atanassov 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
24028ce675bSMihail Atanassov 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
24128ce675bSMihail Atanassov 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
24228ce675bSMihail Atanassov 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
24328ce675bSMihail Atanassov 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
24428ce675bSMihail Atanassov 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
24528ce675bSMihail Atanassov 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
24628ce675bSMihail Atanassov 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
24728ce675bSMihail Atanassov 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
24828ce675bSMihail Atanassov 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
24928ce675bSMihail Atanassov 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
25028ce675bSMihail Atanassov 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
25128ce675bSMihail Atanassov },
25228ce675bSMihail Atanassov [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
25328ce675bSMihail Atanassov 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
25428ce675bSMihail Atanassov 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
25528ce675bSMihail Atanassov 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
25628ce675bSMihail Atanassov 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
25728ce675bSMihail Atanassov 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
25828ce675bSMihail Atanassov 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
25928ce675bSMihail Atanassov 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
26028ce675bSMihail Atanassov 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
26128ce675bSMihail Atanassov 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
26228ce675bSMihail Atanassov 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
26328ce675bSMihail Atanassov 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
26428ce675bSMihail Atanassov 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
26528ce675bSMihail Atanassov },
26628ce675bSMihail Atanassov };
26728ce675bSMihail Atanassov
268ad49f860SLiviu Dudau #define MALIDP_DE_DEFAULT_PREFETCH_START 5
269ad49f860SLiviu Dudau
malidp500_query_hw(struct malidp_hw_device * hwdev)270ad49f860SLiviu Dudau static int malidp500_query_hw(struct malidp_hw_device *hwdev)
271ad49f860SLiviu Dudau {
272ad49f860SLiviu Dudau u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
273ad49f860SLiviu Dudau /* bit 4 of the CONFIG_ID register holds the line size multiplier */
274ad49f860SLiviu Dudau u8 ln_size_mult = conf & 0x10 ? 2 : 1;
275ad49f860SLiviu Dudau
276ad49f860SLiviu Dudau hwdev->min_line_size = 2;
277ad49f860SLiviu Dudau hwdev->max_line_size = SZ_2K * ln_size_mult;
278ad49f860SLiviu Dudau hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
279ad49f860SLiviu Dudau hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
280ad49f860SLiviu Dudau
281ad49f860SLiviu Dudau return 0;
282ad49f860SLiviu Dudau }
283ad49f860SLiviu Dudau
malidp500_enter_config_mode(struct malidp_hw_device * hwdev)284ad49f860SLiviu Dudau static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
285ad49f860SLiviu Dudau {
286ad49f860SLiviu Dudau u32 status, count = 100;
287ad49f860SLiviu Dudau
288ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
289ad49f860SLiviu Dudau while (count) {
290a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
291ad49f860SLiviu Dudau if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
292ad49f860SLiviu Dudau break;
293ad49f860SLiviu Dudau /*
294ad49f860SLiviu Dudau * entering config mode can take as long as the rendering
295ad49f860SLiviu Dudau * of a full frame, hence the long sleep here
296ad49f860SLiviu Dudau */
297ad49f860SLiviu Dudau usleep_range(1000, 10000);
298ad49f860SLiviu Dudau count--;
299ad49f860SLiviu Dudau }
300ad49f860SLiviu Dudau WARN(count == 0, "timeout while entering config mode");
301ad49f860SLiviu Dudau }
302ad49f860SLiviu Dudau
malidp500_leave_config_mode(struct malidp_hw_device * hwdev)303ad49f860SLiviu Dudau static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
304ad49f860SLiviu Dudau {
305ad49f860SLiviu Dudau u32 status, count = 100;
306ad49f860SLiviu Dudau
307e64053f0SBrian Starkey malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
308ad49f860SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
309ad49f860SLiviu Dudau while (count) {
310a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
311ad49f860SLiviu Dudau if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
312ad49f860SLiviu Dudau break;
313ad49f860SLiviu Dudau usleep_range(100, 1000);
314ad49f860SLiviu Dudau count--;
315ad49f860SLiviu Dudau }
316ad49f860SLiviu Dudau WARN(count == 0, "timeout while leaving config mode");
317ad49f860SLiviu Dudau }
318ad49f860SLiviu Dudau
malidp500_in_config_mode(struct malidp_hw_device * hwdev)319ad49f860SLiviu Dudau static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
320ad49f860SLiviu Dudau {
321ad49f860SLiviu Dudau u32 status;
322ad49f860SLiviu Dudau
323a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
324ad49f860SLiviu Dudau if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
325ad49f860SLiviu Dudau return true;
326ad49f860SLiviu Dudau
327ad49f860SLiviu Dudau return false;
328ad49f860SLiviu Dudau }
329ad49f860SLiviu Dudau
malidp500_set_config_valid(struct malidp_hw_device * hwdev,u8 value)3300735cfdfSLiviu Dudau static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
331ad49f860SLiviu Dudau {
3320735cfdfSLiviu Dudau if (value)
333ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
3340735cfdfSLiviu Dudau else
3350735cfdfSLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
336ad49f860SLiviu Dudau }
337ad49f860SLiviu Dudau
malidp500_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)338ad49f860SLiviu Dudau static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
339ad49f860SLiviu Dudau {
340ad49f860SLiviu Dudau u32 val = 0;
341ad49f860SLiviu Dudau
342f877006dSAyan Kumar Halder malidp_hw_write(hwdev, hwdev->output_color_depth,
343f877006dSAyan Kumar Halder hwdev->hw->map.out_depth_base);
344ad49f860SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
345ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
346ad49f860SLiviu Dudau val |= MALIDP500_HSYNCPOL;
347ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
348ad49f860SLiviu Dudau val |= MALIDP500_VSYNCPOL;
349ad49f860SLiviu Dudau val |= MALIDP_DE_DEFAULT_PREFETCH_START;
350ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
351ad49f860SLiviu Dudau
352ad49f860SLiviu Dudau /*
353ad49f860SLiviu Dudau * Mali-DP500 encodes the background color like this:
354ad49f860SLiviu Dudau * - red @ MALIDP500_BGND_COLOR[12:0]
355ad49f860SLiviu Dudau * - green @ MALIDP500_BGND_COLOR[27:16]
356ad49f860SLiviu Dudau * - blue @ (MALIDP500_BGND_COLOR + 4)[12:0]
357ad49f860SLiviu Dudau */
358ad49f860SLiviu Dudau val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
359ad49f860SLiviu Dudau (MALIDP_BGND_COLOR_R & 0xfff);
360ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
361ad49f860SLiviu Dudau malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
362ad49f860SLiviu Dudau
363ad49f860SLiviu Dudau val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
364ad49f860SLiviu Dudau MALIDP_DE_H_BACKPORCH(mode->hback_porch);
365ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
366ad49f860SLiviu Dudau
367ad49f860SLiviu Dudau val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
368ad49f860SLiviu Dudau MALIDP_DE_V_BACKPORCH(mode->vback_porch);
369ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
370ad49f860SLiviu Dudau
371ad49f860SLiviu Dudau val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
372ad49f860SLiviu Dudau MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
373ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
374ad49f860SLiviu Dudau
375ad49f860SLiviu Dudau val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
376ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
377ad49f860SLiviu Dudau
378ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_INTERLACED)
379ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
380ad49f860SLiviu Dudau else
381ad49f860SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
382d298e6a2SWen He
383d298e6a2SWen He /*
384d298e6a2SWen He * Program the RQoS register to avoid high resolutions flicker
385d298e6a2SWen He * issue on the LS1028A.
386d298e6a2SWen He */
387d298e6a2SWen He if (hwdev->arqos_value) {
388d298e6a2SWen He val = hwdev->arqos_value;
389d298e6a2SWen He malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY);
390d298e6a2SWen He }
391ad49f860SLiviu Dudau }
392ad49f860SLiviu Dudau
malidp_format_get_bpp(u32 fmt)393b8207562SAyan Kumar Halder int malidp_format_get_bpp(u32 fmt)
394b8207562SAyan Kumar Halder {
39524c478eaSMaxime Ripard const struct drm_format_info *info = drm_format_info(fmt);
396b0f986b4SMaxime Ripard int bpp = info->cpp[0] * 8;
397b8207562SAyan Kumar Halder
398b8207562SAyan Kumar Halder if (bpp == 0) {
399b8207562SAyan Kumar Halder switch (fmt) {
400b8207562SAyan Kumar Halder case DRM_FORMAT_VUY101010:
401b8207562SAyan Kumar Halder bpp = 30;
40228ba1b1dSAnders Roxell break;
403b8207562SAyan Kumar Halder case DRM_FORMAT_YUV420_10BIT:
404b8207562SAyan Kumar Halder bpp = 15;
405b8207562SAyan Kumar Halder break;
406b8207562SAyan Kumar Halder case DRM_FORMAT_YUV420_8BIT:
407b8207562SAyan Kumar Halder bpp = 12;
408b8207562SAyan Kumar Halder break;
409b8207562SAyan Kumar Halder default:
410b8207562SAyan Kumar Halder bpp = 0;
411b8207562SAyan Kumar Halder }
412b8207562SAyan Kumar Halder }
413b8207562SAyan Kumar Halder
414b8207562SAyan Kumar Halder return bpp;
415b8207562SAyan Kumar Halder }
416b8207562SAyan Kumar Halder
malidp500_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)417b8207562SAyan Kumar Halder static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
418b8207562SAyan Kumar Halder u16 h, u32 fmt, bool has_modifier)
419ad49f860SLiviu Dudau {
420ad49f860SLiviu Dudau /*
421ad49f860SLiviu Dudau * Each layer needs enough rotation memory to fit 8 lines
422ad49f860SLiviu Dudau * worth of pixel data. Required size is then:
423ad49f860SLiviu Dudau * size = rotated_width * (bpp / 8) * 8;
424ad49f860SLiviu Dudau */
425b8207562SAyan Kumar Halder int bpp = malidp_format_get_bpp(fmt);
426b8207562SAyan Kumar Halder
427b8207562SAyan Kumar Halder return w * bpp;
428ad49f860SLiviu Dudau }
429ad49f860SLiviu Dudau
malidp500_se_write_pp_coefftab(struct malidp_hw_device * hwdev,u32 direction,u16 addr,u8 coeffs_id)43028ce675bSMihail Atanassov static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
43128ce675bSMihail Atanassov u32 direction,
43228ce675bSMihail Atanassov u16 addr,
43328ce675bSMihail Atanassov u8 coeffs_id)
43428ce675bSMihail Atanassov {
43528ce675bSMihail Atanassov int i;
43628ce675bSMihail Atanassov u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
43728ce675bSMihail Atanassov
43828ce675bSMihail Atanassov malidp_hw_write(hwdev,
43928ce675bSMihail Atanassov direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
44028ce675bSMihail Atanassov scaling_control + MALIDP_SE_COEFFTAB_ADDR);
44128ce675bSMihail Atanassov for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
44228ce675bSMihail Atanassov malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
44328ce675bSMihail Atanassov dp500_se_scaling_coeffs[coeffs_id][i]),
44428ce675bSMihail Atanassov scaling_control + MALIDP_SE_COEFFTAB_DATA);
44528ce675bSMihail Atanassov }
44628ce675bSMihail Atanassov
malidp500_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)44728ce675bSMihail Atanassov static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
44828ce675bSMihail Atanassov struct malidp_se_config *se_config,
44928ce675bSMihail Atanassov struct malidp_se_config *old_config)
45028ce675bSMihail Atanassov {
45128ce675bSMihail Atanassov /* Get array indices into dp500_se_scaling_coeffs. */
45228ce675bSMihail Atanassov u8 h = (u8)se_config->hcoeff - 1;
45328ce675bSMihail Atanassov u8 v = (u8)se_config->vcoeff - 1;
45428ce675bSMihail Atanassov
45528ce675bSMihail Atanassov if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
45628ce675bSMihail Atanassov v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
45728ce675bSMihail Atanassov return -EINVAL;
45828ce675bSMihail Atanassov
45928ce675bSMihail Atanassov if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
46028ce675bSMihail Atanassov se_config->vcoeff != old_config->vcoeff)) {
46128ce675bSMihail Atanassov malidp500_se_write_pp_coefftab(hwdev,
46228ce675bSMihail Atanassov (MALIDP_SE_V_COEFFTAB |
46328ce675bSMihail Atanassov MALIDP_SE_H_COEFFTAB),
46428ce675bSMihail Atanassov 0, v);
46528ce675bSMihail Atanassov } else {
46628ce675bSMihail Atanassov if (se_config->vcoeff != old_config->vcoeff)
46728ce675bSMihail Atanassov malidp500_se_write_pp_coefftab(hwdev,
46828ce675bSMihail Atanassov MALIDP_SE_V_COEFFTAB,
46928ce675bSMihail Atanassov 0, v);
47028ce675bSMihail Atanassov if (se_config->hcoeff != old_config->hcoeff)
47128ce675bSMihail Atanassov malidp500_se_write_pp_coefftab(hwdev,
47228ce675bSMihail Atanassov MALIDP_SE_H_COEFFTAB,
47328ce675bSMihail Atanassov 0, h);
47428ce675bSMihail Atanassov }
47528ce675bSMihail Atanassov
47628ce675bSMihail Atanassov return 0;
47728ce675bSMihail Atanassov }
47828ce675bSMihail Atanassov
malidp500_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)479c2e7f82dSMihail Atanassov static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
480c2e7f82dSMihail Atanassov struct malidp_se_config *se_config,
481c2e7f82dSMihail Atanassov struct videomode *vm)
482c2e7f82dSMihail Atanassov {
483c2e7f82dSMihail Atanassov unsigned long mclk;
484c2e7f82dSMihail Atanassov unsigned long pxlclk = vm->pixelclock; /* Hz */
485c2e7f82dSMihail Atanassov unsigned long htotal = vm->hactive + vm->hfront_porch +
486c2e7f82dSMihail Atanassov vm->hback_porch + vm->hsync_len;
487c2e7f82dSMihail Atanassov unsigned long input_size = se_config->input_w * se_config->input_h;
488c2e7f82dSMihail Atanassov unsigned long a = 10;
489c2e7f82dSMihail Atanassov long ret;
490c2e7f82dSMihail Atanassov
491c2e7f82dSMihail Atanassov /*
492c2e7f82dSMihail Atanassov * mclk = max(a, 1.5) * pxlclk
493c2e7f82dSMihail Atanassov *
494c2e7f82dSMihail Atanassov * To avoid float calculaiton, using 15 instead of 1.5 and div by
495c2e7f82dSMihail Atanassov * 10 to get mclk.
496c2e7f82dSMihail Atanassov */
497c2e7f82dSMihail Atanassov if (se_config->scale_enable) {
498c2e7f82dSMihail Atanassov a = 15 * input_size / (htotal * se_config->output_h);
499c2e7f82dSMihail Atanassov if (a < 15)
500c2e7f82dSMihail Atanassov a = 15;
501c2e7f82dSMihail Atanassov }
502c2e7f82dSMihail Atanassov mclk = a * pxlclk / 10;
503c2e7f82dSMihail Atanassov ret = clk_get_rate(hwdev->mclk);
504c2e7f82dSMihail Atanassov if (ret < mclk) {
505c2e7f82dSMihail Atanassov DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
506c2e7f82dSMihail Atanassov mclk / 1000);
507c2e7f82dSMihail Atanassov return -EINVAL;
508c2e7f82dSMihail Atanassov }
509c2e7f82dSMihail Atanassov return ret;
510c2e7f82dSMihail Atanassov }
511c2e7f82dSMihail Atanassov
malidp500_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)5121cb3cbe7SLiviu Dudau static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
5131cb3cbe7SLiviu Dudau dma_addr_t *addrs, s32 *pitches,
514b1150781SAlexandru Gheorghe int num_planes, u16 w, u16 h, u32 fmt_id,
515b1150781SAlexandru Gheorghe const s16 *rgb2yuv_coeffs)
5161cb3cbe7SLiviu Dudau {
5171cb3cbe7SLiviu Dudau u32 base = MALIDP500_SE_MEMWRITE_BASE;
5181cb3cbe7SLiviu Dudau u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
5191cb3cbe7SLiviu Dudau
5201cb3cbe7SLiviu Dudau /* enable the scaling engine block */
5211cb3cbe7SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
5221cb3cbe7SLiviu Dudau
5230735cfdfSLiviu Dudau /* restart the writeback if already enabled */
5240735cfdfSLiviu Dudau if (hwdev->mw_state != MW_NOT_ENABLED)
5250735cfdfSLiviu Dudau hwdev->mw_state = MW_RESTART;
5260735cfdfSLiviu Dudau else
5271cb3cbe7SLiviu Dudau hwdev->mw_state = MW_START;
5281cb3cbe7SLiviu Dudau
5291cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
5301cb3cbe7SLiviu Dudau switch (num_planes) {
5311cb3cbe7SLiviu Dudau case 2:
5321cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
5331cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
5341cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
535df561f66SGustavo A. R. Silva fallthrough;
5361cb3cbe7SLiviu Dudau case 1:
5371cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
5381cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
5391cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
5401cb3cbe7SLiviu Dudau break;
5411cb3cbe7SLiviu Dudau default:
5421cb3cbe7SLiviu Dudau WARN(1, "Invalid number of planes");
5431cb3cbe7SLiviu Dudau }
5441cb3cbe7SLiviu Dudau
5451cb3cbe7SLiviu Dudau malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
5461cb3cbe7SLiviu Dudau MALIDP500_SE_MEMWRITE_OUT_SIZE);
547b1150781SAlexandru Gheorghe
548b1150781SAlexandru Gheorghe if (rgb2yuv_coeffs) {
549b1150781SAlexandru Gheorghe int i;
550b1150781SAlexandru Gheorghe
551b1150781SAlexandru Gheorghe for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
552b1150781SAlexandru Gheorghe malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
553b1150781SAlexandru Gheorghe MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
554b1150781SAlexandru Gheorghe }
555b1150781SAlexandru Gheorghe }
556b1150781SAlexandru Gheorghe
5571cb3cbe7SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
5581cb3cbe7SLiviu Dudau
5591cb3cbe7SLiviu Dudau return 0;
5601cb3cbe7SLiviu Dudau }
5611cb3cbe7SLiviu Dudau
malidp500_disable_memwrite(struct malidp_hw_device * hwdev)5621cb3cbe7SLiviu Dudau static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
5631cb3cbe7SLiviu Dudau {
5641cb3cbe7SLiviu Dudau u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
5651cb3cbe7SLiviu Dudau
5660735cfdfSLiviu Dudau if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
5671cb3cbe7SLiviu Dudau hwdev->mw_state = MW_STOP;
5681cb3cbe7SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
5691cb3cbe7SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
5701cb3cbe7SLiviu Dudau }
5711cb3cbe7SLiviu Dudau
malidp550_query_hw(struct malidp_hw_device * hwdev)572ad49f860SLiviu Dudau static int malidp550_query_hw(struct malidp_hw_device *hwdev)
573ad49f860SLiviu Dudau {
574ad49f860SLiviu Dudau u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
575ad49f860SLiviu Dudau u8 ln_size = (conf >> 4) & 0x3, rsize;
576ad49f860SLiviu Dudau
577ad49f860SLiviu Dudau hwdev->min_line_size = 2;
578ad49f860SLiviu Dudau
579ad49f860SLiviu Dudau switch (ln_size) {
580ad49f860SLiviu Dudau case 0:
581ad49f860SLiviu Dudau hwdev->max_line_size = SZ_2K;
582ad49f860SLiviu Dudau /* two banks of 64KB for rotation memory */
583ad49f860SLiviu Dudau rsize = 64;
584ad49f860SLiviu Dudau break;
585ad49f860SLiviu Dudau case 1:
586ad49f860SLiviu Dudau hwdev->max_line_size = SZ_4K;
587ad49f860SLiviu Dudau /* two banks of 128KB for rotation memory */
588ad49f860SLiviu Dudau rsize = 128;
589ad49f860SLiviu Dudau break;
590ad49f860SLiviu Dudau case 2:
591ad49f860SLiviu Dudau hwdev->max_line_size = 1280;
592ad49f860SLiviu Dudau /* two banks of 40KB for rotation memory */
593ad49f860SLiviu Dudau rsize = 40;
594ad49f860SLiviu Dudau break;
595ad49f860SLiviu Dudau case 3:
596ad49f860SLiviu Dudau /* reserved value */
597ad49f860SLiviu Dudau hwdev->max_line_size = 0;
598ad49f860SLiviu Dudau return -EINVAL;
599ad49f860SLiviu Dudau }
600ad49f860SLiviu Dudau
601ad49f860SLiviu Dudau hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
602ad49f860SLiviu Dudau return 0;
603ad49f860SLiviu Dudau }
604ad49f860SLiviu Dudau
malidp550_enter_config_mode(struct malidp_hw_device * hwdev)605ad49f860SLiviu Dudau static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
606ad49f860SLiviu Dudau {
607ad49f860SLiviu Dudau u32 status, count = 100;
608ad49f860SLiviu Dudau
609ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
610ad49f860SLiviu Dudau while (count) {
611a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
612ad49f860SLiviu Dudau if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
613ad49f860SLiviu Dudau break;
614ad49f860SLiviu Dudau /*
615ad49f860SLiviu Dudau * entering config mode can take as long as the rendering
616ad49f860SLiviu Dudau * of a full frame, hence the long sleep here
617ad49f860SLiviu Dudau */
618ad49f860SLiviu Dudau usleep_range(1000, 10000);
619ad49f860SLiviu Dudau count--;
620ad49f860SLiviu Dudau }
621ad49f860SLiviu Dudau WARN(count == 0, "timeout while entering config mode");
622ad49f860SLiviu Dudau }
623ad49f860SLiviu Dudau
malidp550_leave_config_mode(struct malidp_hw_device * hwdev)624ad49f860SLiviu Dudau static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
625ad49f860SLiviu Dudau {
626ad49f860SLiviu Dudau u32 status, count = 100;
627ad49f860SLiviu Dudau
628e64053f0SBrian Starkey malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
629ad49f860SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
630ad49f860SLiviu Dudau while (count) {
631a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
632ad49f860SLiviu Dudau if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
633ad49f860SLiviu Dudau break;
634ad49f860SLiviu Dudau usleep_range(100, 1000);
635ad49f860SLiviu Dudau count--;
636ad49f860SLiviu Dudau }
637ad49f860SLiviu Dudau WARN(count == 0, "timeout while leaving config mode");
638ad49f860SLiviu Dudau }
639ad49f860SLiviu Dudau
malidp550_in_config_mode(struct malidp_hw_device * hwdev)640ad49f860SLiviu Dudau static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
641ad49f860SLiviu Dudau {
642ad49f860SLiviu Dudau u32 status;
643ad49f860SLiviu Dudau
644a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
645ad49f860SLiviu Dudau if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
646ad49f860SLiviu Dudau return true;
647ad49f860SLiviu Dudau
648ad49f860SLiviu Dudau return false;
649ad49f860SLiviu Dudau }
650ad49f860SLiviu Dudau
malidp550_set_config_valid(struct malidp_hw_device * hwdev,u8 value)6510735cfdfSLiviu Dudau static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
652ad49f860SLiviu Dudau {
6530735cfdfSLiviu Dudau if (value)
654ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
6550735cfdfSLiviu Dudau else
6560735cfdfSLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
657ad49f860SLiviu Dudau }
658ad49f860SLiviu Dudau
malidp550_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)659ad49f860SLiviu Dudau static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
660ad49f860SLiviu Dudau {
661ad49f860SLiviu Dudau u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
662ad49f860SLiviu Dudau
663f877006dSAyan Kumar Halder malidp_hw_write(hwdev, hwdev->output_color_depth,
664f877006dSAyan Kumar Halder hwdev->hw->map.out_depth_base);
665ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
666ad49f860SLiviu Dudau /*
667ad49f860SLiviu Dudau * Mali-DP550 and Mali-DP650 encode the background color like this:
668ad49f860SLiviu Dudau * - red @ MALIDP550_DE_BGND_COLOR[23:16]
669ad49f860SLiviu Dudau * - green @ MALIDP550_DE_BGND_COLOR[15:8]
670ad49f860SLiviu Dudau * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
671ad49f860SLiviu Dudau *
672ad49f860SLiviu Dudau * We need to truncate the least significant 4 bits from the default
673ad49f860SLiviu Dudau * MALIDP_BGND_COLOR_x values
674ad49f860SLiviu Dudau */
675ad49f860SLiviu Dudau val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
676ad49f860SLiviu Dudau (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
677ad49f860SLiviu Dudau ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
678ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
679ad49f860SLiviu Dudau
680ad49f860SLiviu Dudau val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
681ad49f860SLiviu Dudau MALIDP_DE_H_BACKPORCH(mode->hback_porch);
682ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
683ad49f860SLiviu Dudau
684ad49f860SLiviu Dudau val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
685ad49f860SLiviu Dudau MALIDP_DE_V_BACKPORCH(mode->vback_porch);
686ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
687ad49f860SLiviu Dudau
688ad49f860SLiviu Dudau val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
689ad49f860SLiviu Dudau MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
690ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
691ad49f860SLiviu Dudau val |= MALIDP550_HSYNCPOL;
692ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
693ad49f860SLiviu Dudau val |= MALIDP550_VSYNCPOL;
694ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
695ad49f860SLiviu Dudau
696ad49f860SLiviu Dudau val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
697ad49f860SLiviu Dudau malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
698ad49f860SLiviu Dudau
699ad49f860SLiviu Dudau if (mode->flags & DISPLAY_FLAGS_INTERLACED)
700ad49f860SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
701ad49f860SLiviu Dudau else
702ad49f860SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
703ad49f860SLiviu Dudau }
704ad49f860SLiviu Dudau
malidpx50_get_bytes_per_column(u32 fmt)705b8207562SAyan Kumar Halder static int malidpx50_get_bytes_per_column(u32 fmt)
706ad49f860SLiviu Dudau {
707b8207562SAyan Kumar Halder u32 bytes_per_column;
708ad49f860SLiviu Dudau
709ad49f860SLiviu Dudau switch (fmt) {
710ad49f860SLiviu Dudau /* 8 lines at 4 bytes per pixel */
711ad49f860SLiviu Dudau case DRM_FORMAT_ARGB2101010:
712ad49f860SLiviu Dudau case DRM_FORMAT_ABGR2101010:
713ad49f860SLiviu Dudau case DRM_FORMAT_RGBA1010102:
714ad49f860SLiviu Dudau case DRM_FORMAT_BGRA1010102:
715ad49f860SLiviu Dudau case DRM_FORMAT_ARGB8888:
716ad49f860SLiviu Dudau case DRM_FORMAT_ABGR8888:
717ad49f860SLiviu Dudau case DRM_FORMAT_RGBA8888:
718ad49f860SLiviu Dudau case DRM_FORMAT_BGRA8888:
719ad49f860SLiviu Dudau case DRM_FORMAT_XRGB8888:
720ad49f860SLiviu Dudau case DRM_FORMAT_XBGR8888:
721ad49f860SLiviu Dudau case DRM_FORMAT_RGBX8888:
722ad49f860SLiviu Dudau case DRM_FORMAT_BGRX8888:
723ad49f860SLiviu Dudau case DRM_FORMAT_RGB888:
724ad49f860SLiviu Dudau case DRM_FORMAT_BGR888:
725ad49f860SLiviu Dudau /* 16 lines at 2 bytes per pixel */
726ad49f860SLiviu Dudau case DRM_FORMAT_RGBA5551:
727ad49f860SLiviu Dudau case DRM_FORMAT_ABGR1555:
728ad49f860SLiviu Dudau case DRM_FORMAT_RGB565:
729ad49f860SLiviu Dudau case DRM_FORMAT_BGR565:
730ad49f860SLiviu Dudau case DRM_FORMAT_UYVY:
731ad49f860SLiviu Dudau case DRM_FORMAT_YUYV:
73255bc277dSAlexandru Gheorghe case DRM_FORMAT_X0L0:
733b8207562SAyan Kumar Halder bytes_per_column = 32;
734ad49f860SLiviu Dudau break;
735ad49f860SLiviu Dudau /* 16 lines at 1.5 bytes per pixel */
736ad49f860SLiviu Dudau case DRM_FORMAT_NV12:
737ad49f860SLiviu Dudau case DRM_FORMAT_YUV420:
738b8207562SAyan Kumar Halder /* 8 lines at 3 bytes per pixel */
739b8207562SAyan Kumar Halder case DRM_FORMAT_VUY888:
740b8207562SAyan Kumar Halder /* 16 lines at 12 bits per pixel */
741b8207562SAyan Kumar Halder case DRM_FORMAT_YUV420_8BIT:
742b8207562SAyan Kumar Halder /* 8 lines at 3 bytes per pixel */
743b8207562SAyan Kumar Halder case DRM_FORMAT_P010:
744b8207562SAyan Kumar Halder bytes_per_column = 24;
745b8207562SAyan Kumar Halder break;
746b8207562SAyan Kumar Halder /* 8 lines at 30 bits per pixel */
747b8207562SAyan Kumar Halder case DRM_FORMAT_VUY101010:
748b8207562SAyan Kumar Halder /* 16 lines at 15 bits per pixel */
749b8207562SAyan Kumar Halder case DRM_FORMAT_YUV420_10BIT:
750b8207562SAyan Kumar Halder bytes_per_column = 30;
751ad49f860SLiviu Dudau break;
752ad49f860SLiviu Dudau default:
753ad49f860SLiviu Dudau return -EINVAL;
754ad49f860SLiviu Dudau }
755ad49f860SLiviu Dudau
756b8207562SAyan Kumar Halder return bytes_per_column;
757b8207562SAyan Kumar Halder }
758b8207562SAyan Kumar Halder
malidp550_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)759b8207562SAyan Kumar Halder static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
760b8207562SAyan Kumar Halder u16 h, u32 fmt, bool has_modifier)
761b8207562SAyan Kumar Halder {
762b8207562SAyan Kumar Halder int bytes_per_column = 0;
763b8207562SAyan Kumar Halder
764b8207562SAyan Kumar Halder switch (fmt) {
765b8207562SAyan Kumar Halder /* 8 lines at 15 bits per pixel */
766b8207562SAyan Kumar Halder case DRM_FORMAT_YUV420_10BIT:
767b8207562SAyan Kumar Halder bytes_per_column = 15;
768b8207562SAyan Kumar Halder break;
769b8207562SAyan Kumar Halder /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
770b8207562SAyan Kumar Halder case DRM_FORMAT_X0L2:
771b8207562SAyan Kumar Halder if (has_modifier)
772b8207562SAyan Kumar Halder bytes_per_column = 8;
773b8207562SAyan Kumar Halder else
774b8207562SAyan Kumar Halder return -EINVAL;
775b8207562SAyan Kumar Halder break;
776b8207562SAyan Kumar Halder default:
777b8207562SAyan Kumar Halder bytes_per_column = malidpx50_get_bytes_per_column(fmt);
778b8207562SAyan Kumar Halder }
779b8207562SAyan Kumar Halder
780b8207562SAyan Kumar Halder if (bytes_per_column == -EINVAL)
781b8207562SAyan Kumar Halder return bytes_per_column;
782b8207562SAyan Kumar Halder
783b8207562SAyan Kumar Halder return w * bytes_per_column;
784b8207562SAyan Kumar Halder }
785b8207562SAyan Kumar Halder
malidp650_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)786b8207562SAyan Kumar Halder static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
787b8207562SAyan Kumar Halder u16 h, u32 fmt, bool has_modifier)
788b8207562SAyan Kumar Halder {
789b8207562SAyan Kumar Halder int bytes_per_column = 0;
790b8207562SAyan Kumar Halder
791b8207562SAyan Kumar Halder switch (fmt) {
792b8207562SAyan Kumar Halder /* 16 lines at 2 bytes per pixel */
793b8207562SAyan Kumar Halder case DRM_FORMAT_X0L2:
794b8207562SAyan Kumar Halder bytes_per_column = 32;
795b8207562SAyan Kumar Halder break;
796b8207562SAyan Kumar Halder default:
797b8207562SAyan Kumar Halder bytes_per_column = malidpx50_get_bytes_per_column(fmt);
798b8207562SAyan Kumar Halder }
799b8207562SAyan Kumar Halder
800b8207562SAyan Kumar Halder if (bytes_per_column == -EINVAL)
801b8207562SAyan Kumar Halder return bytes_per_column;
802b8207562SAyan Kumar Halder
803b8207562SAyan Kumar Halder return w * bytes_per_column;
804ad49f860SLiviu Dudau }
805ad49f860SLiviu Dudau
malidp550_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)80628ce675bSMihail Atanassov static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
80728ce675bSMihail Atanassov struct malidp_se_config *se_config,
80828ce675bSMihail Atanassov struct malidp_se_config *old_config)
80928ce675bSMihail Atanassov {
81028ce675bSMihail Atanassov u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
81128ce675bSMihail Atanassov MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
81228ce675bSMihail Atanassov u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
81328ce675bSMihail Atanassov MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
81428ce675bSMihail Atanassov
81528ce675bSMihail Atanassov malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
81628ce675bSMihail Atanassov malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
81728ce675bSMihail Atanassov return 0;
81828ce675bSMihail Atanassov }
81928ce675bSMihail Atanassov
malidp550_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)820c2e7f82dSMihail Atanassov static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
821c2e7f82dSMihail Atanassov struct malidp_se_config *se_config,
822c2e7f82dSMihail Atanassov struct videomode *vm)
823c2e7f82dSMihail Atanassov {
824c2e7f82dSMihail Atanassov unsigned long mclk;
825c2e7f82dSMihail Atanassov unsigned long pxlclk = vm->pixelclock;
826c2e7f82dSMihail Atanassov unsigned long htotal = vm->hactive + vm->hfront_porch +
827c2e7f82dSMihail Atanassov vm->hback_porch + vm->hsync_len;
828c2e7f82dSMihail Atanassov unsigned long numerator = 1, denominator = 1;
829c2e7f82dSMihail Atanassov long ret;
830c2e7f82dSMihail Atanassov
831c2e7f82dSMihail Atanassov if (se_config->scale_enable) {
832c2e7f82dSMihail Atanassov numerator = max(se_config->input_w, se_config->output_w) *
833c2e7f82dSMihail Atanassov se_config->input_h;
834c2e7f82dSMihail Atanassov numerator += se_config->output_w *
835c2e7f82dSMihail Atanassov (se_config->output_h -
836c2e7f82dSMihail Atanassov min(se_config->input_h, se_config->output_h));
837c2e7f82dSMihail Atanassov denominator = (htotal - 2) * se_config->output_h;
838c2e7f82dSMihail Atanassov }
839c2e7f82dSMihail Atanassov
840c2e7f82dSMihail Atanassov /* mclk can't be slower than pxlclk. */
841c2e7f82dSMihail Atanassov if (numerator < denominator)
842c2e7f82dSMihail Atanassov numerator = denominator = 1;
843c2e7f82dSMihail Atanassov mclk = (pxlclk * numerator) / denominator;
844c2e7f82dSMihail Atanassov ret = clk_get_rate(hwdev->mclk);
845c2e7f82dSMihail Atanassov if (ret < mclk) {
846c2e7f82dSMihail Atanassov DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
847c2e7f82dSMihail Atanassov mclk / 1000);
848c2e7f82dSMihail Atanassov return -EINVAL;
849c2e7f82dSMihail Atanassov }
850c2e7f82dSMihail Atanassov return ret;
851c2e7f82dSMihail Atanassov }
852c2e7f82dSMihail Atanassov
malidp550_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)853846c87a0SLiviu Dudau static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
854846c87a0SLiviu Dudau dma_addr_t *addrs, s32 *pitches,
855b1150781SAlexandru Gheorghe int num_planes, u16 w, u16 h, u32 fmt_id,
856b1150781SAlexandru Gheorghe const s16 *rgb2yuv_coeffs)
857846c87a0SLiviu Dudau {
858846c87a0SLiviu Dudau u32 base = MALIDP550_SE_MEMWRITE_BASE;
859846c87a0SLiviu Dudau u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
860846c87a0SLiviu Dudau
861846c87a0SLiviu Dudau /* enable the scaling engine block */
862846c87a0SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
863846c87a0SLiviu Dudau
8641cb3cbe7SLiviu Dudau hwdev->mw_state = MW_ONESHOT;
8651cb3cbe7SLiviu Dudau
866846c87a0SLiviu Dudau malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
867846c87a0SLiviu Dudau switch (num_planes) {
868846c87a0SLiviu Dudau case 2:
869846c87a0SLiviu Dudau malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
870846c87a0SLiviu Dudau malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
871846c87a0SLiviu Dudau malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
872df561f66SGustavo A. R. Silva fallthrough;
873846c87a0SLiviu Dudau case 1:
874846c87a0SLiviu Dudau malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
875846c87a0SLiviu Dudau malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
876846c87a0SLiviu Dudau malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
877846c87a0SLiviu Dudau break;
878846c87a0SLiviu Dudau default:
879846c87a0SLiviu Dudau WARN(1, "Invalid number of planes");
880846c87a0SLiviu Dudau }
881846c87a0SLiviu Dudau
882846c87a0SLiviu Dudau malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
883846c87a0SLiviu Dudau MALIDP550_SE_MEMWRITE_OUT_SIZE);
884846c87a0SLiviu Dudau malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
885846c87a0SLiviu Dudau MALIDP550_SE_CONTROL);
886846c87a0SLiviu Dudau
887b1150781SAlexandru Gheorghe if (rgb2yuv_coeffs) {
888b1150781SAlexandru Gheorghe int i;
889b1150781SAlexandru Gheorghe
890b1150781SAlexandru Gheorghe for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
891b1150781SAlexandru Gheorghe malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
892b1150781SAlexandru Gheorghe MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
893b1150781SAlexandru Gheorghe }
894b1150781SAlexandru Gheorghe }
895b1150781SAlexandru Gheorghe
896846c87a0SLiviu Dudau return 0;
897846c87a0SLiviu Dudau }
898846c87a0SLiviu Dudau
malidp550_disable_memwrite(struct malidp_hw_device * hwdev)899846c87a0SLiviu Dudau static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
900846c87a0SLiviu Dudau {
901846c87a0SLiviu Dudau u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
902846c87a0SLiviu Dudau
903846c87a0SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
904846c87a0SLiviu Dudau MALIDP550_SE_CONTROL);
905846c87a0SLiviu Dudau malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
906846c87a0SLiviu Dudau }
907846c87a0SLiviu Dudau
malidp650_query_hw(struct malidp_hw_device * hwdev)908ad49f860SLiviu Dudau static int malidp650_query_hw(struct malidp_hw_device *hwdev)
909ad49f860SLiviu Dudau {
910ad49f860SLiviu Dudau u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
911ad49f860SLiviu Dudau u8 ln_size = (conf >> 4) & 0x3, rsize;
912ad49f860SLiviu Dudau
913ad49f860SLiviu Dudau hwdev->min_line_size = 4;
914ad49f860SLiviu Dudau
915ad49f860SLiviu Dudau switch (ln_size) {
916ad49f860SLiviu Dudau case 0:
917ad49f860SLiviu Dudau case 2:
918ad49f860SLiviu Dudau /* reserved values */
919ad49f860SLiviu Dudau hwdev->max_line_size = 0;
920ad49f860SLiviu Dudau return -EINVAL;
921ad49f860SLiviu Dudau case 1:
922ad49f860SLiviu Dudau hwdev->max_line_size = SZ_4K;
923ad49f860SLiviu Dudau /* two banks of 128KB for rotation memory */
924ad49f860SLiviu Dudau rsize = 128;
925ad49f860SLiviu Dudau break;
926ad49f860SLiviu Dudau case 3:
927ad49f860SLiviu Dudau hwdev->max_line_size = 2560;
928ad49f860SLiviu Dudau /* two banks of 80KB for rotation memory */
929ad49f860SLiviu Dudau rsize = 80;
930ad49f860SLiviu Dudau }
931ad49f860SLiviu Dudau
932ad49f860SLiviu Dudau hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
933ad49f860SLiviu Dudau return 0;
934ad49f860SLiviu Dudau }
935ad49f860SLiviu Dudau
936a6993b21SLiviu Dudau const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
937ad49f860SLiviu Dudau [MALIDP_500] = {
938ad49f860SLiviu Dudau .map = {
93902725d31SMihail Atanassov .coeffs_base = MALIDP500_COEFFS_BASE,
940ad49f860SLiviu Dudau .se_base = MALIDP500_SE_BASE,
941ad49f860SLiviu Dudau .dc_base = MALIDP500_DC_BASE,
942ad49f860SLiviu Dudau .out_depth_base = MALIDP500_OUTPUT_DEPTH,
943ad49f860SLiviu Dudau .features = 0, /* no CLEARIRQ register */
944ad49f860SLiviu Dudau .n_layers = ARRAY_SIZE(malidp500_layers),
945ad49f860SLiviu Dudau .layers = malidp500_layers,
946ad49f860SLiviu Dudau .de_irq_map = {
947ad49f860SLiviu Dudau .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
948ad49f860SLiviu Dudau MALIDP500_DE_IRQ_AXI_ERR |
949ad49f860SLiviu Dudau MALIDP500_DE_IRQ_VSYNC |
950ad49f860SLiviu Dudau MALIDP500_DE_IRQ_GLOBAL,
951ad49f860SLiviu Dudau .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
952613c5c7fSAlexandru Gheorghe .err_mask = MALIDP_DE_IRQ_UNDERRUN |
953613c5c7fSAlexandru Gheorghe MALIDP500_DE_IRQ_AXI_ERR |
954613c5c7fSAlexandru Gheorghe MALIDP500_DE_IRQ_SATURATION,
955ad49f860SLiviu Dudau },
956ad49f860SLiviu Dudau .se_irq_map = {
95789610dc2SAlison Wang .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
9581cb3cbe7SLiviu Dudau MALIDP500_SE_IRQ_CONF_VALID |
95989610dc2SAlison Wang MALIDP500_SE_IRQ_GLOBAL,
9601cb3cbe7SLiviu Dudau .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
961613c5c7fSAlexandru Gheorghe .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
962613c5c7fSAlexandru Gheorghe MALIDP500_SE_IRQ_AXI_ERROR |
963613c5c7fSAlexandru Gheorghe MALIDP500_SE_IRQ_OVERRUN,
964ad49f860SLiviu Dudau },
965ad49f860SLiviu Dudau .dc_irq_map = {
966ad49f860SLiviu Dudau .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
967ad49f860SLiviu Dudau .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
968ad49f860SLiviu Dudau },
9696211b486SBrian Starkey .pixel_formats = malidp500_de_formats,
9706211b486SBrian Starkey .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
971a228062cSBrian Starkey .bus_align_bytes = 8,
972ad49f860SLiviu Dudau },
973ad49f860SLiviu Dudau .query_hw = malidp500_query_hw,
974ad49f860SLiviu Dudau .enter_config_mode = malidp500_enter_config_mode,
975ad49f860SLiviu Dudau .leave_config_mode = malidp500_leave_config_mode,
976ad49f860SLiviu Dudau .in_config_mode = malidp500_in_config_mode,
977ad49f860SLiviu Dudau .set_config_valid = malidp500_set_config_valid,
978ad49f860SLiviu Dudau .modeset = malidp500_modeset,
979ad49f860SLiviu Dudau .rotmem_required = malidp500_rotmem_required,
98028ce675bSMihail Atanassov .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
981c2e7f82dSMihail Atanassov .se_calc_mclk = malidp500_se_calc_mclk,
9821cb3cbe7SLiviu Dudau .enable_memwrite = malidp500_enable_memwrite,
9831cb3cbe7SLiviu Dudau .disable_memwrite = malidp500_disable_memwrite,
98483d642eeSMihail Atanassov .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
985ad49f860SLiviu Dudau },
986ad49f860SLiviu Dudau [MALIDP_550] = {
987ad49f860SLiviu Dudau .map = {
98802725d31SMihail Atanassov .coeffs_base = MALIDP550_COEFFS_BASE,
989ad49f860SLiviu Dudau .se_base = MALIDP550_SE_BASE,
990ad49f860SLiviu Dudau .dc_base = MALIDP550_DC_BASE,
991ad49f860SLiviu Dudau .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
9925e290226SAyan Kumar Halder .features = MALIDP_REGMAP_HAS_CLEARIRQ |
9935e290226SAyan Kumar Halder MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
9945e290226SAyan Kumar Halder MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
9955e290226SAyan Kumar Halder MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
996ad49f860SLiviu Dudau .n_layers = ARRAY_SIZE(malidp550_layers),
997ad49f860SLiviu Dudau .layers = malidp550_layers,
998ad49f860SLiviu Dudau .de_irq_map = {
999ad49f860SLiviu Dudau .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1000ad49f860SLiviu Dudau MALIDP550_DE_IRQ_VSYNC,
1001ad49f860SLiviu Dudau .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1002613c5c7fSAlexandru Gheorghe .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1003613c5c7fSAlexandru Gheorghe MALIDP550_DE_IRQ_SATURATION |
1004613c5c7fSAlexandru Gheorghe MALIDP550_DE_IRQ_AXI_ERR,
1005ad49f860SLiviu Dudau },
1006ad49f860SLiviu Dudau .se_irq_map = {
1007613c5c7fSAlexandru Gheorghe .irq_mask = MALIDP550_SE_IRQ_EOW,
1008846c87a0SLiviu Dudau .vsync_irq = MALIDP550_SE_IRQ_EOW,
1009613c5c7fSAlexandru Gheorghe .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1010613c5c7fSAlexandru Gheorghe MALIDP550_SE_IRQ_OVR |
1011613c5c7fSAlexandru Gheorghe MALIDP550_SE_IRQ_IBSY,
1012ad49f860SLiviu Dudau },
1013ad49f860SLiviu Dudau .dc_irq_map = {
1014846c87a0SLiviu Dudau .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1015846c87a0SLiviu Dudau MALIDP550_DC_IRQ_SE,
1016ad49f860SLiviu Dudau .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1017ad49f860SLiviu Dudau },
10186211b486SBrian Starkey .pixel_formats = malidp550_de_formats,
10196211b486SBrian Starkey .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1020a228062cSBrian Starkey .bus_align_bytes = 8,
1021ad49f860SLiviu Dudau },
1022ad49f860SLiviu Dudau .query_hw = malidp550_query_hw,
1023ad49f860SLiviu Dudau .enter_config_mode = malidp550_enter_config_mode,
1024ad49f860SLiviu Dudau .leave_config_mode = malidp550_leave_config_mode,
1025ad49f860SLiviu Dudau .in_config_mode = malidp550_in_config_mode,
1026ad49f860SLiviu Dudau .set_config_valid = malidp550_set_config_valid,
1027ad49f860SLiviu Dudau .modeset = malidp550_modeset,
1028ad49f860SLiviu Dudau .rotmem_required = malidp550_rotmem_required,
102928ce675bSMihail Atanassov .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1030c2e7f82dSMihail Atanassov .se_calc_mclk = malidp550_se_calc_mclk,
1031846c87a0SLiviu Dudau .enable_memwrite = malidp550_enable_memwrite,
1032846c87a0SLiviu Dudau .disable_memwrite = malidp550_disable_memwrite,
103383d642eeSMihail Atanassov .features = 0,
1034ad49f860SLiviu Dudau },
1035ad49f860SLiviu Dudau [MALIDP_650] = {
1036ad49f860SLiviu Dudau .map = {
103702725d31SMihail Atanassov .coeffs_base = MALIDP550_COEFFS_BASE,
1038ad49f860SLiviu Dudau .se_base = MALIDP550_SE_BASE,
1039ad49f860SLiviu Dudau .dc_base = MALIDP550_DC_BASE,
1040ad49f860SLiviu Dudau .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
10415e290226SAyan Kumar Halder .features = MALIDP_REGMAP_HAS_CLEARIRQ |
10425e290226SAyan Kumar Halder MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
10435e290226SAyan Kumar Halder MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
10441f23a56aSJamie Fox .n_layers = ARRAY_SIZE(malidp650_layers),
10451f23a56aSJamie Fox .layers = malidp650_layers,
1046ad49f860SLiviu Dudau .de_irq_map = {
1047ad49f860SLiviu Dudau .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1048ad49f860SLiviu Dudau MALIDP650_DE_IRQ_DRIFT |
1049ad49f860SLiviu Dudau MALIDP550_DE_IRQ_VSYNC,
1050ad49f860SLiviu Dudau .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1051613c5c7fSAlexandru Gheorghe .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1052613c5c7fSAlexandru Gheorghe MALIDP650_DE_IRQ_DRIFT |
1053613c5c7fSAlexandru Gheorghe MALIDP550_DE_IRQ_SATURATION |
1054613c5c7fSAlexandru Gheorghe MALIDP550_DE_IRQ_AXI_ERR |
1055613c5c7fSAlexandru Gheorghe MALIDP650_DE_IRQ_ACEV1 |
1056613c5c7fSAlexandru Gheorghe MALIDP650_DE_IRQ_ACEV2 |
1057613c5c7fSAlexandru Gheorghe MALIDP650_DE_IRQ_ACEG |
1058613c5c7fSAlexandru Gheorghe MALIDP650_DE_IRQ_AXIEP,
1059ad49f860SLiviu Dudau },
1060ad49f860SLiviu Dudau .se_irq_map = {
1061613c5c7fSAlexandru Gheorghe .irq_mask = MALIDP550_SE_IRQ_EOW,
1062846c87a0SLiviu Dudau .vsync_irq = MALIDP550_SE_IRQ_EOW,
1063613c5c7fSAlexandru Gheorghe .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1064613c5c7fSAlexandru Gheorghe MALIDP550_SE_IRQ_OVR |
1065613c5c7fSAlexandru Gheorghe MALIDP550_SE_IRQ_IBSY,
1066ad49f860SLiviu Dudau },
1067ad49f860SLiviu Dudau .dc_irq_map = {
1068846c87a0SLiviu Dudau .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1069846c87a0SLiviu Dudau MALIDP550_DC_IRQ_SE,
1070ad49f860SLiviu Dudau .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1071ad49f860SLiviu Dudau },
107255bc277dSAlexandru Gheorghe .pixel_formats = malidp650_de_formats,
107355bc277dSAlexandru Gheorghe .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1074a228062cSBrian Starkey .bus_align_bytes = 16,
1075ad49f860SLiviu Dudau },
1076ad49f860SLiviu Dudau .query_hw = malidp650_query_hw,
1077ad49f860SLiviu Dudau .enter_config_mode = malidp550_enter_config_mode,
1078ad49f860SLiviu Dudau .leave_config_mode = malidp550_leave_config_mode,
1079ad49f860SLiviu Dudau .in_config_mode = malidp550_in_config_mode,
1080ad49f860SLiviu Dudau .set_config_valid = malidp550_set_config_valid,
1081ad49f860SLiviu Dudau .modeset = malidp550_modeset,
1082b8207562SAyan Kumar Halder .rotmem_required = malidp650_rotmem_required,
108328ce675bSMihail Atanassov .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1084c2e7f82dSMihail Atanassov .se_calc_mclk = malidp550_se_calc_mclk,
1085846c87a0SLiviu Dudau .enable_memwrite = malidp550_enable_memwrite,
1086846c87a0SLiviu Dudau .disable_memwrite = malidp550_disable_memwrite,
108783d642eeSMihail Atanassov .features = 0,
1088ad49f860SLiviu Dudau },
1089ad49f860SLiviu Dudau };
1090ad49f860SLiviu Dudau
malidp_hw_get_format_id(const struct malidp_hw_regmap * map,u8 layer_id,u32 format,bool has_modifier)1091ad49f860SLiviu Dudau u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
10925e290226SAyan Kumar Halder u8 layer_id, u32 format, bool has_modifier)
1093ad49f860SLiviu Dudau {
1094ad49f860SLiviu Dudau unsigned int i;
1095ad49f860SLiviu Dudau
10966211b486SBrian Starkey for (i = 0; i < map->n_pixel_formats; i++) {
10976211b486SBrian Starkey if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
10985e290226SAyan Kumar Halder (map->pixel_formats[i].format == format)) {
10995e290226SAyan Kumar Halder /*
11005e290226SAyan Kumar Halder * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
11015e290226SAyan Kumar Halder * is supported by a different h/w format id than
11025e290226SAyan Kumar Halder * DRM_FORMAT_YUYV (only).
11035e290226SAyan Kumar Halder */
11045e290226SAyan Kumar Halder if (format == DRM_FORMAT_YUYV &&
11055e290226SAyan Kumar Halder (has_modifier) &&
11065e290226SAyan Kumar Halder (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
11075e290226SAyan Kumar Halder return AFBC_YUV_422_FORMAT_ID;
11085e290226SAyan Kumar Halder else
11096211b486SBrian Starkey return map->pixel_formats[i].id;
1110ad49f860SLiviu Dudau }
11115e290226SAyan Kumar Halder }
1112ad49f860SLiviu Dudau
1113ad49f860SLiviu Dudau return MALIDP_INVALID_FORMAT_ID;
1114ad49f860SLiviu Dudau }
1115ad49f860SLiviu Dudau
malidp_hw_format_is_linear_only(u32 format)11165e290226SAyan Kumar Halder bool malidp_hw_format_is_linear_only(u32 format)
11175e290226SAyan Kumar Halder {
11185e290226SAyan Kumar Halder switch (format) {
11195e290226SAyan Kumar Halder case DRM_FORMAT_ARGB2101010:
11205e290226SAyan Kumar Halder case DRM_FORMAT_RGBA1010102:
11215e290226SAyan Kumar Halder case DRM_FORMAT_BGRA1010102:
11225e290226SAyan Kumar Halder case DRM_FORMAT_ARGB8888:
11235e290226SAyan Kumar Halder case DRM_FORMAT_RGBA8888:
11245e290226SAyan Kumar Halder case DRM_FORMAT_BGRA8888:
11255e290226SAyan Kumar Halder case DRM_FORMAT_XBGR8888:
11265e290226SAyan Kumar Halder case DRM_FORMAT_XRGB8888:
11275e290226SAyan Kumar Halder case DRM_FORMAT_RGBX8888:
11285e290226SAyan Kumar Halder case DRM_FORMAT_BGRX8888:
11295e290226SAyan Kumar Halder case DRM_FORMAT_RGB888:
11305e290226SAyan Kumar Halder case DRM_FORMAT_RGB565:
11315e290226SAyan Kumar Halder case DRM_FORMAT_ARGB1555:
11325e290226SAyan Kumar Halder case DRM_FORMAT_RGBA5551:
11335e290226SAyan Kumar Halder case DRM_FORMAT_BGRA5551:
11345e290226SAyan Kumar Halder case DRM_FORMAT_UYVY:
11355e290226SAyan Kumar Halder case DRM_FORMAT_XYUV8888:
11365e290226SAyan Kumar Halder case DRM_FORMAT_XVYU2101010:
11375e290226SAyan Kumar Halder case DRM_FORMAT_X0L2:
11385e290226SAyan Kumar Halder case DRM_FORMAT_X0L0:
11395e290226SAyan Kumar Halder return true;
11405e290226SAyan Kumar Halder default:
11415e290226SAyan Kumar Halder return false;
11425e290226SAyan Kumar Halder }
11435e290226SAyan Kumar Halder }
11445e290226SAyan Kumar Halder
malidp_hw_format_is_afbc_only(u32 format)11455e290226SAyan Kumar Halder bool malidp_hw_format_is_afbc_only(u32 format)
11465e290226SAyan Kumar Halder {
11475e290226SAyan Kumar Halder switch (format) {
11485e290226SAyan Kumar Halder case DRM_FORMAT_VUY888:
11495e290226SAyan Kumar Halder case DRM_FORMAT_VUY101010:
11505e290226SAyan Kumar Halder case DRM_FORMAT_YUV420_8BIT:
11515e290226SAyan Kumar Halder case DRM_FORMAT_YUV420_10BIT:
11525e290226SAyan Kumar Halder return true;
11535e290226SAyan Kumar Halder default:
11545e290226SAyan Kumar Halder return false;
11555e290226SAyan Kumar Halder }
11565e290226SAyan Kumar Halder }
11575e290226SAyan Kumar Halder
malidp_hw_clear_irq(struct malidp_hw_device * hwdev,u8 block,u32 irq)1158ad49f860SLiviu Dudau static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1159ad49f860SLiviu Dudau {
1160ad49f860SLiviu Dudau u32 base = malidp_get_block_base(hwdev, block);
1161ad49f860SLiviu Dudau
1162a6993b21SLiviu Dudau if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1163ad49f860SLiviu Dudau malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1164ad49f860SLiviu Dudau else
1165ad49f860SLiviu Dudau malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1166ad49f860SLiviu Dudau }
1167ad49f860SLiviu Dudau
malidp_de_irq(int irq,void * arg)1168ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq(int irq, void *arg)
1169ad49f860SLiviu Dudau {
1170ad49f860SLiviu Dudau struct drm_device *drm = arg;
1171*1b93d3cbSDanilo Krummrich struct malidp_drm *malidp = drm_to_malidp(drm);
1172ad49f860SLiviu Dudau struct malidp_hw_device *hwdev;
1173a6993b21SLiviu Dudau struct malidp_hw *hw;
1174ad49f860SLiviu Dudau const struct malidp_irq_map *de;
1175ad49f860SLiviu Dudau u32 status, mask, dc_status;
1176ad49f860SLiviu Dudau irqreturn_t ret = IRQ_NONE;
1177ad49f860SLiviu Dudau
1178ad49f860SLiviu Dudau hwdev = malidp->dev;
1179a6993b21SLiviu Dudau hw = hwdev->hw;
1180a6993b21SLiviu Dudau de = &hw->map.de_irq_map;
1181ad49f860SLiviu Dudau
11820df34a80SLiviu Dudau /*
11830df34a80SLiviu Dudau * if we are suspended it is likely that we were invoked because
11840df34a80SLiviu Dudau * we share an interrupt line with some other driver, don't try
11850df34a80SLiviu Dudau * to read the hardware registers
11860df34a80SLiviu Dudau */
11870df34a80SLiviu Dudau if (hwdev->pm_suspended)
11880df34a80SLiviu Dudau return IRQ_NONE;
11890df34a80SLiviu Dudau
1190ad49f860SLiviu Dudau /* first handle the config valid IRQ */
1191a6993b21SLiviu Dudau dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1192a6993b21SLiviu Dudau if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1193ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1194d862b2d6SLiviu Dudau /* do we have a page flip event? */
1195d862b2d6SLiviu Dudau if (malidp->event != NULL) {
1196d862b2d6SLiviu Dudau spin_lock(&drm->event_lock);
1197d862b2d6SLiviu Dudau drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1198d862b2d6SLiviu Dudau malidp->event = NULL;
1199d862b2d6SLiviu Dudau spin_unlock(&drm->event_lock);
1200d862b2d6SLiviu Dudau }
12011cb3cbe7SLiviu Dudau atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1202ad49f860SLiviu Dudau ret = IRQ_WAKE_THREAD;
1203ad49f860SLiviu Dudau }
1204ad49f860SLiviu Dudau
1205ad49f860SLiviu Dudau status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1206ad49f860SLiviu Dudau if (!(status & de->irq_mask))
1207ad49f860SLiviu Dudau return ret;
1208ad49f860SLiviu Dudau
1209ad49f860SLiviu Dudau mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1210613c5c7fSAlexandru Gheorghe /* keep the status of the enabled interrupts, plus the error bits */
1211613c5c7fSAlexandru Gheorghe status &= (mask | de->err_mask);
1212d862b2d6SLiviu Dudau if ((status & de->vsync_irq) && malidp->crtc.enabled)
1213ad49f860SLiviu Dudau drm_crtc_handle_vblank(&malidp->crtc);
1214ad49f860SLiviu Dudau
1215613c5c7fSAlexandru Gheorghe #ifdef CONFIG_DEBUG_FS
1216613c5c7fSAlexandru Gheorghe if (status & de->err_mask) {
1217613c5c7fSAlexandru Gheorghe malidp_error(malidp, &malidp->de_errors, status,
1218613c5c7fSAlexandru Gheorghe drm_crtc_vblank_count(&malidp->crtc));
1219613c5c7fSAlexandru Gheorghe }
1220613c5c7fSAlexandru Gheorghe #endif
1221ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1222ad49f860SLiviu Dudau
1223ad49f860SLiviu Dudau return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1224ad49f860SLiviu Dudau }
1225ad49f860SLiviu Dudau
malidp_de_irq_thread_handler(int irq,void * arg)1226ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1227ad49f860SLiviu Dudau {
1228ad49f860SLiviu Dudau struct drm_device *drm = arg;
1229*1b93d3cbSDanilo Krummrich struct malidp_drm *malidp = drm_to_malidp(drm);
1230ad49f860SLiviu Dudau
1231ad49f860SLiviu Dudau wake_up(&malidp->wq);
1232ad49f860SLiviu Dudau
1233ad49f860SLiviu Dudau return IRQ_HANDLED;
1234ad49f860SLiviu Dudau }
1235ad49f860SLiviu Dudau
malidp_de_irq_hw_init(struct malidp_hw_device * hwdev)1236ff8fc26aSAyan Kumar Halder void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1237ff8fc26aSAyan Kumar Halder {
1238ff8fc26aSAyan Kumar Halder /* ensure interrupts are disabled */
1239ff8fc26aSAyan Kumar Halder malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1240ff8fc26aSAyan Kumar Halder malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1241ff8fc26aSAyan Kumar Halder malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1242ff8fc26aSAyan Kumar Halder malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1243ff8fc26aSAyan Kumar Halder
1244ff8fc26aSAyan Kumar Halder /* first enable the DC block IRQs */
1245ff8fc26aSAyan Kumar Halder malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1246ff8fc26aSAyan Kumar Halder hwdev->hw->map.dc_irq_map.irq_mask);
1247ff8fc26aSAyan Kumar Halder
1248ff8fc26aSAyan Kumar Halder /* now enable the DE block IRQs */
1249ff8fc26aSAyan Kumar Halder malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1250ff8fc26aSAyan Kumar Halder hwdev->hw->map.de_irq_map.irq_mask);
1251ff8fc26aSAyan Kumar Halder }
1252ff8fc26aSAyan Kumar Halder
malidp_de_irq_init(struct drm_device * drm,int irq)1253ad49f860SLiviu Dudau int malidp_de_irq_init(struct drm_device *drm, int irq)
1254ad49f860SLiviu Dudau {
1255*1b93d3cbSDanilo Krummrich struct malidp_drm *malidp = drm_to_malidp(drm);
1256ad49f860SLiviu Dudau struct malidp_hw_device *hwdev = malidp->dev;
1257ad49f860SLiviu Dudau int ret;
1258ad49f860SLiviu Dudau
1259ad49f860SLiviu Dudau /* ensure interrupts are disabled */
1260ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1261ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1262ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1263ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1264ad49f860SLiviu Dudau
1265ad49f860SLiviu Dudau ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1266ad49f860SLiviu Dudau malidp_de_irq_thread_handler,
1267ad49f860SLiviu Dudau IRQF_SHARED, "malidp-de", drm);
1268ad49f860SLiviu Dudau if (ret < 0) {
1269ad49f860SLiviu Dudau DRM_ERROR("failed to install DE IRQ handler\n");
1270ad49f860SLiviu Dudau return ret;
1271ad49f860SLiviu Dudau }
1272ad49f860SLiviu Dudau
1273ff8fc26aSAyan Kumar Halder malidp_de_irq_hw_init(hwdev);
1274ad49f860SLiviu Dudau
1275ad49f860SLiviu Dudau return 0;
1276ad49f860SLiviu Dudau }
1277ad49f860SLiviu Dudau
malidp_de_irq_fini(struct malidp_hw_device * hwdev)127862862cfbSAyan Kumar Halder void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1279ad49f860SLiviu Dudau {
1280ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1281a6993b21SLiviu Dudau hwdev->hw->map.de_irq_map.irq_mask);
1282ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1283a6993b21SLiviu Dudau hwdev->hw->map.dc_irq_map.irq_mask);
1284ad49f860SLiviu Dudau }
1285ad49f860SLiviu Dudau
malidp_se_irq(int irq,void * arg)1286ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq(int irq, void *arg)
1287ad49f860SLiviu Dudau {
1288ad49f860SLiviu Dudau struct drm_device *drm = arg;
1289*1b93d3cbSDanilo Krummrich struct malidp_drm *malidp = drm_to_malidp(drm);
1290ad49f860SLiviu Dudau struct malidp_hw_device *hwdev = malidp->dev;
1291a6993b21SLiviu Dudau struct malidp_hw *hw = hwdev->hw;
1292a6993b21SLiviu Dudau const struct malidp_irq_map *se = &hw->map.se_irq_map;
1293ad49f860SLiviu Dudau u32 status, mask;
1294ad49f860SLiviu Dudau
12950df34a80SLiviu Dudau /*
12960df34a80SLiviu Dudau * if we are suspended it is likely that we were invoked because
12970df34a80SLiviu Dudau * we share an interrupt line with some other driver, don't try
12980df34a80SLiviu Dudau * to read the hardware registers
12990df34a80SLiviu Dudau */
13000df34a80SLiviu Dudau if (hwdev->pm_suspended)
13010df34a80SLiviu Dudau return IRQ_NONE;
13020df34a80SLiviu Dudau
1303a6993b21SLiviu Dudau status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1304613c5c7fSAlexandru Gheorghe if (!(status & (se->irq_mask | se->err_mask)))
1305ad49f860SLiviu Dudau return IRQ_NONE;
1306ad49f860SLiviu Dudau
1307613c5c7fSAlexandru Gheorghe #ifdef CONFIG_DEBUG_FS
1308613c5c7fSAlexandru Gheorghe if (status & se->err_mask)
1309613c5c7fSAlexandru Gheorghe malidp_error(malidp, &malidp->se_errors, status,
1310613c5c7fSAlexandru Gheorghe drm_crtc_vblank_count(&malidp->crtc));
1311613c5c7fSAlexandru Gheorghe #endif
1312a6993b21SLiviu Dudau mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1313ad49f860SLiviu Dudau status &= mask;
13141cb3cbe7SLiviu Dudau
13151cb3cbe7SLiviu Dudau if (status & se->vsync_irq) {
13161cb3cbe7SLiviu Dudau switch (hwdev->mw_state) {
13178cbc5cafSBrian Starkey case MW_ONESHOT:
13188cbc5cafSBrian Starkey drm_writeback_signal_completion(&malidp->mw_connector, 0);
13198cbc5cafSBrian Starkey break;
13201cb3cbe7SLiviu Dudau case MW_STOP:
13218cbc5cafSBrian Starkey drm_writeback_signal_completion(&malidp->mw_connector, 0);
13221cb3cbe7SLiviu Dudau /* disable writeback after stop */
13231cb3cbe7SLiviu Dudau hwdev->mw_state = MW_NOT_ENABLED;
13241cb3cbe7SLiviu Dudau break;
13250735cfdfSLiviu Dudau case MW_RESTART:
13260735cfdfSLiviu Dudau drm_writeback_signal_completion(&malidp->mw_connector, 0);
1327df561f66SGustavo A. R. Silva fallthrough; /* to a new start */
13281cb3cbe7SLiviu Dudau case MW_START:
13291cb3cbe7SLiviu Dudau /* writeback started, need to emulate one-shot mode */
13301cb3cbe7SLiviu Dudau hw->disable_memwrite(hwdev);
13311cb3cbe7SLiviu Dudau /*
13320735cfdfSLiviu Dudau * only set config_valid HW bit if there is no other update
13330735cfdfSLiviu Dudau * in progress or if we raced ahead of the DE IRQ handler
13340735cfdfSLiviu Dudau * and config_valid flag will not be update until later
13351cb3cbe7SLiviu Dudau */
13360735cfdfSLiviu Dudau status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
13370735cfdfSLiviu Dudau if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
13380735cfdfSLiviu Dudau (status & hw->map.dc_irq_map.vsync_irq))
13390735cfdfSLiviu Dudau hw->set_config_valid(hwdev, 1);
13401cb3cbe7SLiviu Dudau break;
13411cb3cbe7SLiviu Dudau }
13421cb3cbe7SLiviu Dudau }
1343ad49f860SLiviu Dudau
1344ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1345ad49f860SLiviu Dudau
1346ad49f860SLiviu Dudau return IRQ_HANDLED;
1347ad49f860SLiviu Dudau }
1348ad49f860SLiviu Dudau
malidp_se_irq_hw_init(struct malidp_hw_device * hwdev)1349ff8fc26aSAyan Kumar Halder void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1350ff8fc26aSAyan Kumar Halder {
1351ff8fc26aSAyan Kumar Halder /* ensure interrupts are disabled */
1352ff8fc26aSAyan Kumar Halder malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1353ff8fc26aSAyan Kumar Halder malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1354ff8fc26aSAyan Kumar Halder
1355ff8fc26aSAyan Kumar Halder malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1356ff8fc26aSAyan Kumar Halder hwdev->hw->map.se_irq_map.irq_mask);
1357ff8fc26aSAyan Kumar Halder }
1358ff8fc26aSAyan Kumar Halder
malidp_se_irq_thread_handler(int irq,void * arg)1359ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1360ad49f860SLiviu Dudau {
1361ad49f860SLiviu Dudau return IRQ_HANDLED;
1362ad49f860SLiviu Dudau }
1363ad49f860SLiviu Dudau
malidp_se_irq_init(struct drm_device * drm,int irq)1364ad49f860SLiviu Dudau int malidp_se_irq_init(struct drm_device *drm, int irq)
1365ad49f860SLiviu Dudau {
1366*1b93d3cbSDanilo Krummrich struct malidp_drm *malidp = drm_to_malidp(drm);
1367ad49f860SLiviu Dudau struct malidp_hw_device *hwdev = malidp->dev;
1368ad49f860SLiviu Dudau int ret;
1369ad49f860SLiviu Dudau
1370ad49f860SLiviu Dudau /* ensure interrupts are disabled */
1371ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1372ad49f860SLiviu Dudau malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1373ad49f860SLiviu Dudau
1374ad49f860SLiviu Dudau ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1375ad49f860SLiviu Dudau malidp_se_irq_thread_handler,
1376ad49f860SLiviu Dudau IRQF_SHARED, "malidp-se", drm);
1377ad49f860SLiviu Dudau if (ret < 0) {
1378ad49f860SLiviu Dudau DRM_ERROR("failed to install SE IRQ handler\n");
1379ad49f860SLiviu Dudau return ret;
1380ad49f860SLiviu Dudau }
1381ad49f860SLiviu Dudau
13821cb3cbe7SLiviu Dudau hwdev->mw_state = MW_NOT_ENABLED;
1383ff8fc26aSAyan Kumar Halder malidp_se_irq_hw_init(hwdev);
1384ad49f860SLiviu Dudau
1385ad49f860SLiviu Dudau return 0;
1386ad49f860SLiviu Dudau }
1387ad49f860SLiviu Dudau
malidp_se_irq_fini(struct malidp_hw_device * hwdev)138862862cfbSAyan Kumar Halder void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1389ad49f860SLiviu Dudau {
1390ad49f860SLiviu Dudau malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1391a6993b21SLiviu Dudau hwdev->hw->map.se_irq_map.irq_mask);
1392ad49f860SLiviu Dudau }
1393