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