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