0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/delay.h>
0013 #include <linux/types.h>
0014 #include <linux/io.h>
0015
0016 #include <video/videomode.h>
0017 #include <video/display_timing.h>
0018
0019 #include <drm/drm_fourcc.h>
0020 #include <drm/drm_vblank.h>
0021 #include <drm/drm_print.h>
0022
0023 #include "malidp_drv.h"
0024 #include "malidp_hw.h"
0025 #include "malidp_mw.h"
0026
0027 enum {
0028 MW_NOT_ENABLED = 0,
0029 MW_ONESHOT,
0030 MW_START,
0031 MW_RESTART,
0032 MW_STOP,
0033 };
0034
0035 static const struct malidp_format_id malidp500_de_formats[] = {
0036
0037 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 0 },
0038 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 1 },
0039 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 2 },
0040 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 3 },
0041 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 4 },
0042 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 5 },
0043 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 6 },
0044 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 7 },
0045 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 8 },
0046 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 9 },
0047 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
0048 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
0049 { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
0050 { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
0051 { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
0052 { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
0053 { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
0054
0055 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
0056 { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
0057 { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
0058 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
0059 };
0060
0061 #define MALIDP_ID(__group, __format) \
0062 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
0063
0064 #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
0065
0066 #define MALIDP_COMMON_FORMATS \
0067 \
0068 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
0069 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
0070 { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
0071 { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
0072 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
0073 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
0074 { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
0075 { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
0076 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
0077 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
0078 { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
0079 { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
0080 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
0081 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
0082 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
0083 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
0084 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
0085 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
0086 \
0087 { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
0088 \
0089 { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
0090 { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
0091 \
0092 { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
0093 { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
0094 \
0095 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
0096 { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
0097 \
0098 { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
0099 \
0100 { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
0101 { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
0102 \
0103 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
0104 { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
0105
0106 static const struct malidp_format_id malidp550_de_formats[] = {
0107 MALIDP_COMMON_FORMATS,
0108 };
0109
0110 static const struct malidp_format_id malidp650_de_formats[] = {
0111 MALIDP_COMMON_FORMATS,
0112 { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
0113 };
0114
0115 static const struct malidp_layer malidp500_layers[] = {
0116
0117
0118
0119 { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
0120 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
0121 MALIDP500_DE_LV_AD_CTRL },
0122 { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
0123 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
0124 MALIDP500_DE_LG1_AD_CTRL },
0125 { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
0126 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
0127 MALIDP500_DE_LG2_AD_CTRL },
0128 };
0129
0130 static const struct malidp_layer malidp550_layers[] = {
0131
0132
0133
0134 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
0135 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
0136 MALIDP550_DE_LV1_AD_CTRL },
0137 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
0138 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
0139 MALIDP550_DE_LG_AD_CTRL },
0140 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
0141 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
0142 MALIDP550_DE_LV2_AD_CTRL },
0143 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
0144 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
0145 };
0146
0147 static const struct malidp_layer malidp650_layers[] = {
0148
0149
0150
0151
0152 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
0153 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
0154 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
0155 MALIDP550_DE_LV1_AD_CTRL },
0156 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
0157 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
0158 ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
0159 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
0160 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
0161 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
0162 MALIDP550_DE_LV2_AD_CTRL },
0163 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
0164 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
0165 ROTATE_NONE, 0 },
0166 };
0167
0168 const u64 malidp_format_modifiers[] = {
0169
0170 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
0171 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
0172
0173
0174 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
0175
0176
0177
0178 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
0179
0180
0181 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
0182 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
0183
0184
0185 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
0186 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
0187
0188
0189 DRM_FORMAT_MOD_LINEAR,
0190
0191 DRM_FORMAT_MOD_INVALID
0192 };
0193
0194 #define SE_N_SCALING_COEFFS 96
0195 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
0196 [MALIDP_UPSCALING_COEFFS - 1] = {
0197 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
0198 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
0199 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
0200 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
0201 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
0202 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
0203 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
0204 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
0205 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
0206 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
0207 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
0208 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
0209 },
0210 [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
0211 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
0212 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
0213 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
0214 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
0215 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
0216 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
0217 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
0218 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
0219 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
0220 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
0221 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
0222 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
0223 },
0224 [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
0225 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
0226 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
0227 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
0228 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
0229 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
0230 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
0231 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
0232 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
0233 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
0234 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
0235 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
0236 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
0237 },
0238 [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
0239 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
0240 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
0241 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
0242 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
0243 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
0244 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
0245 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
0246 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
0247 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
0248 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
0249 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
0250 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
0251 },
0252 [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
0253 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
0254 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
0255 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
0256 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
0257 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
0258 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
0259 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
0260 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
0261 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
0262 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
0263 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
0264 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
0265 },
0266 };
0267
0268 #define MALIDP_DE_DEFAULT_PREFETCH_START 5
0269
0270 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
0271 {
0272 u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
0273
0274 u8 ln_size_mult = conf & 0x10 ? 2 : 1;
0275
0276 hwdev->min_line_size = 2;
0277 hwdev->max_line_size = SZ_2K * ln_size_mult;
0278 hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
0279 hwdev->rotation_memory[1] = 0;
0280
0281 return 0;
0282 }
0283
0284 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
0285 {
0286 u32 status, count = 100;
0287
0288 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
0289 while (count) {
0290 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0291 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
0292 break;
0293
0294
0295
0296
0297 usleep_range(1000, 10000);
0298 count--;
0299 }
0300 WARN(count == 0, "timeout while entering config mode");
0301 }
0302
0303 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
0304 {
0305 u32 status, count = 100;
0306
0307 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
0308 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
0309 while (count) {
0310 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0311 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
0312 break;
0313 usleep_range(100, 1000);
0314 count--;
0315 }
0316 WARN(count == 0, "timeout while leaving config mode");
0317 }
0318
0319 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
0320 {
0321 u32 status;
0322
0323 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0324 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
0325 return true;
0326
0327 return false;
0328 }
0329
0330 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
0331 {
0332 if (value)
0333 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
0334 else
0335 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
0336 }
0337
0338 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
0339 {
0340 u32 val = 0;
0341
0342 malidp_hw_write(hwdev, hwdev->output_color_depth,
0343 hwdev->hw->map.out_depth_base);
0344 malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
0345 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
0346 val |= MALIDP500_HSYNCPOL;
0347 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
0348 val |= MALIDP500_VSYNCPOL;
0349 val |= MALIDP_DE_DEFAULT_PREFETCH_START;
0350 malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
0351
0352
0353
0354
0355
0356
0357
0358 val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
0359 (MALIDP_BGND_COLOR_R & 0xfff);
0360 malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
0361 malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
0362
0363 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
0364 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
0365 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
0366
0367 val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
0368 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
0369 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
0370
0371 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
0372 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
0373 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
0374
0375 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
0376 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
0377
0378 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
0379 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
0380 else
0381 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
0382
0383
0384
0385
0386
0387 if (hwdev->arqos_value) {
0388 val = hwdev->arqos_value;
0389 malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY);
0390 }
0391 }
0392
0393 int malidp_format_get_bpp(u32 fmt)
0394 {
0395 const struct drm_format_info *info = drm_format_info(fmt);
0396 int bpp = info->cpp[0] * 8;
0397
0398 if (bpp == 0) {
0399 switch (fmt) {
0400 case DRM_FORMAT_VUY101010:
0401 bpp = 30;
0402 break;
0403 case DRM_FORMAT_YUV420_10BIT:
0404 bpp = 15;
0405 break;
0406 case DRM_FORMAT_YUV420_8BIT:
0407 bpp = 12;
0408 break;
0409 default:
0410 bpp = 0;
0411 }
0412 }
0413
0414 return bpp;
0415 }
0416
0417 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
0418 u16 h, u32 fmt, bool has_modifier)
0419 {
0420
0421
0422
0423
0424
0425 int bpp = malidp_format_get_bpp(fmt);
0426
0427 return w * bpp;
0428 }
0429
0430 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
0431 u32 direction,
0432 u16 addr,
0433 u8 coeffs_id)
0434 {
0435 int i;
0436 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
0437
0438 malidp_hw_write(hwdev,
0439 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
0440 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
0441 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
0442 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
0443 dp500_se_scaling_coeffs[coeffs_id][i]),
0444 scaling_control + MALIDP_SE_COEFFTAB_DATA);
0445 }
0446
0447 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
0448 struct malidp_se_config *se_config,
0449 struct malidp_se_config *old_config)
0450 {
0451
0452 u8 h = (u8)se_config->hcoeff - 1;
0453 u8 v = (u8)se_config->vcoeff - 1;
0454
0455 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
0456 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
0457 return -EINVAL;
0458
0459 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
0460 se_config->vcoeff != old_config->vcoeff)) {
0461 malidp500_se_write_pp_coefftab(hwdev,
0462 (MALIDP_SE_V_COEFFTAB |
0463 MALIDP_SE_H_COEFFTAB),
0464 0, v);
0465 } else {
0466 if (se_config->vcoeff != old_config->vcoeff)
0467 malidp500_se_write_pp_coefftab(hwdev,
0468 MALIDP_SE_V_COEFFTAB,
0469 0, v);
0470 if (se_config->hcoeff != old_config->hcoeff)
0471 malidp500_se_write_pp_coefftab(hwdev,
0472 MALIDP_SE_H_COEFFTAB,
0473 0, h);
0474 }
0475
0476 return 0;
0477 }
0478
0479 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
0480 struct malidp_se_config *se_config,
0481 struct videomode *vm)
0482 {
0483 unsigned long mclk;
0484 unsigned long pxlclk = vm->pixelclock;
0485 unsigned long htotal = vm->hactive + vm->hfront_porch +
0486 vm->hback_porch + vm->hsync_len;
0487 unsigned long input_size = se_config->input_w * se_config->input_h;
0488 unsigned long a = 10;
0489 long ret;
0490
0491
0492
0493
0494
0495
0496
0497 if (se_config->scale_enable) {
0498 a = 15 * input_size / (htotal * se_config->output_h);
0499 if (a < 15)
0500 a = 15;
0501 }
0502 mclk = a * pxlclk / 10;
0503 ret = clk_get_rate(hwdev->mclk);
0504 if (ret < mclk) {
0505 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
0506 mclk / 1000);
0507 return -EINVAL;
0508 }
0509 return ret;
0510 }
0511
0512 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
0513 dma_addr_t *addrs, s32 *pitches,
0514 int num_planes, u16 w, u16 h, u32 fmt_id,
0515 const s16 *rgb2yuv_coeffs)
0516 {
0517 u32 base = MALIDP500_SE_MEMWRITE_BASE;
0518 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
0519
0520
0521 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
0522
0523
0524 if (hwdev->mw_state != MW_NOT_ENABLED)
0525 hwdev->mw_state = MW_RESTART;
0526 else
0527 hwdev->mw_state = MW_START;
0528
0529 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
0530 switch (num_planes) {
0531 case 2:
0532 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
0533 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
0534 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
0535 fallthrough;
0536 case 1:
0537 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
0538 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
0539 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
0540 break;
0541 default:
0542 WARN(1, "Invalid number of planes");
0543 }
0544
0545 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
0546 MALIDP500_SE_MEMWRITE_OUT_SIZE);
0547
0548 if (rgb2yuv_coeffs) {
0549 int i;
0550
0551 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
0552 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
0553 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
0554 }
0555 }
0556
0557 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
0558
0559 return 0;
0560 }
0561
0562 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
0563 {
0564 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
0565
0566 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
0567 hwdev->mw_state = MW_STOP;
0568 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
0569 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
0570 }
0571
0572 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
0573 {
0574 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
0575 u8 ln_size = (conf >> 4) & 0x3, rsize;
0576
0577 hwdev->min_line_size = 2;
0578
0579 switch (ln_size) {
0580 case 0:
0581 hwdev->max_line_size = SZ_2K;
0582
0583 rsize = 64;
0584 break;
0585 case 1:
0586 hwdev->max_line_size = SZ_4K;
0587
0588 rsize = 128;
0589 break;
0590 case 2:
0591 hwdev->max_line_size = 1280;
0592
0593 rsize = 40;
0594 break;
0595 case 3:
0596
0597 hwdev->max_line_size = 0;
0598 return -EINVAL;
0599 }
0600
0601 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
0602 return 0;
0603 }
0604
0605 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
0606 {
0607 u32 status, count = 100;
0608
0609 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
0610 while (count) {
0611 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0612 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
0613 break;
0614
0615
0616
0617
0618 usleep_range(1000, 10000);
0619 count--;
0620 }
0621 WARN(count == 0, "timeout while entering config mode");
0622 }
0623
0624 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
0625 {
0626 u32 status, count = 100;
0627
0628 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
0629 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
0630 while (count) {
0631 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0632 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
0633 break;
0634 usleep_range(100, 1000);
0635 count--;
0636 }
0637 WARN(count == 0, "timeout while leaving config mode");
0638 }
0639
0640 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
0641 {
0642 u32 status;
0643
0644 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
0645 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
0646 return true;
0647
0648 return false;
0649 }
0650
0651 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
0652 {
0653 if (value)
0654 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
0655 else
0656 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
0657 }
0658
0659 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
0660 {
0661 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
0662
0663 malidp_hw_write(hwdev, hwdev->output_color_depth,
0664 hwdev->hw->map.out_depth_base);
0665 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
0676 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
0677 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
0678 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
0679
0680 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
0681 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
0682 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
0683
0684 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
0685 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
0686 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
0687
0688 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
0689 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
0690 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
0691 val |= MALIDP550_HSYNCPOL;
0692 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
0693 val |= MALIDP550_VSYNCPOL;
0694 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
0695
0696 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
0697 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
0698
0699 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
0700 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
0701 else
0702 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
0703 }
0704
0705 static int malidpx50_get_bytes_per_column(u32 fmt)
0706 {
0707 u32 bytes_per_column;
0708
0709 switch (fmt) {
0710
0711 case DRM_FORMAT_ARGB2101010:
0712 case DRM_FORMAT_ABGR2101010:
0713 case DRM_FORMAT_RGBA1010102:
0714 case DRM_FORMAT_BGRA1010102:
0715 case DRM_FORMAT_ARGB8888:
0716 case DRM_FORMAT_ABGR8888:
0717 case DRM_FORMAT_RGBA8888:
0718 case DRM_FORMAT_BGRA8888:
0719 case DRM_FORMAT_XRGB8888:
0720 case DRM_FORMAT_XBGR8888:
0721 case DRM_FORMAT_RGBX8888:
0722 case DRM_FORMAT_BGRX8888:
0723 case DRM_FORMAT_RGB888:
0724 case DRM_FORMAT_BGR888:
0725
0726 case DRM_FORMAT_RGBA5551:
0727 case DRM_FORMAT_ABGR1555:
0728 case DRM_FORMAT_RGB565:
0729 case DRM_FORMAT_BGR565:
0730 case DRM_FORMAT_UYVY:
0731 case DRM_FORMAT_YUYV:
0732 case DRM_FORMAT_X0L0:
0733 bytes_per_column = 32;
0734 break;
0735
0736 case DRM_FORMAT_NV12:
0737 case DRM_FORMAT_YUV420:
0738
0739 case DRM_FORMAT_VUY888:
0740
0741 case DRM_FORMAT_YUV420_8BIT:
0742
0743 case DRM_FORMAT_P010:
0744 bytes_per_column = 24;
0745 break;
0746
0747 case DRM_FORMAT_VUY101010:
0748
0749 case DRM_FORMAT_YUV420_10BIT:
0750 bytes_per_column = 30;
0751 break;
0752 default:
0753 return -EINVAL;
0754 }
0755
0756 return bytes_per_column;
0757 }
0758
0759 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
0760 u16 h, u32 fmt, bool has_modifier)
0761 {
0762 int bytes_per_column = 0;
0763
0764 switch (fmt) {
0765
0766 case DRM_FORMAT_YUV420_10BIT:
0767 bytes_per_column = 15;
0768 break;
0769
0770 case DRM_FORMAT_X0L2:
0771 if (has_modifier)
0772 bytes_per_column = 8;
0773 else
0774 return -EINVAL;
0775 break;
0776 default:
0777 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
0778 }
0779
0780 if (bytes_per_column == -EINVAL)
0781 return bytes_per_column;
0782
0783 return w * bytes_per_column;
0784 }
0785
0786 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
0787 u16 h, u32 fmt, bool has_modifier)
0788 {
0789 int bytes_per_column = 0;
0790
0791 switch (fmt) {
0792
0793 case DRM_FORMAT_X0L2:
0794 bytes_per_column = 32;
0795 break;
0796 default:
0797 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
0798 }
0799
0800 if (bytes_per_column == -EINVAL)
0801 return bytes_per_column;
0802
0803 return w * bytes_per_column;
0804 }
0805
0806 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
0807 struct malidp_se_config *se_config,
0808 struct malidp_se_config *old_config)
0809 {
0810 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
0811 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
0812 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
0813 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
0814
0815 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
0816 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
0817 return 0;
0818 }
0819
0820 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
0821 struct malidp_se_config *se_config,
0822 struct videomode *vm)
0823 {
0824 unsigned long mclk;
0825 unsigned long pxlclk = vm->pixelclock;
0826 unsigned long htotal = vm->hactive + vm->hfront_porch +
0827 vm->hback_porch + vm->hsync_len;
0828 unsigned long numerator = 1, denominator = 1;
0829 long ret;
0830
0831 if (se_config->scale_enable) {
0832 numerator = max(se_config->input_w, se_config->output_w) *
0833 se_config->input_h;
0834 numerator += se_config->output_w *
0835 (se_config->output_h -
0836 min(se_config->input_h, se_config->output_h));
0837 denominator = (htotal - 2) * se_config->output_h;
0838 }
0839
0840
0841 if (numerator < denominator)
0842 numerator = denominator = 1;
0843 mclk = (pxlclk * numerator) / denominator;
0844 ret = clk_get_rate(hwdev->mclk);
0845 if (ret < mclk) {
0846 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
0847 mclk / 1000);
0848 return -EINVAL;
0849 }
0850 return ret;
0851 }
0852
0853 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
0854 dma_addr_t *addrs, s32 *pitches,
0855 int num_planes, u16 w, u16 h, u32 fmt_id,
0856 const s16 *rgb2yuv_coeffs)
0857 {
0858 u32 base = MALIDP550_SE_MEMWRITE_BASE;
0859 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
0860
0861
0862 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
0863
0864 hwdev->mw_state = MW_ONESHOT;
0865
0866 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
0867 switch (num_planes) {
0868 case 2:
0869 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
0870 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
0871 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
0872 fallthrough;
0873 case 1:
0874 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
0875 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
0876 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
0877 break;
0878 default:
0879 WARN(1, "Invalid number of planes");
0880 }
0881
0882 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
0883 MALIDP550_SE_MEMWRITE_OUT_SIZE);
0884 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
0885 MALIDP550_SE_CONTROL);
0886
0887 if (rgb2yuv_coeffs) {
0888 int i;
0889
0890 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
0891 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
0892 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
0893 }
0894 }
0895
0896 return 0;
0897 }
0898
0899 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
0900 {
0901 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
0902
0903 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
0904 MALIDP550_SE_CONTROL);
0905 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
0906 }
0907
0908 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
0909 {
0910 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
0911 u8 ln_size = (conf >> 4) & 0x3, rsize;
0912
0913 hwdev->min_line_size = 4;
0914
0915 switch (ln_size) {
0916 case 0:
0917 case 2:
0918
0919 hwdev->max_line_size = 0;
0920 return -EINVAL;
0921 case 1:
0922 hwdev->max_line_size = SZ_4K;
0923
0924 rsize = 128;
0925 break;
0926 case 3:
0927 hwdev->max_line_size = 2560;
0928
0929 rsize = 80;
0930 }
0931
0932 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
0933 return 0;
0934 }
0935
0936 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
0937 [MALIDP_500] = {
0938 .map = {
0939 .coeffs_base = MALIDP500_COEFFS_BASE,
0940 .se_base = MALIDP500_SE_BASE,
0941 .dc_base = MALIDP500_DC_BASE,
0942 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
0943 .features = 0,
0944 .n_layers = ARRAY_SIZE(malidp500_layers),
0945 .layers = malidp500_layers,
0946 .de_irq_map = {
0947 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
0948 MALIDP500_DE_IRQ_AXI_ERR |
0949 MALIDP500_DE_IRQ_VSYNC |
0950 MALIDP500_DE_IRQ_GLOBAL,
0951 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
0952 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
0953 MALIDP500_DE_IRQ_AXI_ERR |
0954 MALIDP500_DE_IRQ_SATURATION,
0955 },
0956 .se_irq_map = {
0957 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
0958 MALIDP500_SE_IRQ_CONF_VALID |
0959 MALIDP500_SE_IRQ_GLOBAL,
0960 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
0961 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
0962 MALIDP500_SE_IRQ_AXI_ERROR |
0963 MALIDP500_SE_IRQ_OVERRUN,
0964 },
0965 .dc_irq_map = {
0966 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
0967 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
0968 },
0969 .pixel_formats = malidp500_de_formats,
0970 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
0971 .bus_align_bytes = 8,
0972 },
0973 .query_hw = malidp500_query_hw,
0974 .enter_config_mode = malidp500_enter_config_mode,
0975 .leave_config_mode = malidp500_leave_config_mode,
0976 .in_config_mode = malidp500_in_config_mode,
0977 .set_config_valid = malidp500_set_config_valid,
0978 .modeset = malidp500_modeset,
0979 .rotmem_required = malidp500_rotmem_required,
0980 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
0981 .se_calc_mclk = malidp500_se_calc_mclk,
0982 .enable_memwrite = malidp500_enable_memwrite,
0983 .disable_memwrite = malidp500_disable_memwrite,
0984 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
0985 },
0986 [MALIDP_550] = {
0987 .map = {
0988 .coeffs_base = MALIDP550_COEFFS_BASE,
0989 .se_base = MALIDP550_SE_BASE,
0990 .dc_base = MALIDP550_DC_BASE,
0991 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
0992 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
0993 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
0994 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
0995 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
0996 .n_layers = ARRAY_SIZE(malidp550_layers),
0997 .layers = malidp550_layers,
0998 .de_irq_map = {
0999 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1000 MALIDP550_DE_IRQ_VSYNC,
1001 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1002 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1003 MALIDP550_DE_IRQ_SATURATION |
1004 MALIDP550_DE_IRQ_AXI_ERR,
1005 },
1006 .se_irq_map = {
1007 .irq_mask = MALIDP550_SE_IRQ_EOW,
1008 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1009 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1010 MALIDP550_SE_IRQ_OVR |
1011 MALIDP550_SE_IRQ_IBSY,
1012 },
1013 .dc_irq_map = {
1014 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1015 MALIDP550_DC_IRQ_SE,
1016 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1017 },
1018 .pixel_formats = malidp550_de_formats,
1019 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1020 .bus_align_bytes = 8,
1021 },
1022 .query_hw = malidp550_query_hw,
1023 .enter_config_mode = malidp550_enter_config_mode,
1024 .leave_config_mode = malidp550_leave_config_mode,
1025 .in_config_mode = malidp550_in_config_mode,
1026 .set_config_valid = malidp550_set_config_valid,
1027 .modeset = malidp550_modeset,
1028 .rotmem_required = malidp550_rotmem_required,
1029 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1030 .se_calc_mclk = malidp550_se_calc_mclk,
1031 .enable_memwrite = malidp550_enable_memwrite,
1032 .disable_memwrite = malidp550_disable_memwrite,
1033 .features = 0,
1034 },
1035 [MALIDP_650] = {
1036 .map = {
1037 .coeffs_base = MALIDP550_COEFFS_BASE,
1038 .se_base = MALIDP550_SE_BASE,
1039 .dc_base = MALIDP550_DC_BASE,
1040 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1041 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1042 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1043 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1044 .n_layers = ARRAY_SIZE(malidp650_layers),
1045 .layers = malidp650_layers,
1046 .de_irq_map = {
1047 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1048 MALIDP650_DE_IRQ_DRIFT |
1049 MALIDP550_DE_IRQ_VSYNC,
1050 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1051 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1052 MALIDP650_DE_IRQ_DRIFT |
1053 MALIDP550_DE_IRQ_SATURATION |
1054 MALIDP550_DE_IRQ_AXI_ERR |
1055 MALIDP650_DE_IRQ_ACEV1 |
1056 MALIDP650_DE_IRQ_ACEV2 |
1057 MALIDP650_DE_IRQ_ACEG |
1058 MALIDP650_DE_IRQ_AXIEP,
1059 },
1060 .se_irq_map = {
1061 .irq_mask = MALIDP550_SE_IRQ_EOW,
1062 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1063 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1064 MALIDP550_SE_IRQ_OVR |
1065 MALIDP550_SE_IRQ_IBSY,
1066 },
1067 .dc_irq_map = {
1068 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1069 MALIDP550_DC_IRQ_SE,
1070 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1071 },
1072 .pixel_formats = malidp650_de_formats,
1073 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1074 .bus_align_bytes = 16,
1075 },
1076 .query_hw = malidp650_query_hw,
1077 .enter_config_mode = malidp550_enter_config_mode,
1078 .leave_config_mode = malidp550_leave_config_mode,
1079 .in_config_mode = malidp550_in_config_mode,
1080 .set_config_valid = malidp550_set_config_valid,
1081 .modeset = malidp550_modeset,
1082 .rotmem_required = malidp650_rotmem_required,
1083 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1084 .se_calc_mclk = malidp550_se_calc_mclk,
1085 .enable_memwrite = malidp550_enable_memwrite,
1086 .disable_memwrite = malidp550_disable_memwrite,
1087 .features = 0,
1088 },
1089 };
1090
1091 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1092 u8 layer_id, u32 format, bool has_modifier)
1093 {
1094 unsigned int i;
1095
1096 for (i = 0; i < map->n_pixel_formats; i++) {
1097 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1098 (map->pixel_formats[i].format == format)) {
1099
1100
1101
1102
1103
1104 if (format == DRM_FORMAT_YUYV &&
1105 (has_modifier) &&
1106 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1107 return AFBC_YUV_422_FORMAT_ID;
1108 else
1109 return map->pixel_formats[i].id;
1110 }
1111 }
1112
1113 return MALIDP_INVALID_FORMAT_ID;
1114 }
1115
1116 bool malidp_hw_format_is_linear_only(u32 format)
1117 {
1118 switch (format) {
1119 case DRM_FORMAT_ARGB2101010:
1120 case DRM_FORMAT_RGBA1010102:
1121 case DRM_FORMAT_BGRA1010102:
1122 case DRM_FORMAT_ARGB8888:
1123 case DRM_FORMAT_RGBA8888:
1124 case DRM_FORMAT_BGRA8888:
1125 case DRM_FORMAT_XBGR8888:
1126 case DRM_FORMAT_XRGB8888:
1127 case DRM_FORMAT_RGBX8888:
1128 case DRM_FORMAT_BGRX8888:
1129 case DRM_FORMAT_RGB888:
1130 case DRM_FORMAT_RGB565:
1131 case DRM_FORMAT_ARGB1555:
1132 case DRM_FORMAT_RGBA5551:
1133 case DRM_FORMAT_BGRA5551:
1134 case DRM_FORMAT_UYVY:
1135 case DRM_FORMAT_XYUV8888:
1136 case DRM_FORMAT_XVYU2101010:
1137 case DRM_FORMAT_X0L2:
1138 case DRM_FORMAT_X0L0:
1139 return true;
1140 default:
1141 return false;
1142 }
1143 }
1144
1145 bool malidp_hw_format_is_afbc_only(u32 format)
1146 {
1147 switch (format) {
1148 case DRM_FORMAT_VUY888:
1149 case DRM_FORMAT_VUY101010:
1150 case DRM_FORMAT_YUV420_8BIT:
1151 case DRM_FORMAT_YUV420_10BIT:
1152 return true;
1153 default:
1154 return false;
1155 }
1156 }
1157
1158 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1159 {
1160 u32 base = malidp_get_block_base(hwdev, block);
1161
1162 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1163 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1164 else
1165 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1166 }
1167
1168 static irqreturn_t malidp_de_irq(int irq, void *arg)
1169 {
1170 struct drm_device *drm = arg;
1171 struct malidp_drm *malidp = drm->dev_private;
1172 struct malidp_hw_device *hwdev;
1173 struct malidp_hw *hw;
1174 const struct malidp_irq_map *de;
1175 u32 status, mask, dc_status;
1176 irqreturn_t ret = IRQ_NONE;
1177
1178 hwdev = malidp->dev;
1179 hw = hwdev->hw;
1180 de = &hw->map.de_irq_map;
1181
1182
1183
1184
1185
1186
1187 if (hwdev->pm_suspended)
1188 return IRQ_NONE;
1189
1190
1191 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1192 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1193 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1194
1195 if (malidp->event != NULL) {
1196 spin_lock(&drm->event_lock);
1197 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1198 malidp->event = NULL;
1199 spin_unlock(&drm->event_lock);
1200 }
1201 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1202 ret = IRQ_WAKE_THREAD;
1203 }
1204
1205 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1206 if (!(status & de->irq_mask))
1207 return ret;
1208
1209 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1210
1211 status &= (mask | de->err_mask);
1212 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1213 drm_crtc_handle_vblank(&malidp->crtc);
1214
1215 #ifdef CONFIG_DEBUG_FS
1216 if (status & de->err_mask) {
1217 malidp_error(malidp, &malidp->de_errors, status,
1218 drm_crtc_vblank_count(&malidp->crtc));
1219 }
1220 #endif
1221 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1222
1223 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1224 }
1225
1226 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1227 {
1228 struct drm_device *drm = arg;
1229 struct malidp_drm *malidp = drm->dev_private;
1230
1231 wake_up(&malidp->wq);
1232
1233 return IRQ_HANDLED;
1234 }
1235
1236 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1237 {
1238
1239 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1240 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1241 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1242 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1243
1244
1245 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1246 hwdev->hw->map.dc_irq_map.irq_mask);
1247
1248
1249 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1250 hwdev->hw->map.de_irq_map.irq_mask);
1251 }
1252
1253 int malidp_de_irq_init(struct drm_device *drm, int irq)
1254 {
1255 struct malidp_drm *malidp = drm->dev_private;
1256 struct malidp_hw_device *hwdev = malidp->dev;
1257 int ret;
1258
1259
1260 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1261 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1262 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1263 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1264
1265 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1266 malidp_de_irq_thread_handler,
1267 IRQF_SHARED, "malidp-de", drm);
1268 if (ret < 0) {
1269 DRM_ERROR("failed to install DE IRQ handler\n");
1270 return ret;
1271 }
1272
1273 malidp_de_irq_hw_init(hwdev);
1274
1275 return 0;
1276 }
1277
1278 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1279 {
1280 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1281 hwdev->hw->map.de_irq_map.irq_mask);
1282 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1283 hwdev->hw->map.dc_irq_map.irq_mask);
1284 }
1285
1286 static irqreturn_t malidp_se_irq(int irq, void *arg)
1287 {
1288 struct drm_device *drm = arg;
1289 struct malidp_drm *malidp = drm->dev_private;
1290 struct malidp_hw_device *hwdev = malidp->dev;
1291 struct malidp_hw *hw = hwdev->hw;
1292 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1293 u32 status, mask;
1294
1295
1296
1297
1298
1299
1300 if (hwdev->pm_suspended)
1301 return IRQ_NONE;
1302
1303 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1304 if (!(status & (se->irq_mask | se->err_mask)))
1305 return IRQ_NONE;
1306
1307 #ifdef CONFIG_DEBUG_FS
1308 if (status & se->err_mask)
1309 malidp_error(malidp, &malidp->se_errors, status,
1310 drm_crtc_vblank_count(&malidp->crtc));
1311 #endif
1312 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1313 status &= mask;
1314
1315 if (status & se->vsync_irq) {
1316 switch (hwdev->mw_state) {
1317 case MW_ONESHOT:
1318 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1319 break;
1320 case MW_STOP:
1321 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1322
1323 hwdev->mw_state = MW_NOT_ENABLED;
1324 break;
1325 case MW_RESTART:
1326 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1327 fallthrough;
1328 case MW_START:
1329
1330 hw->disable_memwrite(hwdev);
1331
1332
1333
1334
1335
1336 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1337 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1338 (status & hw->map.dc_irq_map.vsync_irq))
1339 hw->set_config_valid(hwdev, 1);
1340 break;
1341 }
1342 }
1343
1344 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1345
1346 return IRQ_HANDLED;
1347 }
1348
1349 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1350 {
1351
1352 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1353 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1354
1355 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1356 hwdev->hw->map.se_irq_map.irq_mask);
1357 }
1358
1359 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1360 {
1361 return IRQ_HANDLED;
1362 }
1363
1364 int malidp_se_irq_init(struct drm_device *drm, int irq)
1365 {
1366 struct malidp_drm *malidp = drm->dev_private;
1367 struct malidp_hw_device *hwdev = malidp->dev;
1368 int ret;
1369
1370
1371 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1372 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1373
1374 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1375 malidp_se_irq_thread_handler,
1376 IRQF_SHARED, "malidp-se", drm);
1377 if (ret < 0) {
1378 DRM_ERROR("failed to install SE IRQ handler\n");
1379 return ret;
1380 }
1381
1382 hwdev->mw_state = MW_NOT_ENABLED;
1383 malidp_se_irq_hw_init(hwdev);
1384
1385 return 0;
1386 }
1387
1388 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1389 {
1390 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1391 hwdev->hw->map.se_irq_map.irq_mask);
1392 }