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