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