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 * Program the RQoS register to avoid high resolutions flicker 385 * issue on the LS1028A. 386 */ 387 if (hwdev->arqos_value) { 388 val = hwdev->arqos_value; 389 malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY); 390 } 391 } 392 393 int malidp_format_get_bpp(u32 fmt) 394 { 395 const struct drm_format_info *info = drm_format_info(fmt); 396 int bpp = info->cpp[0] * 8; 397 398 if (bpp == 0) { 399 switch (fmt) { 400 case DRM_FORMAT_VUY101010: 401 bpp = 30; 402 break; 403 case DRM_FORMAT_YUV420_10BIT: 404 bpp = 15; 405 break; 406 case DRM_FORMAT_YUV420_8BIT: 407 bpp = 12; 408 break; 409 default: 410 bpp = 0; 411 } 412 } 413 414 return bpp; 415 } 416 417 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 418 u16 h, u32 fmt, bool has_modifier) 419 { 420 /* 421 * Each layer needs enough rotation memory to fit 8 lines 422 * worth of pixel data. Required size is then: 423 * size = rotated_width * (bpp / 8) * 8; 424 */ 425 int bpp = malidp_format_get_bpp(fmt); 426 427 return w * bpp; 428 } 429 430 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev, 431 u32 direction, 432 u16 addr, 433 u8 coeffs_id) 434 { 435 int i; 436 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL; 437 438 malidp_hw_write(hwdev, 439 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK), 440 scaling_control + MALIDP_SE_COEFFTAB_ADDR); 441 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i) 442 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA( 443 dp500_se_scaling_coeffs[coeffs_id][i]), 444 scaling_control + MALIDP_SE_COEFFTAB_DATA); 445 } 446 447 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 448 struct malidp_se_config *se_config, 449 struct malidp_se_config *old_config) 450 { 451 /* Get array indices into dp500_se_scaling_coeffs. */ 452 u8 h = (u8)se_config->hcoeff - 1; 453 u8 v = (u8)se_config->vcoeff - 1; 454 455 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) || 456 v >= ARRAY_SIZE(dp500_se_scaling_coeffs))) 457 return -EINVAL; 458 459 if ((h == v) && (se_config->hcoeff != old_config->hcoeff || 460 se_config->vcoeff != old_config->vcoeff)) { 461 malidp500_se_write_pp_coefftab(hwdev, 462 (MALIDP_SE_V_COEFFTAB | 463 MALIDP_SE_H_COEFFTAB), 464 0, v); 465 } else { 466 if (se_config->vcoeff != old_config->vcoeff) 467 malidp500_se_write_pp_coefftab(hwdev, 468 MALIDP_SE_V_COEFFTAB, 469 0, v); 470 if (se_config->hcoeff != old_config->hcoeff) 471 malidp500_se_write_pp_coefftab(hwdev, 472 MALIDP_SE_H_COEFFTAB, 473 0, h); 474 } 475 476 return 0; 477 } 478 479 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, 480 struct malidp_se_config *se_config, 481 struct videomode *vm) 482 { 483 unsigned long mclk; 484 unsigned long pxlclk = vm->pixelclock; /* Hz */ 485 unsigned long htotal = vm->hactive + vm->hfront_porch + 486 vm->hback_porch + vm->hsync_len; 487 unsigned long input_size = se_config->input_w * se_config->input_h; 488 unsigned long a = 10; 489 long ret; 490 491 /* 492 * mclk = max(a, 1.5) * pxlclk 493 * 494 * To avoid float calculaiton, using 15 instead of 1.5 and div by 495 * 10 to get mclk. 496 */ 497 if (se_config->scale_enable) { 498 a = 15 * input_size / (htotal * se_config->output_h); 499 if (a < 15) 500 a = 15; 501 } 502 mclk = a * pxlclk / 10; 503 ret = clk_get_rate(hwdev->mclk); 504 if (ret < mclk) { 505 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", 506 mclk / 1000); 507 return -EINVAL; 508 } 509 return ret; 510 } 511 512 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, 513 dma_addr_t *addrs, s32 *pitches, 514 int num_planes, u16 w, u16 h, u32 fmt_id, 515 const s16 *rgb2yuv_coeffs) 516 { 517 u32 base = MALIDP500_SE_MEMWRITE_BASE; 518 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 519 520 /* enable the scaling engine block */ 521 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); 522 523 /* restart the writeback if already enabled */ 524 if (hwdev->mw_state != MW_NOT_ENABLED) 525 hwdev->mw_state = MW_RESTART; 526 else 527 hwdev->mw_state = MW_START; 528 529 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); 530 switch (num_planes) { 531 case 2: 532 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); 533 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); 534 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); 535 fallthrough; 536 case 1: 537 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); 538 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); 539 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE); 540 break; 541 default: 542 WARN(1, "Invalid number of planes"); 543 } 544 545 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), 546 MALIDP500_SE_MEMWRITE_OUT_SIZE); 547 548 if (rgb2yuv_coeffs) { 549 int i; 550 551 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { 552 malidp_hw_write(hwdev, rgb2yuv_coeffs[i], 553 MALIDP500_SE_RGB_YUV_COEFFS + i * 4); 554 } 555 } 556 557 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); 558 559 return 0; 560 } 561 562 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev) 563 { 564 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 565 566 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART) 567 hwdev->mw_state = MW_STOP; 568 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); 569 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC); 570 } 571 572 static int malidp550_query_hw(struct malidp_hw_device *hwdev) 573 { 574 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 575 u8 ln_size = (conf >> 4) & 0x3, rsize; 576 577 hwdev->min_line_size = 2; 578 579 switch (ln_size) { 580 case 0: 581 hwdev->max_line_size = SZ_2K; 582 /* two banks of 64KB for rotation memory */ 583 rsize = 64; 584 break; 585 case 1: 586 hwdev->max_line_size = SZ_4K; 587 /* two banks of 128KB for rotation memory */ 588 rsize = 128; 589 break; 590 case 2: 591 hwdev->max_line_size = 1280; 592 /* two banks of 40KB for rotation memory */ 593 rsize = 40; 594 break; 595 case 3: 596 /* reserved value */ 597 hwdev->max_line_size = 0; 598 return -EINVAL; 599 } 600 601 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K; 602 return 0; 603 } 604 605 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev) 606 { 607 u32 status, count = 100; 608 609 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 610 while (count) { 611 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 612 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ) 613 break; 614 /* 615 * entering config mode can take as long as the rendering 616 * of a full frame, hence the long sleep here 617 */ 618 usleep_range(1000, 10000); 619 count--; 620 } 621 WARN(count == 0, "timeout while entering config mode"); 622 } 623 624 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev) 625 { 626 u32 status, count = 100; 627 628 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 629 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 630 while (count) { 631 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 632 if ((status & MALIDP550_DC_CONFIG_REQ) == 0) 633 break; 634 usleep_range(100, 1000); 635 count--; 636 } 637 WARN(count == 0, "timeout while leaving config mode"); 638 } 639 640 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev) 641 { 642 u32 status; 643 644 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS); 645 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ) 646 return true; 647 648 return false; 649 } 650 651 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value) 652 { 653 if (value) 654 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 655 else 656 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 657 } 658 659 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode) 660 { 661 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START; 662 663 malidp_hw_write(hwdev, hwdev->output_color_depth, 664 hwdev->hw->map.out_depth_base); 665 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL); 666 /* 667 * Mali-DP550 and Mali-DP650 encode the background color like this: 668 * - red @ MALIDP550_DE_BGND_COLOR[23:16] 669 * - green @ MALIDP550_DE_BGND_COLOR[15:8] 670 * - blue @ MALIDP550_DE_BGND_COLOR[7:0] 671 * 672 * We need to truncate the least significant 4 bits from the default 673 * MALIDP_BGND_COLOR_x values 674 */ 675 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) | 676 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) | 677 ((MALIDP_BGND_COLOR_B >> 4) & 0xff); 678 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR); 679 680 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) | 681 MALIDP_DE_H_BACKPORCH(mode->hback_porch); 682 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS); 683 684 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) | 685 MALIDP_DE_V_BACKPORCH(mode->vback_porch); 686 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS); 687 688 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) | 689 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len); 690 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH) 691 val |= MALIDP550_HSYNCPOL; 692 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH) 693 val |= MALIDP550_VSYNCPOL; 694 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH); 695 696 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive); 697 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE); 698 699 if (mode->flags & DISPLAY_FLAGS_INTERLACED) 700 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 701 else 702 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC); 703 } 704 705 static int malidpx50_get_bytes_per_column(u32 fmt) 706 { 707 u32 bytes_per_column; 708 709 switch (fmt) { 710 /* 8 lines at 4 bytes per pixel */ 711 case DRM_FORMAT_ARGB2101010: 712 case DRM_FORMAT_ABGR2101010: 713 case DRM_FORMAT_RGBA1010102: 714 case DRM_FORMAT_BGRA1010102: 715 case DRM_FORMAT_ARGB8888: 716 case DRM_FORMAT_ABGR8888: 717 case DRM_FORMAT_RGBA8888: 718 case DRM_FORMAT_BGRA8888: 719 case DRM_FORMAT_XRGB8888: 720 case DRM_FORMAT_XBGR8888: 721 case DRM_FORMAT_RGBX8888: 722 case DRM_FORMAT_BGRX8888: 723 case DRM_FORMAT_RGB888: 724 case DRM_FORMAT_BGR888: 725 /* 16 lines at 2 bytes per pixel */ 726 case DRM_FORMAT_RGBA5551: 727 case DRM_FORMAT_ABGR1555: 728 case DRM_FORMAT_RGB565: 729 case DRM_FORMAT_BGR565: 730 case DRM_FORMAT_UYVY: 731 case DRM_FORMAT_YUYV: 732 case DRM_FORMAT_X0L0: 733 bytes_per_column = 32; 734 break; 735 /* 16 lines at 1.5 bytes per pixel */ 736 case DRM_FORMAT_NV12: 737 case DRM_FORMAT_YUV420: 738 /* 8 lines at 3 bytes per pixel */ 739 case DRM_FORMAT_VUY888: 740 /* 16 lines at 12 bits per pixel */ 741 case DRM_FORMAT_YUV420_8BIT: 742 /* 8 lines at 3 bytes per pixel */ 743 case DRM_FORMAT_P010: 744 bytes_per_column = 24; 745 break; 746 /* 8 lines at 30 bits per pixel */ 747 case DRM_FORMAT_VUY101010: 748 /* 16 lines at 15 bits per pixel */ 749 case DRM_FORMAT_YUV420_10BIT: 750 bytes_per_column = 30; 751 break; 752 default: 753 return -EINVAL; 754 } 755 756 return bytes_per_column; 757 } 758 759 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 760 u16 h, u32 fmt, bool has_modifier) 761 { 762 int bytes_per_column = 0; 763 764 switch (fmt) { 765 /* 8 lines at 15 bits per pixel */ 766 case DRM_FORMAT_YUV420_10BIT: 767 bytes_per_column = 15; 768 break; 769 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */ 770 case DRM_FORMAT_X0L2: 771 if (has_modifier) 772 bytes_per_column = 8; 773 else 774 return -EINVAL; 775 break; 776 default: 777 bytes_per_column = malidpx50_get_bytes_per_column(fmt); 778 } 779 780 if (bytes_per_column == -EINVAL) 781 return bytes_per_column; 782 783 return w * bytes_per_column; 784 } 785 786 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 787 u16 h, u32 fmt, bool has_modifier) 788 { 789 int bytes_per_column = 0; 790 791 switch (fmt) { 792 /* 16 lines at 2 bytes per pixel */ 793 case DRM_FORMAT_X0L2: 794 bytes_per_column = 32; 795 break; 796 default: 797 bytes_per_column = malidpx50_get_bytes_per_column(fmt); 798 } 799 800 if (bytes_per_column == -EINVAL) 801 return bytes_per_column; 802 803 return w * bytes_per_column; 804 } 805 806 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 807 struct malidp_se_config *se_config, 808 struct malidp_se_config *old_config) 809 { 810 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) | 811 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK); 812 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) | 813 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff); 814 815 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL); 816 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL); 817 return 0; 818 } 819 820 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev, 821 struct malidp_se_config *se_config, 822 struct videomode *vm) 823 { 824 unsigned long mclk; 825 unsigned long pxlclk = vm->pixelclock; 826 unsigned long htotal = vm->hactive + vm->hfront_porch + 827 vm->hback_porch + vm->hsync_len; 828 unsigned long numerator = 1, denominator = 1; 829 long ret; 830 831 if (se_config->scale_enable) { 832 numerator = max(se_config->input_w, se_config->output_w) * 833 se_config->input_h; 834 numerator += se_config->output_w * 835 (se_config->output_h - 836 min(se_config->input_h, se_config->output_h)); 837 denominator = (htotal - 2) * se_config->output_h; 838 } 839 840 /* mclk can't be slower than pxlclk. */ 841 if (numerator < denominator) 842 numerator = denominator = 1; 843 mclk = (pxlclk * numerator) / denominator; 844 ret = clk_get_rate(hwdev->mclk); 845 if (ret < mclk) { 846 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", 847 mclk / 1000); 848 return -EINVAL; 849 } 850 return ret; 851 } 852 853 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, 854 dma_addr_t *addrs, s32 *pitches, 855 int num_planes, u16 w, u16 h, u32 fmt_id, 856 const s16 *rgb2yuv_coeffs) 857 { 858 u32 base = MALIDP550_SE_MEMWRITE_BASE; 859 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 860 861 /* enable the scaling engine block */ 862 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); 863 864 hwdev->mw_state = MW_ONESHOT; 865 866 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); 867 switch (num_planes) { 868 case 2: 869 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); 870 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); 871 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); 872 fallthrough; 873 case 1: 874 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); 875 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); 876 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE); 877 break; 878 default: 879 WARN(1, "Invalid number of planes"); 880 } 881 882 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), 883 MALIDP550_SE_MEMWRITE_OUT_SIZE); 884 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, 885 MALIDP550_SE_CONTROL); 886 887 if (rgb2yuv_coeffs) { 888 int i; 889 890 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { 891 malidp_hw_write(hwdev, rgb2yuv_coeffs[i], 892 MALIDP550_SE_RGB_YUV_COEFFS + i * 4); 893 } 894 } 895 896 return 0; 897 } 898 899 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev) 900 { 901 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); 902 903 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, 904 MALIDP550_SE_CONTROL); 905 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC); 906 } 907 908 static int malidp650_query_hw(struct malidp_hw_device *hwdev) 909 { 910 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 911 u8 ln_size = (conf >> 4) & 0x3, rsize; 912 913 hwdev->min_line_size = 4; 914 915 switch (ln_size) { 916 case 0: 917 case 2: 918 /* reserved values */ 919 hwdev->max_line_size = 0; 920 return -EINVAL; 921 case 1: 922 hwdev->max_line_size = SZ_4K; 923 /* two banks of 128KB for rotation memory */ 924 rsize = 128; 925 break; 926 case 3: 927 hwdev->max_line_size = 2560; 928 /* two banks of 80KB for rotation memory */ 929 rsize = 80; 930 } 931 932 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K; 933 return 0; 934 } 935 936 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { 937 [MALIDP_500] = { 938 .map = { 939 .coeffs_base = MALIDP500_COEFFS_BASE, 940 .se_base = MALIDP500_SE_BASE, 941 .dc_base = MALIDP500_DC_BASE, 942 .out_depth_base = MALIDP500_OUTPUT_DEPTH, 943 .features = 0, /* no CLEARIRQ register */ 944 .n_layers = ARRAY_SIZE(malidp500_layers), 945 .layers = malidp500_layers, 946 .de_irq_map = { 947 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 948 MALIDP500_DE_IRQ_AXI_ERR | 949 MALIDP500_DE_IRQ_VSYNC | 950 MALIDP500_DE_IRQ_GLOBAL, 951 .vsync_irq = MALIDP500_DE_IRQ_VSYNC, 952 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 953 MALIDP500_DE_IRQ_AXI_ERR | 954 MALIDP500_DE_IRQ_SATURATION, 955 }, 956 .se_irq_map = { 957 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE | 958 MALIDP500_SE_IRQ_CONF_VALID | 959 MALIDP500_SE_IRQ_GLOBAL, 960 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID, 961 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY | 962 MALIDP500_SE_IRQ_AXI_ERROR | 963 MALIDP500_SE_IRQ_OVERRUN, 964 }, 965 .dc_irq_map = { 966 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID, 967 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID, 968 }, 969 .pixel_formats = malidp500_de_formats, 970 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats), 971 .bus_align_bytes = 8, 972 }, 973 .query_hw = malidp500_query_hw, 974 .enter_config_mode = malidp500_enter_config_mode, 975 .leave_config_mode = malidp500_leave_config_mode, 976 .in_config_mode = malidp500_in_config_mode, 977 .set_config_valid = malidp500_set_config_valid, 978 .modeset = malidp500_modeset, 979 .rotmem_required = malidp500_rotmem_required, 980 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, 981 .se_calc_mclk = malidp500_se_calc_mclk, 982 .enable_memwrite = malidp500_enable_memwrite, 983 .disable_memwrite = malidp500_disable_memwrite, 984 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, 985 }, 986 [MALIDP_550] = { 987 .map = { 988 .coeffs_base = MALIDP550_COEFFS_BASE, 989 .se_base = MALIDP550_SE_BASE, 990 .dc_base = MALIDP550_DC_BASE, 991 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, 992 .features = MALIDP_REGMAP_HAS_CLEARIRQ | 993 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | 994 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT | 995 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2, 996 .n_layers = ARRAY_SIZE(malidp550_layers), 997 .layers = malidp550_layers, 998 .de_irq_map = { 999 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 1000 MALIDP550_DE_IRQ_VSYNC, 1001 .vsync_irq = MALIDP550_DE_IRQ_VSYNC, 1002 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 1003 MALIDP550_DE_IRQ_SATURATION | 1004 MALIDP550_DE_IRQ_AXI_ERR, 1005 }, 1006 .se_irq_map = { 1007 .irq_mask = MALIDP550_SE_IRQ_EOW, 1008 .vsync_irq = MALIDP550_SE_IRQ_EOW, 1009 .err_mask = MALIDP550_SE_IRQ_AXI_ERR | 1010 MALIDP550_SE_IRQ_OVR | 1011 MALIDP550_SE_IRQ_IBSY, 1012 }, 1013 .dc_irq_map = { 1014 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID | 1015 MALIDP550_DC_IRQ_SE, 1016 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, 1017 }, 1018 .pixel_formats = malidp550_de_formats, 1019 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats), 1020 .bus_align_bytes = 8, 1021 }, 1022 .query_hw = malidp550_query_hw, 1023 .enter_config_mode = malidp550_enter_config_mode, 1024 .leave_config_mode = malidp550_leave_config_mode, 1025 .in_config_mode = malidp550_in_config_mode, 1026 .set_config_valid = malidp550_set_config_valid, 1027 .modeset = malidp550_modeset, 1028 .rotmem_required = malidp550_rotmem_required, 1029 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 1030 .se_calc_mclk = malidp550_se_calc_mclk, 1031 .enable_memwrite = malidp550_enable_memwrite, 1032 .disable_memwrite = malidp550_disable_memwrite, 1033 .features = 0, 1034 }, 1035 [MALIDP_650] = { 1036 .map = { 1037 .coeffs_base = MALIDP550_COEFFS_BASE, 1038 .se_base = MALIDP550_SE_BASE, 1039 .dc_base = MALIDP550_DC_BASE, 1040 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, 1041 .features = MALIDP_REGMAP_HAS_CLEARIRQ | 1042 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | 1043 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2, 1044 .n_layers = ARRAY_SIZE(malidp650_layers), 1045 .layers = malidp650_layers, 1046 .de_irq_map = { 1047 .irq_mask = MALIDP_DE_IRQ_UNDERRUN | 1048 MALIDP650_DE_IRQ_DRIFT | 1049 MALIDP550_DE_IRQ_VSYNC, 1050 .vsync_irq = MALIDP550_DE_IRQ_VSYNC, 1051 .err_mask = MALIDP_DE_IRQ_UNDERRUN | 1052 MALIDP650_DE_IRQ_DRIFT | 1053 MALIDP550_DE_IRQ_SATURATION | 1054 MALIDP550_DE_IRQ_AXI_ERR | 1055 MALIDP650_DE_IRQ_ACEV1 | 1056 MALIDP650_DE_IRQ_ACEV2 | 1057 MALIDP650_DE_IRQ_ACEG | 1058 MALIDP650_DE_IRQ_AXIEP, 1059 }, 1060 .se_irq_map = { 1061 .irq_mask = MALIDP550_SE_IRQ_EOW, 1062 .vsync_irq = MALIDP550_SE_IRQ_EOW, 1063 .err_mask = MALIDP550_SE_IRQ_AXI_ERR | 1064 MALIDP550_SE_IRQ_OVR | 1065 MALIDP550_SE_IRQ_IBSY, 1066 }, 1067 .dc_irq_map = { 1068 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID | 1069 MALIDP550_DC_IRQ_SE, 1070 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, 1071 }, 1072 .pixel_formats = malidp650_de_formats, 1073 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats), 1074 .bus_align_bytes = 16, 1075 }, 1076 .query_hw = malidp650_query_hw, 1077 .enter_config_mode = malidp550_enter_config_mode, 1078 .leave_config_mode = malidp550_leave_config_mode, 1079 .in_config_mode = malidp550_in_config_mode, 1080 .set_config_valid = malidp550_set_config_valid, 1081 .modeset = malidp550_modeset, 1082 .rotmem_required = malidp650_rotmem_required, 1083 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 1084 .se_calc_mclk = malidp550_se_calc_mclk, 1085 .enable_memwrite = malidp550_enable_memwrite, 1086 .disable_memwrite = malidp550_disable_memwrite, 1087 .features = 0, 1088 }, 1089 }; 1090 1091 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 1092 u8 layer_id, u32 format, bool has_modifier) 1093 { 1094 unsigned int i; 1095 1096 for (i = 0; i < map->n_pixel_formats; i++) { 1097 if (((map->pixel_formats[i].layer & layer_id) == layer_id) && 1098 (map->pixel_formats[i].format == format)) { 1099 /* 1100 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier 1101 * is supported by a different h/w format id than 1102 * DRM_FORMAT_YUYV (only). 1103 */ 1104 if (format == DRM_FORMAT_YUYV && 1105 (has_modifier) && 1106 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2)) 1107 return AFBC_YUV_422_FORMAT_ID; 1108 else 1109 return map->pixel_formats[i].id; 1110 } 1111 } 1112 1113 return MALIDP_INVALID_FORMAT_ID; 1114 } 1115 1116 bool malidp_hw_format_is_linear_only(u32 format) 1117 { 1118 switch (format) { 1119 case DRM_FORMAT_ARGB2101010: 1120 case DRM_FORMAT_RGBA1010102: 1121 case DRM_FORMAT_BGRA1010102: 1122 case DRM_FORMAT_ARGB8888: 1123 case DRM_FORMAT_RGBA8888: 1124 case DRM_FORMAT_BGRA8888: 1125 case DRM_FORMAT_XBGR8888: 1126 case DRM_FORMAT_XRGB8888: 1127 case DRM_FORMAT_RGBX8888: 1128 case DRM_FORMAT_BGRX8888: 1129 case DRM_FORMAT_RGB888: 1130 case DRM_FORMAT_RGB565: 1131 case DRM_FORMAT_ARGB1555: 1132 case DRM_FORMAT_RGBA5551: 1133 case DRM_FORMAT_BGRA5551: 1134 case DRM_FORMAT_UYVY: 1135 case DRM_FORMAT_XYUV8888: 1136 case DRM_FORMAT_XVYU2101010: 1137 case DRM_FORMAT_X0L2: 1138 case DRM_FORMAT_X0L0: 1139 return true; 1140 default: 1141 return false; 1142 } 1143 } 1144 1145 bool malidp_hw_format_is_afbc_only(u32 format) 1146 { 1147 switch (format) { 1148 case DRM_FORMAT_VUY888: 1149 case DRM_FORMAT_VUY101010: 1150 case DRM_FORMAT_YUV420_8BIT: 1151 case DRM_FORMAT_YUV420_10BIT: 1152 return true; 1153 default: 1154 return false; 1155 } 1156 } 1157 1158 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq) 1159 { 1160 u32 base = malidp_get_block_base(hwdev, block); 1161 1162 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) 1163 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ); 1164 else 1165 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS); 1166 } 1167 1168 static irqreturn_t malidp_de_irq(int irq, void *arg) 1169 { 1170 struct drm_device *drm = arg; 1171 struct malidp_drm *malidp = drm_to_malidp(drm); 1172 struct malidp_hw_device *hwdev; 1173 struct malidp_hw *hw; 1174 const struct malidp_irq_map *de; 1175 u32 status, mask, dc_status; 1176 irqreturn_t ret = IRQ_NONE; 1177 1178 hwdev = malidp->dev; 1179 hw = hwdev->hw; 1180 de = &hw->map.de_irq_map; 1181 1182 /* 1183 * if we are suspended it is likely that we were invoked because 1184 * we share an interrupt line with some other driver, don't try 1185 * to read the hardware registers 1186 */ 1187 if (hwdev->pm_suspended) 1188 return IRQ_NONE; 1189 1190 /* first handle the config valid IRQ */ 1191 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); 1192 if (dc_status & hw->map.dc_irq_map.vsync_irq) { 1193 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); 1194 /* do we have a page flip event? */ 1195 if (malidp->event != NULL) { 1196 spin_lock(&drm->event_lock); 1197 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); 1198 malidp->event = NULL; 1199 spin_unlock(&drm->event_lock); 1200 } 1201 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE); 1202 ret = IRQ_WAKE_THREAD; 1203 } 1204 1205 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS); 1206 if (!(status & de->irq_mask)) 1207 return ret; 1208 1209 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); 1210 /* keep the status of the enabled interrupts, plus the error bits */ 1211 status &= (mask | de->err_mask); 1212 if ((status & de->vsync_irq) && malidp->crtc.enabled) 1213 drm_crtc_handle_vblank(&malidp->crtc); 1214 1215 #ifdef CONFIG_DEBUG_FS 1216 if (status & de->err_mask) { 1217 malidp_error(malidp, &malidp->de_errors, status, 1218 drm_crtc_vblank_count(&malidp->crtc)); 1219 } 1220 #endif 1221 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); 1222 1223 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret; 1224 } 1225 1226 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg) 1227 { 1228 struct drm_device *drm = arg; 1229 struct malidp_drm *malidp = drm_to_malidp(drm); 1230 1231 wake_up(&malidp->wq); 1232 1233 return IRQ_HANDLED; 1234 } 1235 1236 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev) 1237 { 1238 /* ensure interrupts are disabled */ 1239 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1240 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1241 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1242 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1243 1244 /* first enable the DC block IRQs */ 1245 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK, 1246 hwdev->hw->map.dc_irq_map.irq_mask); 1247 1248 /* now enable the DE block IRQs */ 1249 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK, 1250 hwdev->hw->map.de_irq_map.irq_mask); 1251 } 1252 1253 int malidp_de_irq_init(struct drm_device *drm, int irq) 1254 { 1255 struct malidp_drm *malidp = drm_to_malidp(drm); 1256 struct malidp_hw_device *hwdev = malidp->dev; 1257 int ret; 1258 1259 /* ensure interrupts are disabled */ 1260 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1261 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff); 1262 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1263 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff); 1264 1265 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq, 1266 malidp_de_irq_thread_handler, 1267 IRQF_SHARED, "malidp-de", drm); 1268 if (ret < 0) { 1269 DRM_ERROR("failed to install DE IRQ handler\n"); 1270 return ret; 1271 } 1272 1273 malidp_de_irq_hw_init(hwdev); 1274 1275 return 0; 1276 } 1277 1278 void malidp_de_irq_fini(struct malidp_hw_device *hwdev) 1279 { 1280 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 1281 hwdev->hw->map.de_irq_map.irq_mask); 1282 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 1283 hwdev->hw->map.dc_irq_map.irq_mask); 1284 } 1285 1286 static irqreturn_t malidp_se_irq(int irq, void *arg) 1287 { 1288 struct drm_device *drm = arg; 1289 struct malidp_drm *malidp = drm_to_malidp(drm); 1290 struct malidp_hw_device *hwdev = malidp->dev; 1291 struct malidp_hw *hw = hwdev->hw; 1292 const struct malidp_irq_map *se = &hw->map.se_irq_map; 1293 u32 status, mask; 1294 1295 /* 1296 * if we are suspended it is likely that we were invoked because 1297 * we share an interrupt line with some other driver, don't try 1298 * to read the hardware registers 1299 */ 1300 if (hwdev->pm_suspended) 1301 return IRQ_NONE; 1302 1303 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS); 1304 if (!(status & (se->irq_mask | se->err_mask))) 1305 return IRQ_NONE; 1306 1307 #ifdef CONFIG_DEBUG_FS 1308 if (status & se->err_mask) 1309 malidp_error(malidp, &malidp->se_errors, status, 1310 drm_crtc_vblank_count(&malidp->crtc)); 1311 #endif 1312 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ); 1313 status &= mask; 1314 1315 if (status & se->vsync_irq) { 1316 switch (hwdev->mw_state) { 1317 case MW_ONESHOT: 1318 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1319 break; 1320 case MW_STOP: 1321 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1322 /* disable writeback after stop */ 1323 hwdev->mw_state = MW_NOT_ENABLED; 1324 break; 1325 case MW_RESTART: 1326 drm_writeback_signal_completion(&malidp->mw_connector, 0); 1327 fallthrough; /* to a new start */ 1328 case MW_START: 1329 /* writeback started, need to emulate one-shot mode */ 1330 hw->disable_memwrite(hwdev); 1331 /* 1332 * only set config_valid HW bit if there is no other update 1333 * in progress or if we raced ahead of the DE IRQ handler 1334 * and config_valid flag will not be update until later 1335 */ 1336 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); 1337 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) || 1338 (status & hw->map.dc_irq_map.vsync_irq)) 1339 hw->set_config_valid(hwdev, 1); 1340 break; 1341 } 1342 } 1343 1344 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status); 1345 1346 return IRQ_HANDLED; 1347 } 1348 1349 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev) 1350 { 1351 /* ensure interrupts are disabled */ 1352 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1353 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1354 1355 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK, 1356 hwdev->hw->map.se_irq_map.irq_mask); 1357 } 1358 1359 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg) 1360 { 1361 return IRQ_HANDLED; 1362 } 1363 1364 int malidp_se_irq_init(struct drm_device *drm, int irq) 1365 { 1366 struct malidp_drm *malidp = drm_to_malidp(drm); 1367 struct malidp_hw_device *hwdev = malidp->dev; 1368 int ret; 1369 1370 /* ensure interrupts are disabled */ 1371 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1372 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff); 1373 1374 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq, 1375 malidp_se_irq_thread_handler, 1376 IRQF_SHARED, "malidp-se", drm); 1377 if (ret < 0) { 1378 DRM_ERROR("failed to install SE IRQ handler\n"); 1379 return ret; 1380 } 1381 1382 hwdev->mw_state = MW_NOT_ENABLED; 1383 malidp_se_irq_hw_init(hwdev); 1384 1385 return 0; 1386 } 1387 1388 void malidp_se_irq_fini(struct malidp_hw_device *hwdev) 1389 { 1390 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 1391 hwdev->hw->map.se_irq_map.irq_mask); 1392 } 1393