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