Linux Audio

Check our new training course

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