1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. 4 * Author: Liviu Dudau <Liviu.Dudau@arm.com> 5 * 6 * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where 7 * the difference between various versions of the hardware is being dealt with 8 * in an attempt to provide to the rest of the driver code a unified view 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/types.h> 13 #include <linux/io.h> 14 #include <drm/drmP.h> 15 #include <video/videomode.h> 16 #include <video/display_timing.h> 17 18 #include "malidp_drv.h" 19 #include "malidp_hw.h" 20 #include "malidp_mw.h" 21 22 enum { 23 MW_NOT_ENABLED = 0, /* SE writeback not enabled */ 24 MW_ONESHOT, /* SE in one-shot mode for writeback */ 25 MW_START, /* SE started writeback */ 26 MW_RESTART, /* SE will start another writeback after this one */ 27 MW_STOP, /* SE needs to stop after this writeback */ 28 }; 29 30 static const struct malidp_format_id malidp500_de_formats[] = { 31 /* fourcc, layers supporting the format, internal id */ 32 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 0 }, 33 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 1 }, 34 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 2 }, 35 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 3 }, 36 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 4 }, 37 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 5 }, 38 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 6 }, 39 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 7 }, 40 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 8 }, 41 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 9 }, 42 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 }, 43 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 }, 44 { DRM_FORMAT_UYVY, DE_VIDEO1, 12 }, 45 { DRM_FORMAT_YUYV, DE_VIDEO1, 13 }, 46 { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 }, 47 { DRM_FORMAT_YUV420, DE_VIDEO1, 15 }, 48 { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 }, 49 /* These are supported with AFBC only */ 50 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 }, 51 { DRM_FORMAT_VUY888, DE_VIDEO1, 16 }, 52 { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 }, 53 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 } 54 }; 55 56 #define MALIDP_ID(__group, __format) \ 57 ((((__group) & 0x7) << 3) | ((__format) & 0x7)) 58 59 #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1) 60 61 #define MALIDP_COMMON_FORMATS \ 62 /* fourcc, layers supporting the format, internal id */ \ 63 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \ 64 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \ 65 { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \ 66 { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \ 67 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \ 68 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \ 69 { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \ 70 { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \ 71 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \ 72 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \ 73 { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \ 74 { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \ 75 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \ 76 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \ 77 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \ 78 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \ 79 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \ 80 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \ 81 /* This is only supported with linear modifier */ \ 82 { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\ 83 /* This is only supported with AFBC modifier */ \ 84 { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \ 85 { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \ 86 /* This is only supported with linear modifier */ \ 87 { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \ 88 { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \ 89 /* This is only supported with AFBC modifier */ \ 90 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \ 91 { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \ 92 /* This is only supported with linear modifier */ \ 93 { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \ 94 /* This is only supported with AFBC modifier */ \ 95 { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \ 96 { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \ 97 /* This is only supported with AFBC modifier */ \ 98 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \ 99 { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)} 100 101 static const struct malidp_format_id malidp550_de_formats[] = { 102 MALIDP_COMMON_FORMATS, 103 }; 104 105 static const struct malidp_format_id malidp650_de_formats[] = { 106 MALIDP_COMMON_FORMATS, 107 { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)}, 108 }; 109 110 static const struct malidp_layer malidp500_layers[] = { 111 /* id, base address, fb pointer address base, stride offset, 112 * yuv2rgb matrix offset, mmu control register offset, rotation_features 113 */ 114 { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, 115 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY, 116 MALIDP500_DE_LV_AD_CTRL }, 117 { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, 118 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, 119 MALIDP500_DE_LG1_AD_CTRL }, 120 { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, 121 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, 122 MALIDP500_DE_LG2_AD_CTRL }, 123 }; 124 125 static const struct malidp_layer malidp550_layers[] = { 126 /* id, base address, fb pointer address base, stride offset, 127 * yuv2rgb matrix offset, mmu control register offset, rotation_features 128 */ 129 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, 130 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY, 131 MALIDP550_DE_LV1_AD_CTRL }, 132 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, 133 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, 134 MALIDP550_DE_LG_AD_CTRL }, 135 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, 136 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY, 137 MALIDP550_DE_LV2_AD_CTRL }, 138 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 139 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 }, 140 }; 141 142 static const struct malidp_layer malidp650_layers[] = { 143 /* id, base address, fb pointer address base, stride offset, 144 * yuv2rgb matrix offset, mmu control register offset, 145 * rotation_features 146 */ 147 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, 148 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 149 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, 150 MALIDP550_DE_LV1_AD_CTRL }, 151 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, 152 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL, 153 ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL }, 154 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, 155 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 156 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, 157 MALIDP550_DE_LV2_AD_CTRL }, 158 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 159 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL, 160 ROTATE_NONE, 0 }, 161 }; 162 163 const u64 malidp_format_modifiers[] = { 164 /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */ 165 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE), 166 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR), 167 168 /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */ 169 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT), 170 171 /* All 8 or 10 bit YUV 444 formats. */ 172 /* In DP550, 10 bit YUV 420 format also supported */ 173 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT), 174 175 /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */ 176 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE), 177 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16), 178 179 /* YUV 420, 422 P1 8, 10 bit formats */ 180 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE), 181 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR), 182 183 /* All formats */ 184 DRM_FORMAT_MOD_LINEAR, 185 186 DRM_FORMAT_MOD_INVALID 187 }; 188 189 #define SE_N_SCALING_COEFFS 96 190 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = { 191 [MALIDP_UPSCALING_COEFFS - 1] = { 192 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052, 193 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f, 194 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a, 195 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40, 196 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c, 197 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5, 198 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15, 199 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5, 200 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0, 201 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6, 202 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073, 203 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001 204 }, 205 [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = { 206 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4, 207 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c, 208 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5, 209 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8, 210 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba, 211 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20, 212 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03, 213 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d, 214 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68, 215 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f, 216 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62, 217 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f 218 }, 219 [MALIDP_DOWNSCALING_2_COEFFS - 1] = { 220 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9, 221 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52, 222 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158, 223 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455, 224 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e, 225 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887, 226 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5, 227 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e, 228 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d, 229 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0, 230 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf, 231 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03 232 }, 233 [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = { 234 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3, 235 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106, 236 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280, 237 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410, 238 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533, 239 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3, 240 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566, 241 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468, 242 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4, 243 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160, 244 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f, 245 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60 246 }, 247 [MALIDP_DOWNSCALING_4_COEFFS - 1] = { 248 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f, 249 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff, 250 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd, 251 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374, 252 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db, 253 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a, 254 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed, 255 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397, 256 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb, 257 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233, 258 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160, 259 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9 260 }, 261 }; 262 263 #define MALIDP_DE_DEFAULT_PREFETCH_START 5 264 265 static int malidp500_query_hw(struct malidp_hw_device *hwdev) 266 { 267 u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID); 268 /* bit 4 of the CONFIG_ID register holds the line size multiplier */ 269 u8 ln_size_mult = conf & 0x10 ? 2 : 1; 270 271 hwdev->min_line_size = 2; 272 hwdev->max_line_size = SZ_2K * ln_size_mult; 273 hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult; 274 hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */ 275 276 return 0; 277 } 278 279 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev) 280 { 281 u32 status, count = 100; 282 283 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); 284 while (count) { 285 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 286 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ) 287 break; 288 /* 289 * entering config mode can take as long as the rendering 290 * of a full frame, hence the long sleep here 291 */ 292 usleep_range(1000, 10000); 293 count--; 294 } 295 WARN(count == 0, "timeout while entering config mode"); 296 } 297 298 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev) 299 { 300 u32 status, count = 100; 301 302 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID); 303 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); 304 while (count) { 305 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 306 if ((status & MALIDP500_DC_CONFIG_REQ) == 0) 307 break; 308 usleep_range(100, 1000); 309 count--; 310 } 311 WARN(count == 0, "timeout while leaving config mode"); 312 } 313 314 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev) 315 { 316 u32 status; 317 318 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 319 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ) 320 return true; 321 322 return false; 323 } 324 325 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value) 326 { 327 if (value) 328 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID); 329 else 330 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID); 331 } 332 333 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode) 334 { 335 u32 val = 0; 336 337 malidp_hw_write(hwdev, hwdev->output_color_depth, 338 hwdev->hw->map.out_depth_base); 339 malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL); 340 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH) 341 val |= MALIDP500_HSYNCPOL; 342 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH) 343 val |= MALIDP500_VSYNCPOL; 344 val |= MALIDP_DE_DEFAULT_PREFETCH_START; 345 malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL); 346 347 /* 348 * Mali-DP500 encodes the background color like this: 349 * - red @ MALIDP500_BGND_COLOR[12:0] 350 * - green @ MALIDP500_BGND_COLOR[27:16] 351 * - blue @ (MALIDP500_BGND_COLOR + 4)[12:0] 352 */ 353 val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) | 354 (MALIDP_BGND_COLOR_R & 0xfff); 355 malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR); 356 malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4); 357 358 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) | 359 MALIDP_DE_H_BACKPORCH(mode->hback_porch); 360 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS); 361 362 val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) | 363 MALIDP_DE_V_BACKPORCH(mode->vback_porch); 364 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS); 365 366 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) | 367 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len); 368 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH); 369 370 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive); 371 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE); 372 373 if (mode->flags & DISPLAY_FLAGS_INTERLACED) 374 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 375 else 376 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 377 } 378 379 int malidp_format_get_bpp(u32 fmt) 380 { 381 int bpp = drm_format_plane_cpp(fmt, 0) * 8; 382 383 if (bpp == 0) { 384 switch (fmt) { 385 case DRM_FORMAT_VUY101010: 386 bpp = 30; 387 case DRM_FORMAT_YUV420_10BIT: 388 bpp = 15; 389 break; 390 case DRM_FORMAT_YUV420_8BIT: 391 bpp = 12; 392 break; 393 default: 394 bpp = 0; 395 } 396 } 397 398 return bpp; 399 } 400 401 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 402 u16 h, u32 fmt, bool has_modifier) 403 { 404 /* 405 * Each layer needs enough rotation memory to fit 8 lines 406 * worth of pixel data. Required size is then: 407 * size = rotated_width * (bpp / 8) * 8; 408 */ 409 int bpp = malidp_format_get_bpp(fmt); 410 411 return w * bpp; 412 } 413 414 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev, 415 u32 direction, 416 u16 addr, 417 u8 coeffs_id) 418 { 419 int i; 420 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL; 421 422 malidp_hw_write(hwdev, 423 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK), 424 scaling_control + MALIDP_SE_COEFFTAB_ADDR); 425 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i) 426 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA( 427 dp500_se_scaling_coeffs[coeffs_id][i]), 428 scaling_control + MALIDP_SE_COEFFTAB_DATA); 429 } 430 431 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 432 struct malidp_se_config *se_config, 433 struct malidp_se_config *old_config) 434 { 435 /* Get array indices into dp500_se_scaling_coeffs. */ 436 u8 h = (u8)se_config->hcoeff - 1; 437 u8 v = (u8)se_config->vcoeff - 1; 438 439 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) || 440 v >= ARRAY_SIZE(dp500_se_scaling_coeffs))) 441 return -EINVAL; 442 443 if ((h == v) && (se_config->hcoeff != old_config->hcoeff || 444 se_config->vcoeff != old_config->vcoeff)) { 445 malidp500_se_write_pp_coefftab(hwdev, 446 (MALIDP_SE_V_COEFFTAB | 447 MALIDP_SE_H_COEFFTAB), 448 0, v); 449 } else { 450 if (se_config->vcoeff != old_config->vcoeff) 451 malidp500_se_write_pp_coefftab(hwdev, 452 MALIDP_SE_V_COEFFTAB, 453 0, v); 454 if (se_config->hcoeff != old_config->hcoeff) 455 malidp500_se_write_pp_coefftab(hwdev, 456 MALIDP_SE_H_COEFFTAB, 457 0, h); 458 } 459 460 return 0; 461 } 462 463 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, 464 struct malidp_se_config *se_config, 465 struct videomode *vm) 466 { 467 unsigned long mclk; 468 unsigned long pxlclk = vm->pixelclock; /* Hz */ 469 unsigned long htotal = vm->hactive + vm->hfront_porch + 470 vm->hback_porch + vm->hsync_len; 471 unsigned long input_size = se_config->input_w * se_config->input_h; 472 unsigned long a = 10; 473 long ret; 474 475 /* 476 * mclk = max(a, 1.5) * pxlclk 477 * 478 * To avoid float calculaiton, using 15 instead of 1.5 and div by 479 * 10 to get mclk. 480 */ 481 if (se_config->scale_enable) { 482 a = 15 * input_size / (htotal * se_config->output_h); 483 if (a < 15) 484 a = 15; 485 } 486 mclk = a * pxlclk / 10; 487 ret = clk_get_rate(hwdev->mclk); 488 if (ret < mclk) { 489 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", 490 mclk / 1000); 491 return -EINVAL; 492 } 493 return ret; 494 } 495 496 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, 497 dma_addr_t *addrs, s32 *pitches, 498 int num_planes, u16 w, u16 h, u32 fmt_id, 499 const s16 *rgb2yuv_coeffs) 500 { 501 u32 base = MALIDP500_SE_MEMWRITE_BASE; 502 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 503 504 /* enable the scaling engine block */ 505 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); 506 507 /* restart the writeback if already enabled */ 508 if (hwdev->mw_state != MW_NOT_ENABLED) 509 hwdev->mw_state = MW_RESTART; 510 else 511 hwdev->mw_state = MW_START; 512 513 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); 514 switch (num_planes) { 515 case 2: 516 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); 517 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); 518 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); 519 /* fall through */ 520 case 1: 521 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); 522 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); 523 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE); 524 break; 525 default: 526 WARN(1, "Invalid number of planes"); 527 } 528 529 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), 530 MALIDP500_SE_MEMWRITE_OUT_SIZE); 531 532 if (rgb2yuv_coeffs) { 533 int i; 534 535 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { 536 malidp_hw_write(hwdev, rgb2yuv_coeffs[i], 537 MALIDP500_SE_RGB_YUV_COEFFS + i * 4); 538 } 539 } 540 541 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); 542 543 return 0; 544 } 545 546 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev) 547 { 548 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 549 550 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART) 551 hwdev->mw_state = MW_STOP; 552 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); 553 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC); 554 } 555 556 static int malidp550_query_hw(struct malidp_hw_device *hwdev) 557 { 558 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 559 u8 ln_size = (conf >> 4) & 0x3, rsize; 560 561 hwdev->min_line_size = 2; 562 563 switch (ln_size) { 564 case 0: 565 hwdev->max_line_size = SZ_2K; 566 /* two banks of 64KB for rotation memory */ 567 rsize = 64; 568 break; 569 case 1: 570 hwdev->max_line_size = SZ_4K; 571 /* two banks of 128KB for rotation memory */ 572 rsize = 128; 573 break; 574 case 2: 575 hwdev->max_line_size = 1280; 576 /* two banks of 40KB for rotation memory */ 577 rsize = 40; 578 break; 579 case 3: 580 /* reserved value */ 581 hwdev->max_line_size = 0; 582 return -EINVAL; 583 } 584 585 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K; 586 return 0; 587 } 588 589 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev) 590 { 591 u32 status, count = 100; 592 593 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 594 while (count) { 595 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 596 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ) 597 break; 598 /* 599 * entering config mode can take as long as the rendering 600 * of a full frame, hence the long sleep here 601 */ 602 usleep_range(1000, 10000); 603 count--; 604 } 605 WARN(count == 0, "timeout while entering config mode"); 606 } 607 608 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev) 609 { 610 u32 status, count = 100; 611 612 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 613 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 614 while (count) { 615 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 616 if ((status & MALIDP550_DC_CONFIG_REQ) == 0) 617 break; 618 usleep_range(100, 1000); 619 count--; 620 } 621 WARN(count == 0, "timeout while leaving config mode"); 622 } 623 624 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev) 625 { 626 u32 status; 627 628 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 629 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ) 630 return true; 631 632 return false; 633 } 634 635 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value) 636 { 637 if (value) 638 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 639 else 640 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 641 } 642 643 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode) 644 { 645 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START; 646 647 malidp_hw_write(hwdev, hwdev->output_color_depth, 648 hwdev->hw->map.out_depth_base); 649 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL); 650 /* 651 * Mali-DP550 and Mali-DP650 encode the background color like this: 652 * - red @ MALIDP550_DE_BGND_COLOR[23:16] 653 * - green @ MALIDP550_DE_BGND_COLOR[15:8] 654 * - blue @ MALIDP550_DE_BGND_COLOR[7:0] 655 * 656 * We need to truncate the least significant 4 bits from the default 657 * MALIDP_BGND_COLOR_x values 658 */ 659 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) | 660 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) | 661 ((MALIDP_BGND_COLOR_B >> 4) & 0xff); 662 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR); 663 664 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) | 665 MALIDP_DE_H_BACKPORCH(mode->hback_porch); 666 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS); 667 668 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) | 669 MALIDP_DE_V_BACKPORCH(mode->vback_porch); 670 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS); 671 672 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) | 673 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len); 674 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH) 675 val |= MALIDP550_HSYNCPOL; 676 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH) 677 val |= MALIDP550_VSYNCPOL; 678 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH); 679 680 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive); 681 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE); 682 683 if (mode->flags & DISPLAY_FLAGS_INTERLACED) 684 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 685 else 686 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 687 } 688 689 static int malidpx50_get_bytes_per_column(u32 fmt) 690 { 691 u32 bytes_per_column; 692 693 switch (fmt) { 694 /* 8 lines at 4 bytes per pixel */ 695 case DRM_FORMAT_ARGB2101010: 696 case DRM_FORMAT_ABGR2101010: 697 case DRM_FORMAT_RGBA1010102: 698 case DRM_FORMAT_BGRA1010102: 699 case DRM_FORMAT_ARGB8888: 700 case DRM_FORMAT_ABGR8888: 701 case DRM_FORMAT_RGBA8888: 702 case DRM_FORMAT_BGRA8888: 703 case DRM_FORMAT_XRGB8888: 704 case DRM_FORMAT_XBGR8888: 705 case DRM_FORMAT_RGBX8888: 706 case DRM_FORMAT_BGRX8888: 707 case DRM_FORMAT_RGB888: 708 case DRM_FORMAT_BGR888: 709 /* 16 lines at 2 bytes per pixel */ 710 case DRM_FORMAT_RGBA5551: 711 case DRM_FORMAT_ABGR1555: 712 case DRM_FORMAT_RGB565: 713 case DRM_FORMAT_BGR565: 714 case DRM_FORMAT_UYVY: 715 case DRM_FORMAT_YUYV: 716 case DRM_FORMAT_X0L0: 717 bytes_per_column = 32; 718 break; 719 /* 16 lines at 1.5 bytes per pixel */ 720 case DRM_FORMAT_NV12: 721 case DRM_FORMAT_YUV420: 722 /* 8 lines at 3 bytes per pixel */ 723 case DRM_FORMAT_VUY888: 724 /* 16 lines at 12 bits per pixel */ 725 case DRM_FORMAT_YUV420_8BIT: 726 /* 8 lines at 3 bytes per pixel */ 727 case DRM_FORMAT_P010: 728 bytes_per_column = 24; 729 break; 730 /* 8 lines at 30 bits per pixel */ 731 case DRM_FORMAT_VUY101010: 732 /* 16 lines at 15 bits per pixel */ 733 case DRM_FORMAT_YUV420_10BIT: 734 bytes_per_column = 30; 735 break; 736 default: 737 return -EINVAL; 738 } 739 740 return bytes_per_column; 741 } 742 743 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 744 u16 h, u32 fmt, bool has_modifier) 745 { 746 int bytes_per_column = 0; 747 748 switch (fmt) { 749 /* 8 lines at 15 bits per pixel */ 750 case DRM_FORMAT_YUV420_10BIT: 751 bytes_per_column = 15; 752 break; 753 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */ 754 case DRM_FORMAT_X0L2: 755 if (has_modifier) 756 bytes_per_column = 8; 757 else 758 return -EINVAL; 759 break; 760 default: 761 bytes_per_column = malidpx50_get_bytes_per_column(fmt); 762 } 763 764 if (bytes_per_column == -EINVAL) 765 return bytes_per_column; 766 767 return w * bytes_per_column; 768 } 769 770 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 771 u16 h, u32 fmt, bool has_modifier) 772 { 773 int bytes_per_column = 0; 774 775 switch (fmt) { 776 /* 16 lines at 2 bytes per pixel */ 777 case DRM_FORMAT_X0L2: 778 bytes_per_column = 32; 779 break; 780 default: 781 bytes_per_column = malidpx50_get_bytes_per_column(fmt); 782 } 783 784 if (bytes_per_column == -EINVAL) 785 return bytes_per_column; 786 787 return w * bytes_per_column; 788 } 789 790 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 791 struct malidp_se_config *se_config, 792 struct malidp_se_config *old_config) 793 { 794 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) | 795 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK); 796 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) | 797 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff); 798 799 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL); 800 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL); 801 return 0; 802 } 803 804 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev, 805 struct malidp_se_config *se_config, 806 struct videomode *vm) 807 { 808 unsigned long mclk; 809 unsigned long pxlclk = vm->pixelclock; 810 unsigned long htotal = vm->hactive + vm->hfront_porch + 811 vm->hback_porch + vm->hsync_len; 812 unsigned long numerator = 1, denominator = 1; 813 long ret; 814 815 if (se_config->scale_enable) { 816 numerator = max(se_config->input_w, se_config->output_w) * 817 se_config->input_h; 818 numerator += se_config->output_w * 819 (se_config->output_h - 820 min(se_config->input_h, se_config->output_h)); 821 denominator = (htotal - 2) * se_config->output_h; 822 } 823 824 /* mclk can't be slower than pxlclk. */ 825 if (numerator < denominator) 826 numerator = denominator = 1; 827 mclk = (pxlclk * numerator) / denominator; 828 ret = clk_get_rate(hwdev->mclk); 829 if (ret < mclk) { 830 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", 831 mclk / 1000); 832 return -EINVAL; 833 } 834 return ret; 835 } 836 837 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, 838 dma_addr_t *addrs, s32 *pitches, 839 int num_planes, u16 w, u16 h, u32 fmt_id, 840 const s16 *rgb2yuv_coeffs) 841 { 842 u32 base = MALIDP550_SE_MEMWRITE_BASE; 843 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 844 845 /* enable the scaling engine block */ 846 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); 847 848 hwdev->mw_state = MW_ONESHOT; 849 850 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); 851 switch (num_planes) { 852 case 2: 853 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); 854 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); 855 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); 856 /* fall through */ 857 case 1: 858 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); 859 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); 860 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE); 861 break; 862 default: 863 WARN(1, "Invalid number of planes"); 864 } 865 866 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), 867 MALIDP550_SE_MEMWRITE_OUT_SIZE); 868 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, 869 MALIDP550_SE_CONTROL); 870 871 if (rgb2yuv_coeffs) { 872 int i; 873 874 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { 875 malidp_hw_write(hwdev, rgb2yuv_coeffs[i], 876 MALIDP550_SE_RGB_YUV_COEFFS + i * 4); 877 } 878 } 879 880 return 0; 881 } 882 883 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev) 884 { 885 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 886 887 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, 888 MALIDP550_SE_CONTROL); 889 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC); 890 } 891 892 static int malidp650_query_hw(struct malidp_hw_device *hwdev) 893 { 894 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 895 u8 ln_size = (conf >> 4) & 0x3, rsize; 896 897 hwdev->min_line_size = 4; 898 899 switch (ln_size) { 900 case 0: 901 case 2: 902 /* reserved values */ 903 hwdev->max_line_size = 0; 904 return -EINVAL; 905 case 1: 906 hwdev->max_line_size = SZ_4K; 907 /* two banks of 128KB for rotation memory */ 908 rsize = 128; 909 break; 910 case 3: 911 hwdev->max_line_size = 2560; 912 /* two banks of 80KB for rotation memory */ 913 rsize = 80; 914 } 915 916 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K; 917 return 0; 918 } 919 920 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { 921 [MALIDP_500] = { 922 .map = { 923 .coeffs_base = MALIDP500_COEFFS_BASE, 924 .se_base = MALIDP500_SE_BASE, 925 .dc_base = MALIDP500_DC_BASE, 926 .out_depth_base = MALIDP500_OUTPUT_DEPTH, 927 .features = 0, /* no CLEARIRQ register */ 928 .n_layers = ARRAY_SIZE(malidp500_layers), 929 .layers = malidp500_layers, 930 .de_irq_map = { 931 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 932 MALIDP500_DE_IRQ_AXI_ERR | 933 MALIDP500_DE_IRQ_VSYNC | 934 MALIDP500_DE_IRQ_GLOBAL, 935 .vsync_irq = MALIDP500_DE_IRQ_VSYNC, 936 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 937 MALIDP500_DE_IRQ_AXI_ERR | 938 MALIDP500_DE_IRQ_SATURATION, 939 }, 940 .se_irq_map = { 941 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE | 942 MALIDP500_SE_IRQ_CONF_VALID | 943 MALIDP500_SE_IRQ_GLOBAL, 944 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID, 945 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY | 946 MALIDP500_SE_IRQ_AXI_ERROR | 947 MALIDP500_SE_IRQ_OVERRUN, 948 }, 949 .dc_irq_map = { 950 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID, 951 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID, 952 }, 953 .pixel_formats = malidp500_de_formats, 954 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats), 955 .bus_align_bytes = 8, 956 }, 957 .query_hw = malidp500_query_hw, 958 .enter_config_mode = malidp500_enter_config_mode, 959 .leave_config_mode = malidp500_leave_config_mode, 960 .in_config_mode = malidp500_in_config_mode, 961 .set_config_valid = malidp500_set_config_valid, 962 .modeset = malidp500_modeset, 963 .rotmem_required = malidp500_rotmem_required, 964 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, 965 .se_calc_mclk = malidp500_se_calc_mclk, 966 .enable_memwrite = malidp500_enable_memwrite, 967 .disable_memwrite = malidp500_disable_memwrite, 968 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, 969 }, 970 [MALIDP_550] = { 971 .map = { 972 .coeffs_base = MALIDP550_COEFFS_BASE, 973 .se_base = MALIDP550_SE_BASE, 974 .dc_base = MALIDP550_DC_BASE, 975 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, 976 .features = MALIDP_REGMAP_HAS_CLEARIRQ | 977 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | 978 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT | 979 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2, 980 .n_layers = ARRAY_SIZE(malidp550_layers), 981 .layers = malidp550_layers, 982 .de_irq_map = { 983 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 984 MALIDP550_DE_IRQ_VSYNC, 985 .vsync_irq = MALIDP550_DE_IRQ_VSYNC, 986 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 987 MALIDP550_DE_IRQ_SATURATION | 988 MALIDP550_DE_IRQ_AXI_ERR, 989 }, 990 .se_irq_map = { 991 .irq_mask = MALIDP550_SE_IRQ_EOW, 992 .vsync_irq = MALIDP550_SE_IRQ_EOW, 993 .err_mask = MALIDP550_SE_IRQ_AXI_ERR | 994 MALIDP550_SE_IRQ_OVR | 995 MALIDP550_SE_IRQ_IBSY, 996 }, 997 .dc_irq_map = { 998 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID | 999 MALIDP550_DC_IRQ_SE, 1000 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, 1001 }, 1002 .pixel_formats = malidp550_de_formats, 1003 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats), 1004 .bus_align_bytes = 8, 1005 }, 1006 .query_hw = malidp550_query_hw, 1007 .enter_config_mode = malidp550_enter_config_mode, 1008 .leave_config_mode = malidp550_leave_config_mode, 1009 .in_config_mode = malidp550_in_config_mode, 1010 .set_config_valid = malidp550_set_config_valid, 1011 .modeset = malidp550_modeset, 1012 .rotmem_required = malidp550_rotmem_required, 1013 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 1014 .se_calc_mclk = malidp550_se_calc_mclk, 1015 .enable_memwrite = malidp550_enable_memwrite, 1016 .disable_memwrite = malidp550_disable_memwrite, 1017 .features = 0, 1018 }, 1019 [MALIDP_650] = { 1020 .map = { 1021 .coeffs_base = MALIDP550_COEFFS_BASE, 1022 .se_base = MALIDP550_SE_BASE, 1023 .dc_base = MALIDP550_DC_BASE, 1024 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, 1025 .features = MALIDP_REGMAP_HAS_CLEARIRQ | 1026 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | 1027 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2, 1028 .n_layers = ARRAY_SIZE(malidp650_layers), 1029 .layers = malidp650_layers, 1030 .de_irq_map = { 1031 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 1032 MALIDP650_DE_IRQ_DRIFT | 1033 MALIDP550_DE_IRQ_VSYNC, 1034 .vsync_irq = MALIDP550_DE_IRQ_VSYNC, 1035 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 1036 MALIDP650_DE_IRQ_DRIFT | 1037 MALIDP550_DE_IRQ_SATURATION | 1038 MALIDP550_DE_IRQ_AXI_ERR | 1039 MALIDP650_DE_IRQ_ACEV1 | 1040 MALIDP650_DE_IRQ_ACEV2 | 1041 MALIDP650_DE_IRQ_ACEG | 1042 MALIDP650_DE_IRQ_AXIEP, 1043 }, 1044 .se_irq_map = { 1045 .irq_mask = MALIDP550_SE_IRQ_EOW, 1046 .vsync_irq = MALIDP550_SE_IRQ_EOW, 1047 .err_mask = MALIDP550_SE_IRQ_AXI_ERR | 1048 MALIDP550_SE_IRQ_OVR | 1049 MALIDP550_SE_IRQ_IBSY, 1050 }, 1051 .dc_irq_map = { 1052 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID | 1053 MALIDP550_DC_IRQ_SE, 1054 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, 1055 }, 1056 .pixel_formats = malidp650_de_formats, 1057 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats), 1058 .bus_align_bytes = 16, 1059 }, 1060 .query_hw = malidp650_query_hw, 1061 .enter_config_mode = malidp550_enter_config_mode, 1062 .leave_config_mode = malidp550_leave_config_mode, 1063 .in_config_mode = malidp550_in_config_mode, 1064 .set_config_valid = malidp550_set_config_valid, 1065 .modeset = malidp550_modeset, 1066 .rotmem_required = malidp650_rotmem_required, 1067 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 1068 .se_calc_mclk = malidp550_se_calc_mclk, 1069 .enable_memwrite = malidp550_enable_memwrite, 1070 .disable_memwrite = malidp550_disable_memwrite, 1071 .features = 0, 1072 }, 1073 }; 1074 1075 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 1076 u8 layer_id, u32 format, bool has_modifier) 1077 { 1078 unsigned int i; 1079 1080 for (i = 0; i < map->n_pixel_formats; i++) { 1081 if (((map->pixel_formats[i].layer & layer_id) == layer_id) && 1082 (map->pixel_formats[i].format == format)) { 1083 /* 1084 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier 1085 * is supported by a different h/w format id than 1086 * DRM_FORMAT_YUYV (only). 1087 */ 1088 if (format == DRM_FORMAT_YUYV && 1089 (has_modifier) && 1090 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2)) 1091 return AFBC_YUV_422_FORMAT_ID; 1092 else 1093 return map->pixel_formats[i].id; 1094 } 1095 } 1096 1097 return MALIDP_INVALID_FORMAT_ID; 1098 } 1099 1100 bool malidp_hw_format_is_linear_only(u32 format) 1101 { 1102 switch (format) { 1103 case DRM_FORMAT_ARGB2101010: 1104 case DRM_FORMAT_RGBA1010102: 1105 case DRM_FORMAT_BGRA1010102: 1106 case DRM_FORMAT_ARGB8888: 1107 case DRM_FORMAT_RGBA8888: 1108 case DRM_FORMAT_BGRA8888: 1109 case DRM_FORMAT_XBGR8888: 1110 case DRM_FORMAT_XRGB8888: 1111 case DRM_FORMAT_RGBX8888: 1112 case DRM_FORMAT_BGRX8888: 1113 case DRM_FORMAT_RGB888: 1114 case DRM_FORMAT_RGB565: 1115 case DRM_FORMAT_ARGB1555: 1116 case DRM_FORMAT_RGBA5551: 1117 case DRM_FORMAT_BGRA5551: 1118 case DRM_FORMAT_UYVY: 1119 case DRM_FORMAT_XYUV8888: 1120 case DRM_FORMAT_XVYU2101010: 1121 case DRM_FORMAT_X0L2: 1122 case DRM_FORMAT_X0L0: 1123 return true; 1124 default: 1125 return false; 1126 } 1127 } 1128 1129 bool malidp_hw_format_is_afbc_only(u32 format) 1130 { 1131 switch (format) { 1132 case DRM_FORMAT_VUY888: 1133 case DRM_FORMAT_VUY101010: 1134 case DRM_FORMAT_YUV420_8BIT: 1135 case DRM_FORMAT_YUV420_10BIT: 1136 return true; 1137 default: 1138 return false; 1139 } 1140 } 1141 1142 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq) 1143 { 1144 u32 base = malidp_get_block_base(hwdev, block); 1145 1146 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) 1147 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ); 1148 else 1149 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS); 1150 } 1151 1152 static irqreturn_t malidp_de_irq(int irq, void *arg) 1153 { 1154 struct drm_device *drm = arg; 1155 struct malidp_drm *malidp = drm->dev_private; 1156 struct malidp_hw_device *hwdev; 1157 struct malidp_hw *hw; 1158 const struct malidp_irq_map *de; 1159 u32 status, mask, dc_status; 1160 irqreturn_t ret = IRQ_NONE; 1161 1162 hwdev = malidp->dev; 1163 hw = hwdev->hw; 1164 de = &hw->map.de_irq_map; 1165 1166 /* 1167 * if we are suspended it is likely that we were invoked because 1168 * we share an interrupt line with some other driver, don't try 1169 * to read the hardware registers 1170 */ 1171 if (hwdev->pm_suspended) 1172 return IRQ_NONE; 1173 1174 /* first handle the config valid IRQ */ 1175 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); 1176 if (dc_status & hw->map.dc_irq_map.vsync_irq) { 1177 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); 1178 /* do we have a page flip event? */ 1179 if (malidp->event != NULL) { 1180 spin_lock(&drm->event_lock); 1181 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); 1182 malidp->event = NULL; 1183 spin_unlock(&drm->event_lock); 1184 } 1185 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE); 1186 ret = IRQ_WAKE_THREAD; 1187 } 1188 1189 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS); 1190 if (!(status & de->irq_mask)) 1191 return ret; 1192 1193 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); 1194 /* keep the status of the enabled interrupts, plus the error bits */ 1195 status &= (mask | de->err_mask); 1196 if ((status & de->vsync_irq) && malidp->crtc.enabled) 1197 drm_crtc_handle_vblank(&malidp->crtc); 1198 1199 #ifdef CONFIG_DEBUG_FS 1200 if (status & de->err_mask) { 1201 malidp_error(malidp, &malidp->de_errors, status, 1202 drm_crtc_vblank_count(&malidp->crtc)); 1203 } 1204 #endif 1205 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); 1206 1207 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret; 1208 } 1209 1210 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg) 1211 { 1212 struct drm_device *drm = arg; 1213 struct malidp_drm *malidp = drm->dev_private; 1214 1215 wake_up(&malidp->wq); 1216 1217 return IRQ_HANDLED; 1218 } 1219 1220 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev) 1221 { 1222 /* ensure interrupts are disabled */ 1223 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1224 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1225 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1226 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1227 1228 /* first enable the DC block IRQs */ 1229 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK, 1230 hwdev->hw->map.dc_irq_map.irq_mask); 1231 1232 /* now enable the DE block IRQs */ 1233 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK, 1234 hwdev->hw->map.de_irq_map.irq_mask); 1235 } 1236 1237 int malidp_de_irq_init(struct drm_device *drm, int irq) 1238 { 1239 struct malidp_drm *malidp = drm->dev_private; 1240 struct malidp_hw_device *hwdev = malidp->dev; 1241 int ret; 1242 1243 /* ensure interrupts are disabled */ 1244 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1245 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1246 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1247 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1248 1249 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq, 1250 malidp_de_irq_thread_handler, 1251 IRQF_SHARED, "malidp-de", drm); 1252 if (ret < 0) { 1253 DRM_ERROR("failed to install DE IRQ handler\n"); 1254 return ret; 1255 } 1256 1257 malidp_de_irq_hw_init(hwdev); 1258 1259 return 0; 1260 } 1261 1262 void malidp_de_irq_fini(struct malidp_hw_device *hwdev) 1263 { 1264 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 1265 hwdev->hw->map.de_irq_map.irq_mask); 1266 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 1267 hwdev->hw->map.dc_irq_map.irq_mask); 1268 } 1269 1270 static irqreturn_t malidp_se_irq(int irq, void *arg) 1271 { 1272 struct drm_device *drm = arg; 1273 struct malidp_drm *malidp = drm->dev_private; 1274 struct malidp_hw_device *hwdev = malidp->dev; 1275 struct malidp_hw *hw = hwdev->hw; 1276 const struct malidp_irq_map *se = &hw->map.se_irq_map; 1277 u32 status, mask; 1278 1279 /* 1280 * if we are suspended it is likely that we were invoked because 1281 * we share an interrupt line with some other driver, don't try 1282 * to read the hardware registers 1283 */ 1284 if (hwdev->pm_suspended) 1285 return IRQ_NONE; 1286 1287 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS); 1288 if (!(status & (se->irq_mask | se->err_mask))) 1289 return IRQ_NONE; 1290 1291 #ifdef CONFIG_DEBUG_FS 1292 if (status & se->err_mask) 1293 malidp_error(malidp, &malidp->se_errors, status, 1294 drm_crtc_vblank_count(&malidp->crtc)); 1295 #endif 1296 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ); 1297 status &= mask; 1298 1299 if (status & se->vsync_irq) { 1300 switch (hwdev->mw_state) { 1301 case MW_ONESHOT: 1302 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1303 break; 1304 case MW_STOP: 1305 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1306 /* disable writeback after stop */ 1307 hwdev->mw_state = MW_NOT_ENABLED; 1308 break; 1309 case MW_RESTART: 1310 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1311 /* fall through to a new start */ 1312 case MW_START: 1313 /* writeback started, need to emulate one-shot mode */ 1314 hw->disable_memwrite(hwdev); 1315 /* 1316 * only set config_valid HW bit if there is no other update 1317 * in progress or if we raced ahead of the DE IRQ handler 1318 * and config_valid flag will not be update until later 1319 */ 1320 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); 1321 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) || 1322 (status & hw->map.dc_irq_map.vsync_irq)) 1323 hw->set_config_valid(hwdev, 1); 1324 break; 1325 } 1326 } 1327 1328 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status); 1329 1330 return IRQ_HANDLED; 1331 } 1332 1333 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev) 1334 { 1335 /* ensure interrupts are disabled */ 1336 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1337 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1338 1339 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK, 1340 hwdev->hw->map.se_irq_map.irq_mask); 1341 } 1342 1343 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg) 1344 { 1345 return IRQ_HANDLED; 1346 } 1347 1348 int malidp_se_irq_init(struct drm_device *drm, int irq) 1349 { 1350 struct malidp_drm *malidp = drm->dev_private; 1351 struct malidp_hw_device *hwdev = malidp->dev; 1352 int ret; 1353 1354 /* ensure interrupts are disabled */ 1355 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1356 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1357 1358 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq, 1359 malidp_se_irq_thread_handler, 1360 IRQF_SHARED, "malidp-se", drm); 1361 if (ret < 0) { 1362 DRM_ERROR("failed to install SE IRQ handler\n"); 1363 return ret; 1364 } 1365 1366 hwdev->mw_state = MW_NOT_ENABLED; 1367 malidp_se_irq_hw_init(hwdev); 1368 1369 return 0; 1370 } 1371 1372 void malidp_se_irq_fini(struct malidp_hw_device *hwdev) 1373 { 1374 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 1375 hwdev->hw->map.se_irq_map.irq_mask); 1376 } 1377