diff options
Diffstat (limited to 'drivers/gpu/drm/msm')
63 files changed, 3293 insertions, 420 deletions
| diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 0a6f6764a37c..08ba8d0d93f5 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -46,3 +46,10 @@ config DRM_MSM_DSI  	  Choose this option if you have a need for MIPI DSI connector  	  support. +config DRM_MSM_DSI_PLL +	bool "Enable DSI PLL driver in MSM DRM" +	depends on DRM_MSM_DSI && COMMON_CLK +	default y +	help +	  Choose this option to enable DSI PLL driver which provides DSI +	  source clocks under common clock framework. diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index ab2086783fee..16a81b94d6f0 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,4 +1,5 @@  ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm +ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi  msm-y := \  	adreno/adreno_device.o \ @@ -50,10 +51,14 @@ msm-y := \  msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o  msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o +  msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \  			dsi/dsi_host.o \  			dsi/dsi_manager.o \  			dsi/dsi_phy.o \  			mdp/mdp5/mdp5_cmd_encoder.o +msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \ +				dsi/pll/dsi_pll_28nm.o +  obj-$(CONFIG_DRM_MSM)	+= msm.o diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h index edc845fffdf4..23176e402796 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h @@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)  Copyright (C) 2013-2014 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h index e91a739452d7..1c599e5cf318 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h @@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -130,6 +130,10 @@ enum a3xx_tex_fmt {  	TFMT_I420_Y = 24,  	TFMT_I420_U = 26,  	TFMT_I420_V = 27, +	TFMT_ATC_RGB = 32, +	TFMT_ATC_RGBA_EXPLICIT = 33, +	TFMT_ETC1 = 34, +	TFMT_ATC_RGBA_INTERPOLATED = 35,  	TFMT_DXT1 = 36,  	TFMT_DXT3 = 37,  	TFMT_DXT5 = 38, @@ -178,10 +182,13 @@ enum a3xx_tex_fmt {  	TFMT_32_SINT = 92,  	TFMT_32_32_SINT = 93,  	TFMT_32_32_32_32_SINT = 95, -	TFMT_RGTC2_SNORM = 112, -	TFMT_RGTC2_UNORM = 113, -	TFMT_RGTC1_SNORM = 114, -	TFMT_RGTC1_UNORM = 115, +	TFMT_ETC2_RG11_SNORM = 112, +	TFMT_ETC2_RG11_UNORM = 113, +	TFMT_ETC2_R11_SNORM = 114, +	TFMT_ETC2_R11_UNORM = 115, +	TFMT_ETC2_RGBA8 = 116, +	TFMT_ETC2_RGB8A1 = 117, +	TFMT_ETC2_RGB8 = 118,  };  enum a3xx_tex_fetchsize { @@ -209,14 +216,24 @@ enum a3xx_color_fmt {  	RB_R10G10B10A2_UNORM = 16,  	RB_A8_UNORM = 20,  	RB_R8_UNORM = 21, +	RB_R16_FLOAT = 24, +	RB_R16G16_FLOAT = 25,  	RB_R16G16B16A16_FLOAT = 27,  	RB_R11G11B10_FLOAT = 28, +	RB_R16_SNORM = 32, +	RB_R16G16_SNORM = 33, +	RB_R16G16B16A16_SNORM = 35, +	RB_R16_UNORM = 36, +	RB_R16G16_UNORM = 37, +	RB_R16G16B16A16_UNORM = 39,  	RB_R16_SINT = 40,  	RB_R16G16_SINT = 41,  	RB_R16G16B16A16_SINT = 43,  	RB_R16_UINT = 44,  	RB_R16G16_UINT = 45,  	RB_R16G16B16A16_UINT = 47, +	RB_R32_FLOAT = 48, +	RB_R32G32_FLOAT = 49,  	RB_R32G32B32A32_FLOAT = 51,  	RB_R32_SINT = 52,  	RB_R32G32_SINT = 53, @@ -265,6 +282,12 @@ enum a3xx_intp_mode {  	FLAT = 1,  }; +enum a3xx_repl_mode { +	S = 1, +	T = 2, +	ONE_T = 3, +}; +  enum a3xx_tex_filter {  	A3XX_TEX_NEAREST = 0,  	A3XX_TEX_LINEAR = 1, @@ -751,7 +774,7 @@ static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)  #define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT			0  static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)  { -	return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK; +	return ((((int32_t)(val * 64.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;  }  #define REG_A3XX_GRAS_SU_MODE_CONTROL				0x00002070 @@ -854,6 +877,12 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_RENDER_MODE(enum a3xx_render_mode va  {  	return ((val) << A3XX_RB_MODE_CONTROL_RENDER_MODE__SHIFT) & A3XX_RB_MODE_CONTROL_RENDER_MODE__MASK;  } +#define A3XX_RB_MODE_CONTROL_MRT__MASK				0x00003000 +#define A3XX_RB_MODE_CONTROL_MRT__SHIFT				12 +static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val) +{ +	return ((val) << A3XX_RB_MODE_CONTROL_MRT__SHIFT) & A3XX_RB_MODE_CONTROL_MRT__MASK; +}  #define A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE		0x00008000  #define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE		0x00010000 @@ -1246,9 +1275,21 @@ static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op v  #define REG_A3XX_RB_STENCIL_CLEAR				0x00002105 -#define REG_A3XX_RB_STENCIL_BUF_INFO				0x00002106 +#define REG_A3XX_RB_STENCIL_INFO				0x00002106 +#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK			0xfffff800 +#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT		11 +static inline uint32_t A3XX_RB_STENCIL_INFO_STENCIL_BASE(uint32_t val) +{ +	return ((val >> 12) << A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT) & A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK; +} -#define REG_A3XX_RB_STENCIL_BUF_PITCH				0x00002107 +#define REG_A3XX_RB_STENCIL_PITCH				0x00002107 +#define A3XX_RB_STENCIL_PITCH__MASK				0xffffffff +#define A3XX_RB_STENCIL_PITCH__SHIFT				0 +static inline uint32_t A3XX_RB_STENCIL_PITCH(uint32_t val) +{ +	return ((val >> 3) << A3XX_RB_STENCIL_PITCH__SHIFT) & A3XX_RB_STENCIL_PITCH__MASK; +}  #define REG_A3XX_RB_STENCILREFMASK				0x00002108  #define A3XX_RB_STENCILREFMASK_STENCILREF__MASK			0x000000ff @@ -1356,6 +1397,7 @@ static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(enum adreno_pa_  {  	return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;  } +#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE			0x00001000  #define A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART			0x00100000  #define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST		0x02000000  #define A3XX_PC_PRIM_VTX_CNTL_PSIZE				0x04000000 @@ -1805,6 +1847,102 @@ static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CF(enum a3xx_intp_mode val)  static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x00002286 + 0x1*i0; }  static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x00002286 + 0x1*i0; } +#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK			0x00000003 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT			0 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C0(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK			0x0000000c +#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT			2 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C1(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK			0x00000030 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT			4 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C2(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK			0x000000c0 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT			6 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C3(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK			0x00000300 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT			8 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C4(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK			0x00000c00 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT			10 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C5(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK			0x00003000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT			12 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C6(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK			0x0000c000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT			14 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C7(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK			0x00030000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT			16 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C8(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK			0x000c0000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT			18 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C9(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK			0x00300000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT			20 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CA(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK			0x00c00000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT			22 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CB(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK			0x03000000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT			24 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CC(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK			0x0c000000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT			26 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CD(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK			0x30000000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT			28 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CE(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK; +} +#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK			0xc0000000 +#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT			30 +static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CF(enum a3xx_repl_mode val) +{ +	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK; +}  #define REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_0			0x0000228a @@ -2107,6 +2245,12 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)  #define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1			0x000022e9  #define REG_A3XX_SP_FS_OUTPUT_REG				0x000022ec +#define A3XX_SP_FS_OUTPUT_REG_MRT__MASK				0x00000003 +#define A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT			0 +static inline uint32_t A3XX_SP_FS_OUTPUT_REG_MRT(uint32_t val) +{ +	return ((val) << A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A3XX_SP_FS_OUTPUT_REG_MRT__MASK; +}  #define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE			0x00000080  #define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK			0x0000ff00  #define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT		8 @@ -2661,7 +2805,7 @@ static inline uint32_t A3XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)  }  #define REG_A3XX_TEX_CONST_3					0x00000003 -#define A3XX_TEX_CONST_3_LAYERSZ1__MASK				0x0000000f +#define A3XX_TEX_CONST_3_LAYERSZ1__MASK				0x00007fff  #define A3XX_TEX_CONST_3_LAYERSZ1__SHIFT			0  static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ1(uint32_t val)  { diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index b66c53bdc039..fd266ed963b6 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -93,7 +93,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu)  		/* Set up AOOO: */  		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);  		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); - +	} else if (adreno_is_a306(adreno_gpu)) { +		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003); +		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a); +		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);  	} else if (adreno_is_a320(adreno_gpu)) {  		/* Set up 16 deep read/write request queues: */  		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); @@ -186,7 +189,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)  	gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);  	/* Enable Clock gating: */ -	if (adreno_is_a320(adreno_gpu)) +	if (adreno_is_a306(adreno_gpu)) +		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); +	else if (adreno_is_a320(adreno_gpu))  		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);  	else if (adreno_is_a330v2(adreno_gpu))  		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); @@ -271,7 +276,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu)  		gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);  	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ -	if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) { +	if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) || +			adreno_is_a320(adreno_gpu)) {  		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,  				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |  				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) | @@ -295,9 +301,12 @@ static int a3xx_hw_init(struct msm_gpu *gpu)  static void a3xx_recover(struct msm_gpu *gpu)  { +	adreno_dump_info(gpu); +  	/* dump registers before resetting gpu, if enabled: */  	if (hang_debug)  		a3xx_dump(gpu); +  	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);  	gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);  	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h index 755723fd8ba5..3f06ecf62583 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h @@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -43,10 +43,40 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  enum a4xx_color_fmt {  	RB4_A8_UNORM = 1, +	RB4_R8_UNORM = 2, +	RB4_R4G4B4A4_UNORM = 8, +	RB4_R5G5B5A1_UNORM = 10,  	RB4_R5G6R5_UNORM = 14, -	RB4_Z16_UNORM = 15, +	RB4_R8G8_UNORM = 15, +	RB4_R8G8_SNORM = 16, +	RB4_R8G8_UINT = 17, +	RB4_R8G8_SINT = 18, +	RB4_R16_FLOAT = 21, +	RB4_R16_UINT = 22, +	RB4_R16_SINT = 23,  	RB4_R8G8B8_UNORM = 25,  	RB4_R8G8B8A8_UNORM = 26, +	RB4_R8G8B8A8_SNORM = 28, +	RB4_R8G8B8A8_UINT = 29, +	RB4_R8G8B8A8_SINT = 30, +	RB4_R10G10B10A2_UNORM = 31, +	RB4_R10G10B10A2_UINT = 34, +	RB4_R11G11B10_FLOAT = 39, +	RB4_R16G16_FLOAT = 42, +	RB4_R16G16_UINT = 43, +	RB4_R16G16_SINT = 44, +	RB4_R32_FLOAT = 45, +	RB4_R32_UINT = 46, +	RB4_R32_SINT = 47, +	RB4_R16G16B16A16_FLOAT = 54, +	RB4_R16G16B16A16_UINT = 55, +	RB4_R16G16B16A16_SINT = 56, +	RB4_R32G32_FLOAT = 57, +	RB4_R32G32_UINT = 58, +	RB4_R32G32_SINT = 59, +	RB4_R32G32B32A32_FLOAT = 60, +	RB4_R32G32B32A32_UINT = 61, +	RB4_R32G32B32A32_SINT = 62,  };  enum a4xx_tile_mode { @@ -91,7 +121,14 @@ enum a4xx_vtx_fmt {  	VFMT4_16_16_UNORM = 29,  	VFMT4_16_16_16_UNORM = 30,  	VFMT4_16_16_16_16_UNORM = 31, +	VFMT4_32_UINT = 32, +	VFMT4_32_32_UINT = 33, +	VFMT4_32_32_32_UINT = 34, +	VFMT4_32_32_32_32_UINT = 35, +	VFMT4_32_SINT = 36,  	VFMT4_32_32_SINT = 37, +	VFMT4_32_32_32_SINT = 38, +	VFMT4_32_32_32_32_SINT = 39,  	VFMT4_8_UINT = 40,  	VFMT4_8_8_UINT = 41,  	VFMT4_8_8_8_UINT = 42, @@ -125,12 +162,57 @@ enum a4xx_tex_fmt {  	TFMT4_8_UNORM = 4,  	TFMT4_8_8_UNORM = 14,  	TFMT4_8_8_8_8_UNORM = 28, +	TFMT4_8_8_SNORM = 15, +	TFMT4_8_8_8_8_SNORM = 29, +	TFMT4_8_8_UINT = 16, +	TFMT4_8_8_8_8_UINT = 30, +	TFMT4_8_8_SINT = 17, +	TFMT4_8_8_8_8_SINT = 31, +	TFMT4_16_UINT = 21, +	TFMT4_16_16_UINT = 41, +	TFMT4_16_16_16_16_UINT = 54, +	TFMT4_16_SINT = 22, +	TFMT4_16_16_SINT = 42, +	TFMT4_16_16_16_16_SINT = 55, +	TFMT4_32_UINT = 44, +	TFMT4_32_32_UINT = 57, +	TFMT4_32_32_32_32_UINT = 64, +	TFMT4_32_SINT = 45, +	TFMT4_32_32_SINT = 58, +	TFMT4_32_32_32_32_SINT = 65,  	TFMT4_16_FLOAT = 20,  	TFMT4_16_16_FLOAT = 40,  	TFMT4_16_16_16_16_FLOAT = 53,  	TFMT4_32_FLOAT = 43,  	TFMT4_32_32_FLOAT = 56,  	TFMT4_32_32_32_32_FLOAT = 63, +	TFMT4_9_9_9_E5_FLOAT = 32, +	TFMT4_11_11_10_FLOAT = 37, +	TFMT4_ATC_RGB = 100, +	TFMT4_ATC_RGBA_EXPLICIT = 101, +	TFMT4_ATC_RGBA_INTERPOLATED = 102, +	TFMT4_ETC2_RG11_UNORM = 103, +	TFMT4_ETC2_RG11_SNORM = 104, +	TFMT4_ETC2_R11_UNORM = 105, +	TFMT4_ETC2_R11_SNORM = 106, +	TFMT4_ETC1 = 107, +	TFMT4_ETC2_RGB8 = 108, +	TFMT4_ETC2_RGBA8 = 109, +	TFMT4_ETC2_RGB8A1 = 110, +	TFMT4_ASTC_4x4 = 111, +	TFMT4_ASTC_5x4 = 112, +	TFMT4_ASTC_5x5 = 113, +	TFMT4_ASTC_6x5 = 114, +	TFMT4_ASTC_6x6 = 115, +	TFMT4_ASTC_8x5 = 116, +	TFMT4_ASTC_8x6 = 117, +	TFMT4_ASTC_8x8 = 118, +	TFMT4_ASTC_10x5 = 119, +	TFMT4_ASTC_10x6 = 120, +	TFMT4_ASTC_10x8 = 121, +	TFMT4_ASTC_10x10 = 122, +	TFMT4_ASTC_12x10 = 123, +	TFMT4_ASTC_12x12 = 124,  };  enum a4xx_tex_fetchsize { @@ -147,9 +229,16 @@ enum a4xx_depth_format {  	DEPTH4_24_8 = 2,  }; +enum a4xx_tess_spacing { +	EQUAL_SPACING = 0, +	ODD_SPACING = 2, +	EVEN_SPACING = 3, +}; +  enum a4xx_tex_filter {  	A4XX_TEX_NEAREST = 0,  	A4XX_TEX_LINEAR = 1, +	A4XX_TEX_ANISO = 2,  };  enum a4xx_tex_clamp { @@ -159,6 +248,14 @@ enum a4xx_tex_clamp {  	A4XX_TEX_CLAMP_NONE = 3,  }; +enum a4xx_tex_aniso { +	A4XX_TEX_ANISO_1 = 0, +	A4XX_TEX_ANISO_2 = 1, +	A4XX_TEX_ANISO_4 = 2, +	A4XX_TEX_ANISO_8 = 3, +	A4XX_TEX_ANISO_16 = 4, +}; +  enum a4xx_tex_swiz {  	A4XX_TEX_X = 0,  	A4XX_TEX_Y = 1, @@ -279,13 +376,16 @@ static inline uint32_t A4XX_RB_MSAA_CONTROL_SAMPLES(uint32_t val)  #define A4XX_RB_RENDER_CONTROL2_YCOORD				0x00000002  #define A4XX_RB_RENDER_CONTROL2_ZCOORD				0x00000004  #define A4XX_RB_RENDER_CONTROL2_WCOORD				0x00000008 +#define A4XX_RB_RENDER_CONTROL2_SAMPLEMASK			0x00000010  #define A4XX_RB_RENDER_CONTROL2_FACENESS			0x00000020 +#define A4XX_RB_RENDER_CONTROL2_SAMPLEID			0x00000040  #define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK		0x00000380  #define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT		7  static inline uint32_t A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(uint32_t val)  {  	return ((val) << A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK;  } +#define A4XX_RB_RENDER_CONTROL2_SAMPLEID_HR			0x00000800  #define A4XX_RB_RENDER_CONTROL2_VARYING				0x00001000  static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; } @@ -310,6 +410,12 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a4xx_color_fmt val  {  	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;  } +#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK		0x000000c0 +#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT		6 +static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a4xx_tile_mode val) +{ +	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK; +}  #define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__MASK			0x00000600  #define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__SHIFT			9  static inline uint32_t A4XX_RB_MRT_BUF_INFO_DITHER_MODE(enum adreno_rb_dither_mode val) @@ -322,6 +428,7 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)  {  	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;  } +#define A4XX_RB_MRT_BUF_INFO_COLOR_SRGB				0x00002000  #define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK		0x007fc000  #define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT		14  static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val) @@ -449,7 +556,12 @@ static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare  }  #define REG_A4XX_RB_FS_OUTPUT					0x000020f9 -#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND				0x00000001 +#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK			0x000000ff +#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT			0 +static inline uint32_t A4XX_RB_FS_OUTPUT_ENABLE_BLEND(uint32_t val) +{ +	return ((val) << A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT) & A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK; +}  #define A4XX_RB_FS_OUTPUT_FAST_CLEAR				0x00000100  #define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK			0xffff0000  #define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT			16 @@ -458,12 +570,54 @@ static inline uint32_t A4XX_RB_FS_OUTPUT_SAMPLE_MASK(uint32_t val)  	return ((val) << A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT) & A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK;  } -#define REG_A4XX_RB_RENDER_CONTROL3				0x000020fb -#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK		0x0000001f -#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT		0 -static inline uint32_t A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE(uint32_t val) +#define REG_A4XX_RB_RENDER_COMPONENTS				0x000020fb +#define A4XX_RB_RENDER_COMPONENTS_RT0__MASK			0x0000000f +#define A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT			0 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)  { -	return ((val) << A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT) & A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK; +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT0__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT1__MASK			0x000000f0 +#define A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT			4 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT1(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT1__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT2__MASK			0x00000f00 +#define A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT			8 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT2(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT2__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT3__MASK			0x0000f000 +#define A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT			12 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT3(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT3__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT4__MASK			0x000f0000 +#define A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT			16 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT4(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT4__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT5__MASK			0x00f00000 +#define A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT			20 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT5(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT5__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT6__MASK			0x0f000000 +#define A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT			24 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT6(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT6__MASK; +} +#define A4XX_RB_RENDER_COMPONENTS_RT7__MASK			0xf0000000 +#define A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT			28 +static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT7(uint32_t val) +{ +	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT7__MASK;  }  #define REG_A4XX_RB_COPY_CONTROL				0x000020fc @@ -547,7 +701,12 @@ static inline uint32_t A4XX_RB_COPY_DEST_INFO_TILE(enum a4xx_tile_mode val)  }  #define REG_A4XX_RB_FS_OUTPUT_REG				0x00002100 -#define A4XX_RB_FS_OUTPUT_REG_COLOR_PIPE_ENABLE			0x00000001 +#define A4XX_RB_FS_OUTPUT_REG_MRT__MASK				0x0000000f +#define A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT			0 +static inline uint32_t A4XX_RB_FS_OUTPUT_REG_MRT(uint32_t val) +{ +	return ((val) << A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_RB_FS_OUTPUT_REG_MRT__MASK; +}  #define A4XX_RB_FS_OUTPUT_REG_FRAG_WRITES_Z			0x00000020  #define REG_A4XX_RB_DEPTH_CONTROL				0x00002101 @@ -930,6 +1089,10 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)  #define REG_A4XX_CP_IB2_BUFSZ					0x00000209 +#define REG_A4XX_CP_ME_NRT_ADDR					0x0000020c + +#define REG_A4XX_CP_ME_NRT_DATA					0x0000020d +  #define REG_A4XX_CP_ME_RB_DONE_DATA				0x00000217  #define REG_A4XX_CP_QUEUE_THRESH2				0x00000219 @@ -940,9 +1103,9 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)  #define REG_A4XX_CP_ROQ_DATA					0x0000021d -#define REG_A4XX_CP_MEQ_ADDR 					0x0000021e +#define REG_A4XX_CP_MEQ_ADDR					0x0000021e -#define REG_A4XX_CP_MEQ_DATA 					0x0000021f +#define REG_A4XX_CP_MEQ_DATA					0x0000021f  #define REG_A4XX_CP_MERCIU_ADDR					0x00000220 @@ -1004,12 +1167,17 @@ static inline uint32_t REG_A4XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000578  #define REG_A4XX_SP_VS_STATUS					0x00000ec0 +#define REG_A4XX_SP_MODE_CONTROL				0x00000ec3 +  #define REG_A4XX_SP_PERFCTR_SP_SEL_11				0x00000ecf  #define REG_A4XX_SP_SP_CTRL_REG					0x000022c0  #define A4XX_SP_SP_CTRL_REG_BINNING_PASS			0x00080000  #define REG_A4XX_SP_INSTR_CACHE_CTRL				0x000022c1 +#define A4XX_SP_INSTR_CACHE_CTRL_VS_BUFFER			0x00000080 +#define A4XX_SP_INSTR_CACHE_CTRL_FS_BUFFER			0x00000100 +#define A4XX_SP_INSTR_CACHE_CTRL_INSTR_BUFFER			0x00000400  #define REG_A4XX_SP_VS_CTRL_REG0				0x000022c4  #define A4XX_SP_VS_CTRL_REG0_THREADMODE__MASK			0x00000001 @@ -1229,6 +1397,12 @@ static inline uint32_t A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)  #define REG_A4XX_SP_FS_LENGTH_REG				0x000022ef  #define REG_A4XX_SP_FS_OUTPUT_REG				0x000022f0 +#define A4XX_SP_FS_OUTPUT_REG_MRT__MASK				0x0000000f +#define A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT			0 +static inline uint32_t A4XX_SP_FS_OUTPUT_REG_MRT(uint32_t val) +{ +	return ((val) << A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_SP_FS_OUTPUT_REG_MRT__MASK; +}  #define A4XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE			0x00000080  #define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK			0x0000ff00  #define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT		8 @@ -1236,6 +1410,12 @@ static inline uint32_t A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)  {  	return ((val) << A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;  } +#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK		0xff000000 +#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT		24 +static inline uint32_t A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID(uint32_t val) +{ +	return ((val) << A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK; +}  static inline uint32_t REG_A4XX_SP_FS_MRT(uint32_t i0) { return 0x000022f1 + 0x1*i0; } @@ -1254,6 +1434,20 @@ static inline uint32_t A4XX_SP_FS_MRT_REG_MRTFORMAT(enum a4xx_color_fmt val)  	return ((val) << A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT) & A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK;  } +#define REG_A4XX_SP_CS_CTRL_REG0				0x00002300 + +#define REG_A4XX_SP_CS_OBJ_OFFSET_REG				0x00002301 + +#define REG_A4XX_SP_CS_OBJ_START				0x00002302 + +#define REG_A4XX_SP_CS_PVT_MEM_PARAM				0x00002303 + +#define REG_A4XX_SP_CS_PVT_MEM_ADDR				0x00002304 + +#define REG_A4XX_SP_CS_PVT_MEM_SIZE				0x00002305 + +#define REG_A4XX_SP_CS_LENGTH_REG				0x00002306 +  #define REG_A4XX_SP_HS_OBJ_OFFSET_REG				0x0000230d  #define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000  #define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16 @@ -1268,6 +1462,14 @@ static inline uint32_t A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)  	return ((val) << A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;  } +#define REG_A4XX_SP_HS_OBJ_START				0x0000230e + +#define REG_A4XX_SP_HS_PVT_MEM_PARAM				0x0000230f + +#define REG_A4XX_SP_HS_PVT_MEM_ADDR				0x00002310 + +#define REG_A4XX_SP_HS_LENGTH_REG				0x00002312 +  #define REG_A4XX_SP_DS_OBJ_OFFSET_REG				0x00002334  #define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000  #define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16 @@ -1282,6 +1484,14 @@ static inline uint32_t A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)  	return ((val) << A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;  } +#define REG_A4XX_SP_DS_OBJ_START				0x00002335 + +#define REG_A4XX_SP_DS_PVT_MEM_PARAM				0x00002336 + +#define REG_A4XX_SP_DS_PVT_MEM_ADDR				0x00002337 + +#define REG_A4XX_SP_DS_LENGTH_REG				0x00002339 +  #define REG_A4XX_SP_GS_OBJ_OFFSET_REG				0x0000235b  #define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000  #define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16 @@ -1296,6 +1506,12 @@ static inline uint32_t A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)  	return ((val) << A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;  } +#define REG_A4XX_SP_GS_OBJ_START				0x0000235c + +#define REG_A4XX_SP_GS_PVT_MEM_PARAM				0x0000235d + +#define REG_A4XX_SP_GS_PVT_MEM_ADDR				0x0000235e +  #define REG_A4XX_SP_GS_LENGTH_REG				0x00002360  #define REG_A4XX_VPC_DEBUG_RAM_SEL				0x00000e60 @@ -1418,6 +1634,10 @@ static inline uint32_t REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(uint32_t i0) { return 0  #define REG_A4XX_VFD_PERFCTR_VFD_SEL_7				0x00000e4a +#define REG_A4XX_VGT_CL_INITIATOR				0x000021d0 + +#define REG_A4XX_VGT_EVENT_INITIATOR				0x000021d9 +  #define REG_A4XX_VFD_CONTROL_0					0x00002200  #define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK			0x000000ff  #define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT			0 @@ -1554,10 +1774,54 @@ static inline uint32_t A4XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)  #define REG_A4XX_TPL1_DEBUG_ECO_CONTROL				0x00000f00 +#define REG_A4XX_TPL1_TP_MODE_CONTROL				0x00000f03 +  #define REG_A4XX_TPL1_PERFCTR_TP_SEL_7				0x00000f0b  #define REG_A4XX_TPL1_TP_TEX_OFFSET				0x00002380 +#define REG_A4XX_TPL1_TP_TEX_COUNT				0x00002381 +#define A4XX_TPL1_TP_TEX_COUNT_VS__MASK				0x000000ff +#define A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT			0 +static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_VS(uint32_t val) +{ +	return ((val) << A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_VS__MASK; +} +#define A4XX_TPL1_TP_TEX_COUNT_HS__MASK				0x0000ff00 +#define A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT			8 +static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_HS(uint32_t val) +{ +	return ((val) << A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_HS__MASK; +} +#define A4XX_TPL1_TP_TEX_COUNT_DS__MASK				0x00ff0000 +#define A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT			16 +static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_DS(uint32_t val) +{ +	return ((val) << A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_DS__MASK; +} +#define A4XX_TPL1_TP_TEX_COUNT_GS__MASK				0xff000000 +#define A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT			24 +static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_GS(uint32_t val) +{ +	return ((val) << A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_GS__MASK; +} + +#define REG_A4XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR		0x00002384 + +#define REG_A4XX_TPL1_TP_HS_BORDER_COLOR_BASE_ADDR		0x00002387 + +#define REG_A4XX_TPL1_TP_DS_BORDER_COLOR_BASE_ADDR		0x0000238a + +#define REG_A4XX_TPL1_TP_GS_BORDER_COLOR_BASE_ADDR		0x0000238d + +#define REG_A4XX_TPL1_TP_FS_TEX_COUNT				0x000023a0 + +#define REG_A4XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR		0x000023a1 + +#define REG_A4XX_TPL1_TP_CS_BORDER_COLOR_BASE_ADDR		0x000023a4 + +#define REG_A4XX_TPL1_TP_CS_SAMPLER_BASE_ADDR			0x000023a5 +  #define REG_A4XX_TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR			0x000023a6  #define REG_A4XX_GRAS_TSE_STATUS				0x00000c80 @@ -1676,6 +1940,14 @@ static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)  	return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;  } +#define REG_A4XX_GRAS_SU_POLY_OFFSET_CLAMP			0x00002076 +#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK			0xffffffff +#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT			0 +static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_CLAMP(float val) +{ +	return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK; +} +  #define REG_A4XX_GRAS_DEPTH_CONTROL				0x00002077  #define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK			0x00000003  #define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT			0 @@ -1828,6 +2100,8 @@ static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y(uint32_t val)  #define REG_A4XX_HLSQ_DEBUG_ECO_CONTROL				0x00000e04 +#define REG_A4XX_HLSQ_MODE_CONTROL				0x00000e05 +  #define REG_A4XX_HLSQ_PERF_PIPE_MASK				0x00000e0e  #define REG_A4XX_HLSQ_CONTROL_0_REG				0x000023c0 @@ -1867,7 +2141,12 @@ static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_COORDREGID(uint32_t val)  {  	return ((val) << A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK;  } -#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORD				0x02000000 +#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK		0xff000000 +#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT		24 +static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID(uint32_t val) +{ +	return ((val) << A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK; +}  #define REG_A4XX_HLSQ_CONTROL_2_REG				0x000023c2  #define A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK	0xfc000000 @@ -1882,6 +2161,18 @@ static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)  {  	return ((val) << A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;  } +#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK		0x0003fc00 +#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT		10 +static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID(uint32_t val) +{ +	return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK; +} +#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK		0x03fc0000 +#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT		18 +static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID(uint32_t val) +{ +	return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK; +}  #define REG_A4XX_HLSQ_CONTROL_3_REG				0x000023c3  #define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK			0x000000ff @@ -1891,6 +2182,8 @@ static inline uint32_t A4XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)  	return ((val) << A4XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A4XX_HLSQ_CONTROL_3_REG_REGID__MASK;  } +#define REG_A4XX_HLSQ_CONTROL_4_REG				0x000023c4 +  #define REG_A4XX_HLSQ_VS_CONTROL_REG				0x000023c5  #define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK		0x000000ff  #define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT		0 @@ -1904,6 +2197,7 @@ static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)  {  	return ((val) << A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;  } +#define A4XX_HLSQ_VS_CONTROL_REG_ENABLED			0x00010000  #define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000  #define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17  static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val) @@ -1930,6 +2224,7 @@ static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)  {  	return ((val) << A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;  } +#define A4XX_HLSQ_FS_CONTROL_REG_ENABLED			0x00010000  #define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000  #define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17  static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val) @@ -1956,6 +2251,7 @@ static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)  {  	return ((val) << A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;  } +#define A4XX_HLSQ_HS_CONTROL_REG_ENABLED			0x00010000  #define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000  #define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17  static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val) @@ -1982,6 +2278,7 @@ static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)  {  	return ((val) << A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;  } +#define A4XX_HLSQ_DS_CONTROL_REG_ENABLED			0x00010000  #define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000  #define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17  static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val) @@ -2008,6 +2305,7 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)  {  	return ((val) << A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;  } +#define A4XX_HLSQ_GS_CONTROL_REG_ENABLED			0x00010000  #define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000  #define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17  static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val) @@ -2021,6 +2319,36 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)  	return ((val) << A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__MASK;  } +#define REG_A4XX_HLSQ_CS_CONTROL				0x000023ca + +#define REG_A4XX_HLSQ_CL_NDRANGE_0				0x000023cd + +#define REG_A4XX_HLSQ_CL_NDRANGE_1				0x000023ce + +#define REG_A4XX_HLSQ_CL_NDRANGE_2				0x000023cf + +#define REG_A4XX_HLSQ_CL_NDRANGE_3				0x000023d0 + +#define REG_A4XX_HLSQ_CL_NDRANGE_4				0x000023d1 + +#define REG_A4XX_HLSQ_CL_NDRANGE_5				0x000023d2 + +#define REG_A4XX_HLSQ_CL_NDRANGE_6				0x000023d3 + +#define REG_A4XX_HLSQ_CL_CONTROL_0				0x000023d4 + +#define REG_A4XX_HLSQ_CL_CONTROL_1				0x000023d5 + +#define REG_A4XX_HLSQ_CL_KERNEL_CONST				0x000023d6 + +#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_X				0x000023d7 + +#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Y				0x000023d8 + +#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Z				0x000023d9 + +#define REG_A4XX_HLSQ_CL_WG_OFFSET				0x000023da +  #define REG_A4XX_HLSQ_UPDATE_CONTROL				0x000023db  #define REG_A4XX_PC_BINNING_COMMAND				0x00000d00 @@ -2035,7 +2363,13 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)  #define REG_A4XX_PC_BIN_BASE					0x000021c0  #define REG_A4XX_PC_PRIM_VTX_CNTL				0x000021c4 -#define A4XX_PC_PRIM_VTX_CNTL_VAROUT				0x00000001 +#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK			0x0000000f +#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT			0 +static inline uint32_t A4XX_PC_PRIM_VTX_CNTL_VAROUT(uint32_t val) +{ +	return ((val) << A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT) & A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK; +} +#define A4XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART			0x00100000  #define A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST		0x02000000  #define A4XX_PC_PRIM_VTX_CNTL_PSIZE				0x04000000 @@ -2044,8 +2378,45 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)  #define REG_A4XX_PC_RESTART_INDEX				0x000021c6  #define REG_A4XX_PC_GS_PARAM					0x000021e5 +#define A4XX_PC_GS_PARAM_MAX_VERTICES__MASK			0x000003ff +#define A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT			0 +static inline uint32_t A4XX_PC_GS_PARAM_MAX_VERTICES(uint32_t val) +{ +	return ((val) << A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT) & A4XX_PC_GS_PARAM_MAX_VERTICES__MASK; +} +#define A4XX_PC_GS_PARAM_INVOCATIONS__MASK			0x0000f800 +#define A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT			11 +static inline uint32_t A4XX_PC_GS_PARAM_INVOCATIONS(uint32_t val) +{ +	return ((val) << A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT) & A4XX_PC_GS_PARAM_INVOCATIONS__MASK; +} +#define A4XX_PC_GS_PARAM_PRIMTYPE__MASK				0x01800000 +#define A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT			23 +static inline uint32_t A4XX_PC_GS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val) +{ +	return ((val) << A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_GS_PARAM_PRIMTYPE__MASK; +} +#define A4XX_PC_GS_PARAM_LAYER					0x80000000  #define REG_A4XX_PC_HS_PARAM					0x000021e7 +#define A4XX_PC_HS_PARAM_VERTICES_OUT__MASK			0x0000003f +#define A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT			0 +static inline uint32_t A4XX_PC_HS_PARAM_VERTICES_OUT(uint32_t val) +{ +	return ((val) << A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT) & A4XX_PC_HS_PARAM_VERTICES_OUT__MASK; +} +#define A4XX_PC_HS_PARAM_SPACING__MASK				0x00600000 +#define A4XX_PC_HS_PARAM_SPACING__SHIFT				21 +static inline uint32_t A4XX_PC_HS_PARAM_SPACING(enum a4xx_tess_spacing val) +{ +	return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK; +} +#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK				0x01800000 +#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT			23 +static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val) +{ +	return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK; +}  #define REG_A4XX_VBIF_VERSION					0x00003000 @@ -2074,16 +2445,10 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)  #define REG_A4XX_UNKNOWN_0D01					0x00000d01 -#define REG_A4XX_UNKNOWN_0E05					0x00000e05 -  #define REG_A4XX_UNKNOWN_0E42					0x00000e42  #define REG_A4XX_UNKNOWN_0EC2					0x00000ec2 -#define REG_A4XX_UNKNOWN_0EC3					0x00000ec3 - -#define REG_A4XX_UNKNOWN_0F03					0x00000f03 -  #define REG_A4XX_UNKNOWN_2001					0x00002001  #define REG_A4XX_UNKNOWN_209B					0x0000209b @@ -2124,10 +2489,6 @@ static inline uint32_t A4XX_UNKNOWN_20F7(float val)  #define REG_A4XX_UNKNOWN_22D7					0x000022d7 -#define REG_A4XX_UNKNOWN_2381					0x00002381 - -#define REG_A4XX_UNKNOWN_23A0					0x000023a0 -  #define REG_A4XX_TEX_SAMP_0					0x00000000  #define A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR			0x00000001  #define A4XX_TEX_SAMP_0_XY_MAG__MASK				0x00000006 @@ -2160,6 +2521,12 @@ static inline uint32_t A4XX_TEX_SAMP_0_WRAP_R(enum a4xx_tex_clamp val)  {  	return ((val) << A4XX_TEX_SAMP_0_WRAP_R__SHIFT) & A4XX_TEX_SAMP_0_WRAP_R__MASK;  } +#define A4XX_TEX_SAMP_0_ANISO__MASK				0x0001c000 +#define A4XX_TEX_SAMP_0_ANISO__SHIFT				14 +static inline uint32_t A4XX_TEX_SAMP_0_ANISO(enum a4xx_tex_aniso val) +{ +	return ((val) << A4XX_TEX_SAMP_0_ANISO__SHIFT) & A4XX_TEX_SAMP_0_ANISO__MASK; +}  #define REG_A4XX_TEX_SAMP_1					0x00000001  #define A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK			0x0000000e @@ -2185,6 +2552,7 @@ static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val)  #define REG_A4XX_TEX_CONST_0					0x00000000  #define A4XX_TEX_CONST_0_TILED					0x00000001 +#define A4XX_TEX_CONST_0_SRGB					0x00000004  #define A4XX_TEX_CONST_0_SWIZ_X__MASK				0x00000070  #define A4XX_TEX_CONST_0_SWIZ_X__SHIFT				4  static inline uint32_t A4XX_TEX_CONST_0_SWIZ_X(enum a4xx_tex_swiz val) diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 91221836c5ad..a53f1be05f75 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -268,6 +268,8 @@ static int a4xx_hw_init(struct msm_gpu *gpu)  static void a4xx_recover(struct msm_gpu *gpu)  { +	adreno_dump_info(gpu); +  	/* dump registers before resetting gpu, if enabled: */  	if (hang_debug)  		a4xx_dump(gpu); @@ -505,7 +507,6 @@ static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {  static void a4xx_dump(struct msm_gpu *gpu)  { -	adreno_dump(gpu);  	printk("status:   %08x\n",  			gpu_read(gpu, REG_A4XX_RBBM_STATUS));  	adreno_dump(gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h index 8531beb982e7..9562a1fa552b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h +++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h @@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)  Copyright (C) 2013-2014 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index be83dee83d08..1ea2df524fac 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -19,7 +19,7 @@  #include "adreno_gpu.h" -#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF) +#if defined(DOWNSTREAM_CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)  #  include <mach/kgsl.h>  #endif @@ -42,6 +42,14 @@ static const struct adreno_info gpulist[] = {  		.gmem  = SZ_256K,  		.init  = a3xx_gpu_init,  	}, { +		.rev   = ADRENO_REV(3, 0, 6, 0), +		.revn  = 307,        /* because a305c is revn==306 */ +		.name  = "A306", +		.pm4fw = "a300_pm4.fw", +		.pfpfw = "a300_pfp.fw", +		.gmem  = SZ_128K, +		.init  = a3xx_gpu_init, +	}, {  		.rev   = ADRENO_REV(3, 2, ANY_ID, ANY_ID),  		.revn  = 320,  		.name  = "A320", @@ -240,7 +248,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)  			config.rev = ADRENO_REV(3, 0, 5, 0);  	} -#  ifdef CONFIG_MSM_BUS_SCALING +#  ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  	config.bus_scale_table = pdata->bus_scale_table;  #  endif  #endif diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 94a5bee69fe7..a3b54cc76495 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -176,6 +176,17 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,  	OUT_PKT3(ring, CP_INTERRUPT, 1);  	OUT_RING(ring, 0x80000000); +	/* Workaround for missing irq issue on 8x16/a306.  Unsure if the +	 * root cause is a platform issue or some a306 quirk, but this +	 * keeps things humming along: +	 */ +	if (adreno_is_a306(adreno_gpu)) { +		OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); +		OUT_RING(ring, 0x00000000); +		OUT_PKT3(ring, CP_INTERRUPT, 1); +		OUT_RING(ring, 0x80000000); +	} +  #if 0  	if (adreno_is_a3xx(adreno_gpu)) {  		/* Dummy set-constant to trigger context rollover */ @@ -249,8 +260,13 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)  }  #endif -/* would be nice to not have to duplicate the _show() stuff with printk(): */ -void adreno_dump(struct msm_gpu *gpu) +/* Dump common gpu status and scratch registers on any hang, to make + * the hangcheck logs more useful.  The scratch registers seem always + * safe to read when GPU has hung (unlike some other regs, depending + * on how the GPU hung), and they are useful to match up to cmdstream + * dumps when debugging hangs: + */ +void adreno_dump_info(struct msm_gpu *gpu)  {  	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);  	int i; @@ -266,6 +282,18 @@ void adreno_dump(struct msm_gpu *gpu)  	printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);  	printk("rb wptr:  %d\n", get_wptr(gpu->rb)); +	for (i = 0; i < 8; i++) { +		printk("CP_SCRATCH_REG%d: %u\n", i, +			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); +	} +} + +/* would be nice to not have to duplicate the _show() stuff with printk(): */ +void adreno_dump(struct msm_gpu *gpu) +{ +	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); +	int i; +  	/* dump these out in a form that can be parsed by demsm: */  	printk("IO:region %s 00000000 00020000\n", gpu->name);  	for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) { @@ -317,7 +345,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	gpu->fast_rate = config->fast_rate;  	gpu->slow_rate = config->slow_rate;  	gpu->bus_freq  = config->bus_freq; -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  	gpu->bus_scale_table = config->bus_scale_table;  #endif @@ -384,7 +412,7 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu)  	if (gpu->memptrs_bo) {  		if (gpu->memptrs_iova)  			msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); -		drm_gem_object_unreference(gpu->memptrs_bo); +		drm_gem_object_unreference_unlocked(gpu->memptrs_bo);  	}  	release_firmware(gpu->pm4);  	release_firmware(gpu->pfp); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index a0cc30977e67..0a312e9d3afd 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -167,7 +167,7 @@ struct adreno_gpu {  struct adreno_platform_config {  	struct adreno_rev rev;  	uint32_t fast_rate, slow_rate, bus_freq; -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  	struct msm_bus_scale_pdata *bus_scale_table;  #endif  }; @@ -197,6 +197,12 @@ static inline bool adreno_is_a305(struct adreno_gpu *gpu)  	return gpu->revn == 305;  } +static inline bool adreno_is_a306(struct adreno_gpu *gpu) +{ +	/* yes, 307, because a305c is 306 */ +	return gpu->revn == 307; +} +  static inline bool adreno_is_a320(struct adreno_gpu *gpu)  {  	return gpu->revn == 320; @@ -233,6 +239,7 @@ void adreno_idle(struct msm_gpu *gpu);  #ifdef CONFIG_DEBUG_FS  void adreno_show(struct msm_gpu *gpu, struct seq_file *m);  #endif +void adreno_dump_info(struct msm_gpu *gpu);  void adreno_dump(struct msm_gpu *gpu);  void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h index 6ffc4f6c8af1..bd5b23bf9041 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h +++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h @@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)  - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26) -- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35) +- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -76,16 +76,11 @@ enum pc_di_primtype {  	DI_PT_LINELOOP = 7,  	DI_PT_RECTLIST = 8,  	DI_PT_POINTLIST_A3XX = 9, -	DI_PT_QUADLIST = 13, -	DI_PT_QUADSTRIP = 14, -	DI_PT_POLYGON = 15, -	DI_PT_2D_COPY_RECT_LIST_V0 = 16, -	DI_PT_2D_COPY_RECT_LIST_V1 = 17, -	DI_PT_2D_COPY_RECT_LIST_V2 = 18, -	DI_PT_2D_COPY_RECT_LIST_V3 = 19, -	DI_PT_2D_FILL_RECT_LIST = 20, -	DI_PT_2D_LINE_STRIP = 21, -	DI_PT_2D_TRI_STRIP = 22, +	DI_PT_LINE_ADJ = 10, +	DI_PT_LINESTRIP_ADJ = 11, +	DI_PT_TRI_ADJ = 12, +	DI_PT_TRISTRIP_ADJ = 13, +	DI_PT_PATCHES = 34,  };  enum pc_di_src_sel { @@ -192,6 +187,7 @@ enum adreno_state_block {  	SB_FRAG_TEX = 2,  	SB_FRAG_MIPADDR = 3,  	SB_VERT_SHADER = 4, +	SB_GEOM_SHADER = 5,  	SB_FRAG_SHADER = 6,  }; @@ -382,12 +378,19 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel va  {  	return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;  } +#define CP_DRAW_INDX_OFFSET_0_TESSELLATE			0x00000100  #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK			0x00000c00  #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT			10  static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)  {  	return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;  } +#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK			0x01f00000 +#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT			20 +static inline uint32_t CP_DRAW_INDX_OFFSET_0_TESS_MODE(uint32_t val) +{ +	return ((val) << CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT) & CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK; +}  #define REG_CP_DRAW_INDX_OFFSET_1				0x00000001  #define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK		0xffffffff diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 28d1f95a90cc..1f2561e2ff71 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -23,12 +23,47 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)  		msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];  } +static int dsi_get_phy(struct msm_dsi *msm_dsi) +{ +	struct platform_device *pdev = msm_dsi->pdev; +	struct platform_device *phy_pdev; +	struct device_node *phy_node; + +	phy_node = of_parse_phandle(pdev->dev.of_node, "qcom,dsi-phy", 0); +	if (!phy_node) { +		dev_err(&pdev->dev, "cannot find phy device\n"); +		return -ENXIO; +	} + +	phy_pdev = of_find_device_by_node(phy_node); +	if (phy_pdev) +		msm_dsi->phy = platform_get_drvdata(phy_pdev); + +	of_node_put(phy_node); + +	if (!phy_pdev || !msm_dsi->phy) { +		dev_err(&pdev->dev, "%s: phy driver is not ready\n", __func__); +		return -EPROBE_DEFER; +	} + +	msm_dsi->phy_dev = get_device(&phy_pdev->dev); + +	return 0; +} +  static void dsi_destroy(struct msm_dsi *msm_dsi)  {  	if (!msm_dsi)  		return;  	msm_dsi_manager_unregister(msm_dsi); + +	if (msm_dsi->phy_dev) { +		put_device(msm_dsi->phy_dev); +		msm_dsi->phy = NULL; +		msm_dsi->phy_dev = NULL; +	} +  	if (msm_dsi->host) {  		msm_dsi_host_destroy(msm_dsi->host);  		msm_dsi->host = NULL; @@ -43,7 +78,6 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)  	int ret;  	if (!pdev) { -		dev_err(&pdev->dev, "no dsi device\n");  		ret = -ENXIO;  		goto fail;  	} @@ -63,6 +97,11 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)  	if (ret)  		goto fail; +	/* GET dsi PHY */ +	ret = dsi_get_phy(msm_dsi); +	if (ret) +		goto fail; +  	/* Register to dsi manager */  	ret = msm_dsi_manager_register(msm_dsi);  	if (ret) @@ -142,12 +181,14 @@ static struct platform_driver dsi_driver = {  void __init msm_dsi_register(void)  {  	DBG(""); +	msm_dsi_phy_driver_register();  	platform_driver_register(&dsi_driver);  }  void __exit msm_dsi_unregister(void)  {  	DBG(""); +	msm_dsi_phy_driver_unregister();  	platform_driver_unregister(&dsi_driver);  } @@ -177,6 +218,11 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,  		goto fail;  	} +	for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { +		encoders[i]->bridge = msm_dsi->bridge; +		msm_dsi->encoders[i] = encoders[i]; +	} +  	msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);  	if (IS_ERR(msm_dsi->connector)) {  		ret = PTR_ERR(msm_dsi->connector); @@ -185,11 +231,6 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,  		goto fail;  	} -	for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { -		encoders[i]->bridge = msm_dsi->bridge; -		msm_dsi->encoders[i] = encoders[i]; -	} -  	priv->bridges[priv->num_bridges++]       = msm_dsi->bridge;  	priv->connectors[priv->num_connectors++] = msm_dsi->connector; diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 10f54d4e379a..92d697de4858 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -14,6 +14,7 @@  #ifndef __DSI_CONNECTOR_H__  #define __DSI_CONNECTOR_H__ +#include <linux/of_platform.h>  #include <linux/platform_device.h>  #include "drm_crtc.h" @@ -38,6 +39,28 @@  #define DSI_ENCODER_MASTER	DSI_1  #define DSI_ENCODER_SLAVE	DSI_0 +enum msm_dsi_phy_type { +	MSM_DSI_PHY_28NM_HPM, +	MSM_DSI_PHY_28NM_LP, +	MSM_DSI_PHY_MAX +}; + +#define DSI_DEV_REGULATOR_MAX	8 + +/* Regulators for DSI devices */ +struct dsi_reg_entry { +	char name[32]; +	int min_voltage; +	int max_voltage; +	int enable_load; +	int disable_load; +}; + +struct dsi_reg_config { +	int num; +	struct dsi_reg_entry regs[DSI_DEV_REGULATOR_MAX]; +}; +  struct msm_dsi {  	struct drm_device *dev;  	struct platform_device *pdev; @@ -49,6 +72,8 @@ struct msm_dsi {  	struct msm_dsi_phy *phy;  	struct drm_panel *panel;  	unsigned long panel_flags; + +	struct device *phy_dev;  	bool phy_enabled;  	/* the encoders we are hooked to (outside of dsi block) */ @@ -73,6 +98,29 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);  /* msm dsi */  struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); +/* dsi pll */ +struct msm_dsi_pll; +#ifdef CONFIG_DRM_MSM_DSI_PLL +struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, +			enum msm_dsi_phy_type type, int dsi_id); +void msm_dsi_pll_destroy(struct msm_dsi_pll *pll); +int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, +	struct clk **byte_clk_provider, struct clk **pixel_clk_provider); +#else +static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, +			 enum msm_dsi_phy_type type, int id) { +	return ERR_PTR(-ENODEV); +} +static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll) +{ +} +static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, +	struct clk **byte_clk_provider, struct clk **pixel_clk_provider) +{ +	return -ENODEV; +} +#endif +  /* dsi host */  int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host,  					const struct mipi_dsi_msg *msg); @@ -94,6 +142,8 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,  					unsigned long *panel_flags);  int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);  void msm_dsi_host_unregister(struct mipi_dsi_host *host); +int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, +			struct msm_dsi_pll *src_pll);  void msm_dsi_host_destroy(struct mipi_dsi_host *host);  int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,  					struct drm_device *dev); @@ -101,17 +151,14 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);  /* dsi phy */  struct msm_dsi_phy; -enum msm_dsi_phy_type { -	MSM_DSI_PHY_UNKNOWN, -	MSM_DSI_PHY_28NM, -	MSM_DSI_PHY_MAX -}; -struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, -			enum msm_dsi_phy_type type, int id); +void msm_dsi_phy_driver_register(void); +void msm_dsi_phy_driver_unregister(void);  int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,  	const unsigned long bit_rate, const unsigned long esc_rate);  int msm_dsi_phy_disable(struct msm_dsi_phy *phy);  void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,  					u32 *clk_pre, u32 *clk_post); +struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); +  #endif /* __DSI_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index 1dcfae265e98..9791ea04bcbc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -8,8 +8,17 @@ http://github.com/freedreno/envytools/  git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are: -- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml             (  18681 bytes, from 2015-03-04 23:08:31) -- /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-01-28 21:43:22) +- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49) +- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) @@ -394,6 +403,9 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val)  #define DSI_EOT_PACKET_CTRL_TX_EOT_APPEND			0x00000001  #define DSI_EOT_PACKET_CTRL_RX_EOT_IGNORE			0x00000010 +#define REG_DSI_LANE_CTRL					0x000000a8 +#define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST			0x10000000 +  #define REG_DSI_LANE_SWAP_CTRL					0x000000ac  #define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__MASK			0x00000007  #define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__SHIFT			0 @@ -835,5 +847,152 @@ static inline uint32_t DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)  #define REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG			0x00000018 +#define REG_DSI_28nm_PHY_PLL_REFCLK_CFG				0x00000000 +#define DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR			0x00000001 + +#define REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004 + +#define REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008 + +#define REG_DSI_28nm_PHY_PLL_VCOLPF_CFG				0x0000000c + +#define REG_DSI_28nm_PHY_PLL_VREG_CFG				0x00000010 +#define DSI_28nm_PHY_PLL_VREG_CFG_POSTDIV1_BYPASS_B		0x00000002 + +#define REG_DSI_28nm_PHY_PLL_PWRGEN_CFG				0x00000014 + +#define REG_DSI_28nm_PHY_PLL_DMUX_CFG				0x00000018 + +#define REG_DSI_28nm_PHY_PLL_AMUX_CFG				0x0000001c + +#define REG_DSI_28nm_PHY_PLL_GLB_CFG				0x00000020 +#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001 +#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002 +#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004 +#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008 + +#define REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024 + +#define REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028 + +#define REG_DSI_28nm_PHY_PLL_LPFR_CFG				0x0000002c + +#define REG_DSI_28nm_PHY_PLL_LPFC1_CFG				0x00000030 + +#define REG_DSI_28nm_PHY_PLL_LPFC2_CFG				0x00000034 + +#define REG_DSI_28nm_PHY_PLL_SDM_CFG0				0x00000038 +#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK			0x0000003f +#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT		0 +static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(uint32_t val) +{ +	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK; +} +#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP				0x00000040 + +#define REG_DSI_28nm_PHY_PLL_SDM_CFG1				0x0000003c +#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK		0x0000003f +#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT		0 +static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(uint32_t val) +{ +	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK; +} +#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK		0x00000040 +#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT		6 +static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN(uint32_t val) +{ +	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK; +} + +#define REG_DSI_28nm_PHY_PLL_SDM_CFG2				0x00000040 +#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK		0x000000ff +#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT		0 +static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(uint32_t val) +{ +	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK; +} + +#define REG_DSI_28nm_PHY_PLL_SDM_CFG3				0x00000044 +#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK		0x000000ff +#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT		0 +static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(uint32_t val) +{ +	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK; +} + +#define REG_DSI_28nm_PHY_PLL_SDM_CFG4				0x00000048 + +#define REG_DSI_28nm_PHY_PLL_SSC_CFG0				0x0000004c + +#define REG_DSI_28nm_PHY_PLL_SSC_CFG1				0x00000050 + +#define REG_DSI_28nm_PHY_PLL_SSC_CFG2				0x00000054 + +#define REG_DSI_28nm_PHY_PLL_SSC_CFG3				0x00000058 + +#define REG_DSI_28nm_PHY_PLL_LKDET_CFG0				0x0000005c + +#define REG_DSI_28nm_PHY_PLL_LKDET_CFG1				0x00000060 + +#define REG_DSI_28nm_PHY_PLL_LKDET_CFG2				0x00000064 + +#define REG_DSI_28nm_PHY_PLL_TEST_CFG				0x00000068 +#define DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG0				0x0000006c + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG1				0x00000070 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG2				0x00000074 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG3				0x00000078 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG4				0x0000007c + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG5				0x00000080 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG6				0x00000084 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG7				0x00000088 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG8				0x0000008c + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG9				0x00000090 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG10				0x00000094 + +#define REG_DSI_28nm_PHY_PLL_CAL_CFG11				0x00000098 + +#define REG_DSI_28nm_PHY_PLL_EFUSE_CFG				0x0000009c + +#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0 + +#define REG_DSI_28nm_PHY_PLL_CTRL_42				0x000000a4 + +#define REG_DSI_28nm_PHY_PLL_CTRL_43				0x000000a8 + +#define REG_DSI_28nm_PHY_PLL_CTRL_44				0x000000ac + +#define REG_DSI_28nm_PHY_PLL_CTRL_45				0x000000b0 + +#define REG_DSI_28nm_PHY_PLL_CTRL_46				0x000000b4 + +#define REG_DSI_28nm_PHY_PLL_CTRL_47				0x000000b8 + +#define REG_DSI_28nm_PHY_PLL_CTRL_48				0x000000bc + +#define REG_DSI_28nm_PHY_PLL_STATUS				0x000000c0 +#define DSI_28nm_PHY_PLL_STATUS_PLL_RDY				0x00000001 + +#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS0				0x000000c4 + +#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS1				0x000000c8 + +#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS2				0x000000cc + +#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS3				0x000000d0 + +#define REG_DSI_28nm_PHY_PLL_CTRL_54				0x000000d4 +  #endif /* DSI_XML */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 956b22492c9a..de0400923303 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -15,6 +15,7 @@  #include <linux/delay.h>  #include <linux/err.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/of_device.h>  #include <linux/of_gpio.h> @@ -36,35 +37,19 @@  #define DSI_6G_REG_SHIFT	4 -#define DSI_REGULATOR_MAX	8 -struct dsi_reg_entry { -	char name[32]; -	int min_voltage; -	int max_voltage; -	int enable_load; -	int disable_load; -}; - -struct dsi_reg_config { -	int num; -	struct dsi_reg_entry regs[DSI_REGULATOR_MAX]; -}; -  struct dsi_config {  	u32 major;  	u32 minor;  	u32 io_offset; -	enum msm_dsi_phy_type phy_type;  	struct dsi_reg_config reg_cfg;  };  static const struct dsi_config dsi_cfgs[] = { -	{MSM_DSI_VER_MAJOR_V2, 0, 0, MSM_DSI_PHY_UNKNOWN}, +	{MSM_DSI_VER_MAJOR_V2, 0, 0, {0,} },  	{ /* 8974 v1 */  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_0,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -79,7 +64,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -94,7 +78,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_1_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -109,7 +92,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_2,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -124,7 +106,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_3_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -197,7 +178,7 @@ struct msm_dsi_host {  	int id;  	void __iomem *ctrl_base; -	struct regulator_bulk_data supplies[DSI_REGULATOR_MAX]; +	struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];  	struct clk *mdp_core_clk;  	struct clk *ahb_clk;  	struct clk *axi_clk; @@ -205,6 +186,9 @@ struct msm_dsi_host {  	struct clk *byte_clk;  	struct clk *esc_clk;  	struct clk *pixel_clk; +	struct clk *byte_clk_src; +	struct clk *pixel_clk_src; +  	u32 byte_clk_rate;  	struct gpio_desc *disp_en_gpio; @@ -273,7 +257,7 @@ static const struct dsi_config *dsi_get_config(struct msm_dsi_host *msm_host)  	u32 major = 0, minor = 0;  	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc"); -	if (IS_ERR_OR_NULL(gdsc_reg)) { +	if (IS_ERR(gdsc_reg)) {  		pr_err("%s: cannot get gdsc\n", __func__);  		goto fail;  	} @@ -463,6 +447,22 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)  		goto exit;  	} +	msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src"); +	if (IS_ERR(msm_host->byte_clk_src)) { +		ret = PTR_ERR(msm_host->byte_clk_src); +		pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret); +		msm_host->byte_clk_src = NULL; +		goto exit; +	} + +	msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src"); +	if (IS_ERR(msm_host->pixel_clk_src)) { +		ret = PTR_ERR(msm_host->pixel_clk_src); +		pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret); +		msm_host->pixel_clk_src = NULL; +		goto exit; +	} +  exit:  	return ret;  } @@ -787,6 +787,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,  		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,  			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));  	} + +	if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) +		dsi_write(msm_host, REG_DSI_LANE_CTRL, +			DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST); +  	data |= DSI_CTRL_ENABLE;  	dsi_write(msm_host, REG_DSI_CTRL, data); @@ -1023,7 +1028,7 @@ static int dsi_short_read1_resp(u8 *buf, const struct mipi_dsi_msg *msg)  		*data = buf[1]; /* strip out dcs type */  		return 1;  	} else { -		pr_err("%s: read data does not match with rx_buf len %d\n", +		pr_err("%s: read data does not match with rx_buf len %zu\n",  			__func__, msg->rx_len);  		return -EINVAL;  	} @@ -1040,7 +1045,7 @@ static int dsi_short_read2_resp(u8 *buf, const struct mipi_dsi_msg *msg)  		data[1] = buf[2];  		return 2;  	} else { -		pr_err("%s: read data does not match with rx_buf len %d\n", +		pr_err("%s: read data does not match with rx_buf len %zu\n",  			__func__, msg->rx_len);  		return -EINVAL;  	} @@ -1093,7 +1098,6 @@ static int dsi_cmd_dma_rx(struct msm_dsi_host *msm_host,  {  	u32 *lp, *temp, data;  	int i, j = 0, cnt; -	bool ack_error = false;  	u32 read_cnt;  	u8 reg[16];  	int repeated_bytes = 0; @@ -1105,15 +1109,10 @@ static int dsi_cmd_dma_rx(struct msm_dsi_host *msm_host,  	if (cnt > 4)  		cnt = 4; /* 4 x 32 bits registers only */ -	/* Calculate real read data count */ -	read_cnt = dsi_read(msm_host, 0x1d4) >> 16; - -	ack_error = (rx_byte == 4) ? -		(read_cnt == 8) : /* short pkt + 4-byte error pkt */ -		(read_cnt == (pkt_size + 6 + 4)); /* long pkt+4-byte error pkt*/ - -	if (ack_error) -		read_cnt -= 4; /* Remove 4 byte error pkt */ +	if (rx_byte == 4) +		read_cnt = 4; +	else +		read_cnt = pkt_size + 6;  	/*  	 * In case of multiple reads from the panel, after the first read, there @@ -1215,7 +1214,7 @@ static void dsi_err_worker(struct work_struct *work)  		container_of(work, struct msm_dsi_host, err_work);  	u32 status = msm_host->err_work_state; -	pr_err("%s: status=%x\n", __func__, status); +	pr_err_ratelimited("%s: status=%x\n", __func__, status);  	if (status & DSI_ERR_STATE_MDP_FIFO_UNDERFLOW)  		dsi_sw_reset_restore(msm_host); @@ -1351,36 +1350,19 @@ static irqreturn_t dsi_host_irq(int irq, void *ptr)  static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,  			struct device *panel_device)  { -	int ret; - -	msm_host->disp_en_gpio = devm_gpiod_get(panel_device, -						"disp-enable"); +	msm_host->disp_en_gpio = devm_gpiod_get_optional(panel_device, +							 "disp-enable", +							 GPIOD_OUT_LOW);  	if (IS_ERR(msm_host->disp_en_gpio)) {  		DBG("cannot get disp-enable-gpios %ld",  				PTR_ERR(msm_host->disp_en_gpio)); -		msm_host->disp_en_gpio = NULL; -	} -	if (msm_host->disp_en_gpio) { -		ret = gpiod_direction_output(msm_host->disp_en_gpio, 0); -		if (ret) { -			pr_err("cannot set dir to disp-en-gpios %d\n", ret); -			return ret; -		} +		return PTR_ERR(msm_host->disp_en_gpio);  	} -	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te"); +	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);  	if (IS_ERR(msm_host->te_gpio)) {  		DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio)); -		msm_host->te_gpio = NULL; -	} - -	if (msm_host->te_gpio) { -		ret = gpiod_direction_input(msm_host->te_gpio); -		if (ret) { -			pr_err("%s: cannot set dir to disp-te-gpios, %d\n", -				__func__, ret); -			return ret; -		} +		return PTR_ERR(msm_host->te_gpio);  	}  	return 0; @@ -1514,13 +1496,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)  	msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);  	INIT_WORK(&msm_host->err_work, dsi_err_worker); -	msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type, -					msm_host->id); -	if (!msm_dsi->phy) { -		ret = -EINVAL; -		pr_err("%s: phy init failed\n", __func__); -		goto fail; -	}  	msm_dsi->host = &msm_host->base;  	msm_dsi->id = msm_host->id; @@ -1797,6 +1772,7 @@ int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,  	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:  		pr_err("%s: rx ACK_ERR_PACLAGE\n", __func__);  		ret = 0; +		break;  	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:  	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:  		ret = dsi_short_read1_resp(buf, msg); @@ -1829,6 +1805,39 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len)  	wmb();  } +int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, +	struct msm_dsi_pll *src_pll) +{ +	struct msm_dsi_host *msm_host = to_msm_dsi_host(host); +	struct clk *byte_clk_provider, *pixel_clk_provider; +	int ret; + +	ret = msm_dsi_pll_get_clk_provider(src_pll, +				&byte_clk_provider, &pixel_clk_provider); +	if (ret) { +		pr_info("%s: can't get provider from pll, don't set parent\n", +			__func__); +		return 0; +	} + +	ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider); +	if (ret) { +		pr_err("%s: can't set parent to byte_clk_src. ret=%d\n", +			__func__, ret); +		goto exit; +	} + +	ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider); +	if (ret) { +		pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n", +			__func__, ret); +		goto exit; +	} + +exit: +	return ret; +} +  int msm_dsi_host_enable(struct mipi_dsi_host *host)  {  	struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index ee3ebcaa33f5..87ac6612b6f8 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -60,6 +60,53 @@ static int dsi_mgr_parse_dual_panel(struct device_node *np, int id)  	return 0;  } +static int dsi_mgr_host_register(int id) +{ +	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); +	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); +	struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); +	struct msm_dsi_pll *src_pll; +	int ret; + +	if (!IS_DUAL_PANEL()) { +		ret = msm_dsi_host_register(msm_dsi->host, true); +		if (ret) +			return ret; + +		src_pll = msm_dsi_phy_get_pll(msm_dsi->phy); +		ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); +	} else if (!other_dsi) { +		ret = 0; +	} else { +		struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ? +					msm_dsi : other_dsi; +		struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ? +					other_dsi : msm_dsi; +		/* Register slave host first, so that slave DSI device +		 * has a chance to probe, and do not block the master +		 * DSI device's probe. +		 * Also, do not check defer for the slave host, +		 * because only master DSI device adds the panel to global +		 * panel list. The panel's device is the master DSI device. +		 */ +		ret = msm_dsi_host_register(sdsi->host, false); +		if (ret) +			return ret; +		ret = msm_dsi_host_register(mdsi->host, true); +		if (ret) +			return ret; + +		/* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */ +		src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy); +		ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); +		if (ret) +			return ret; +		ret = msm_dsi_host_set_src_pll(other_dsi->host, src_pll); +	} + +	return ret; +} +  struct dsi_connector {  	struct drm_connector base;  	int id; @@ -462,7 +509,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);  	struct drm_connector *connector = NULL;  	struct dsi_connector *dsi_connector; -	int ret; +	int ret, i;  	dsi_connector = devm_kzalloc(msm_dsi->dev->dev,  				sizeof(*dsi_connector), GFP_KERNEL); @@ -495,6 +542,10 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)  	if (ret)  		goto fail; +	for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) +		drm_mode_connector_attach_encoder(connector, +						msm_dsi->encoders[i]); +  	return connector;  fail: @@ -648,7 +699,6 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)  {  	struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;  	int id = msm_dsi->id; -	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);  	int ret;  	if (id > DSI_MAX) { @@ -666,31 +716,20 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)  	ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id);  	if (ret) {  		pr_err("%s: failed to parse dual panel info\n", __func__); -		return ret; +		goto fail;  	} -	if (!IS_DUAL_PANEL()) { -		ret = msm_dsi_host_register(msm_dsi->host, true); -	} else if (!other_dsi) { -		return 0; -	} else { -		struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ? -					msm_dsi : other_dsi; -		struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ? -					other_dsi : msm_dsi; -		/* Register slave host first, so that slave DSI device -		 * has a chance to probe, and do not block the master -		 * DSI device's probe. -		 * Also, do not check defer for the slave host, -		 * because only master DSI device adds the panel to global -		 * panel list. The panel's device is the master DSI device. -		 */ -		ret = msm_dsi_host_register(sdsi->host, false); -		if (ret) -			return ret; -		ret = msm_dsi_host_register(mdsi->host, true); +	ret = dsi_mgr_host_register(id); +	if (ret) { +		pr_err("%s: failed to register mipi dsi host for DSI %d\n", +			__func__, id); +		goto fail;  	} +	return 0; + +fail: +	msm_dsim->dsi[id] = NULL;  	return ret;  } diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c index f0cea8927388..2d3b33ce1cc5 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c @@ -11,12 +11,27 @@   * GNU General Public License for more details.   */ +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +  #include "dsi.h"  #include "dsi.xml.h"  #define dsi_phy_read(offset) msm_readl((offset))  #define dsi_phy_write(offset, data) msm_writel((data), (offset)) +struct dsi_phy_ops { +	int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel, +		const unsigned long bit_rate, const unsigned long esc_rate); +	int (*disable)(struct msm_dsi_phy *phy); +}; + +struct dsi_phy_cfg { +	enum msm_dsi_phy_type type; +	struct dsi_reg_config reg_cfg; +	struct dsi_phy_ops ops; +}; +  struct dsi_dphy_timing {  	u32 clk_pre;  	u32 clk_post; @@ -34,15 +49,106 @@ struct dsi_dphy_timing {  };  struct msm_dsi_phy { +	struct platform_device *pdev;  	void __iomem *base;  	void __iomem *reg_base;  	int id; + +	struct clk *ahb_clk; +	struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX]; +  	struct dsi_dphy_timing timing; -	int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel, -		const unsigned long bit_rate, const unsigned long esc_rate); -	int (*disable)(struct msm_dsi_phy *phy); +	const struct dsi_phy_cfg *cfg; + +	struct msm_dsi_pll *pll;  }; +static int dsi_phy_regulator_init(struct msm_dsi_phy *phy) +{ +	struct regulator_bulk_data *s = phy->supplies; +	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; +	struct device *dev = &phy->pdev->dev; +	int num = phy->cfg->reg_cfg.num; +	int i, ret; + +	for (i = 0; i < num; i++) +		s[i].supply = regs[i].name; + +	ret = devm_regulator_bulk_get(&phy->pdev->dev, num, s); +	if (ret < 0) { +		dev_err(dev, "%s: failed to init regulator, ret=%d\n", +						__func__, ret); +		return ret; +	} + +	for (i = 0; i < num; i++) { +		if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) { +			ret = regulator_set_voltage(s[i].consumer, +				regs[i].min_voltage, regs[i].max_voltage); +			if (ret < 0) { +				dev_err(dev, +					"regulator %d set voltage failed, %d\n", +					i, ret); +				return ret; +			} +		} +	} + +	return 0; +} + +static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy) +{ +	struct regulator_bulk_data *s = phy->supplies; +	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; +	int num = phy->cfg->reg_cfg.num; +	int i; + +	DBG(""); +	for (i = num - 1; i >= 0; i--) +		if (regs[i].disable_load >= 0) +			regulator_set_load(s[i].consumer, +						regs[i].disable_load); + +	regulator_bulk_disable(num, s); +} + +static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy) +{ +	struct regulator_bulk_data *s = phy->supplies; +	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; +	struct device *dev = &phy->pdev->dev; +	int num = phy->cfg->reg_cfg.num; +	int ret, i; + +	DBG(""); +	for (i = 0; i < num; i++) { +		if (regs[i].enable_load >= 0) { +			ret = regulator_set_load(s[i].consumer, +							regs[i].enable_load); +			if (ret < 0) { +				dev_err(dev, +					"regulator %d set op mode failed, %d\n", +					i, ret); +				goto fail; +			} +		} +	} + +	ret = regulator_bulk_enable(num, s); +	if (ret < 0) { +		dev_err(dev, "regulator enable failed, %d\n", ret); +		goto fail; +	} + +	return 0; + +fail: +	for (i--; i >= 0; i--) +		regulator_set_load(s[i].consumer, regs[i].disable_load); +	return ret; +} +  #define S_DIV_ROUND_UP(n, d)	\  	(((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d))) @@ -284,59 +390,200 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)  	return 0;  } -#define dsi_phy_func_init(name)	\ -	do {	\ -		phy->enable = dsi_##name##_phy_enable;	\ -		phy->disable = dsi_##name##_phy_disable;	\ -	} while (0) +static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) +{ +	int ret; + +	pm_runtime_get_sync(&phy->pdev->dev); -struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, -			enum msm_dsi_phy_type type, int id) +	ret = clk_prepare_enable(phy->ahb_clk); +	if (ret) { +		pr_err("%s: can't enable ahb clk, %d\n", __func__, ret); +		pm_runtime_put_sync(&phy->pdev->dev); +	} + +	return ret; +} + +static void dsi_phy_disable_resource(struct msm_dsi_phy *phy) +{ +	clk_disable_unprepare(phy->ahb_clk); +	pm_runtime_put_sync(&phy->pdev->dev); +} + +static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = { +	[MSM_DSI_PHY_28NM_HPM] = { +		.type = MSM_DSI_PHY_28NM_HPM, +		.reg_cfg = { +			.num = 1, +			.regs = { +				{"vddio", 1800000, 1800000, 100000, 100}, +			}, +		}, +		.ops = { +			.enable = dsi_28nm_phy_enable, +			.disable = dsi_28nm_phy_disable, +		} +	}, +	[MSM_DSI_PHY_28NM_LP] = { +		.type = MSM_DSI_PHY_28NM_LP, +		.reg_cfg = { +			.num = 1, +			.regs = { +				{"vddio", 1800000, 1800000, 100000, 100}, +			}, +		}, +		.ops = { +			.enable = dsi_28nm_phy_enable, +			.disable = dsi_28nm_phy_disable, +		} +	}, +}; + +static const struct of_device_id dsi_phy_dt_match[] = { +	{ .compatible = "qcom,dsi-phy-28nm-hpm", +	  .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],}, +	{ .compatible = "qcom,dsi-phy-28nm-lp", +	  .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],}, +	{} +}; + +static int dsi_phy_driver_probe(struct platform_device *pdev)  {  	struct msm_dsi_phy *phy; +	const struct of_device_id *match; +	int ret;  	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);  	if (!phy) -		return NULL; +		return -ENOMEM; + +	match = of_match_node(dsi_phy_dt_match, pdev->dev.of_node); +	if (!match) +		return -ENODEV; + +	phy->cfg = match->data; +	phy->pdev = pdev; + +	ret = of_property_read_u32(pdev->dev.of_node, +				"qcom,dsi-phy-index", &phy->id); +	if (ret) { +		dev_err(&pdev->dev, +			"%s: PHY index not specified, ret=%d\n", +			__func__, ret); +		goto fail; +	}  	phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY"); -	if (IS_ERR_OR_NULL(phy->base)) { -		pr_err("%s: failed to map phy base\n", __func__); -		return NULL; +	if (IS_ERR(phy->base)) { +		dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__); +		ret = -ENOMEM; +		goto fail;  	}  	phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator", "DSI_PHY_REG"); -	if (IS_ERR_OR_NULL(phy->reg_base)) { -		pr_err("%s: failed to map phy regulator base\n", __func__); -		return NULL; +	if (IS_ERR(phy->reg_base)) { +		dev_err(&pdev->dev, +			"%s: failed to map phy regulator base\n", __func__); +		ret = -ENOMEM; +		goto fail;  	} -	switch (type) { -	case MSM_DSI_PHY_28NM: -		dsi_phy_func_init(28nm); -		break; -	default: -		pr_err("%s: unsupported type, %d\n", __func__, type); -		return NULL; +	ret = dsi_phy_regulator_init(phy); +	if (ret) { +		dev_err(&pdev->dev, "%s: failed to init regulator\n", __func__); +		goto fail; +	} + +	phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk"); +	if (IS_ERR(phy->ahb_clk)) { +		pr_err("%s: Unable to get ahb clk\n", __func__); +		ret = PTR_ERR(phy->ahb_clk); +		goto fail;  	} -	phy->id = id; +	/* PLL init will call into clk_register which requires +	 * register access, so we need to enable power and ahb clock. +	 */ +	ret = dsi_phy_enable_resource(phy); +	if (ret) +		goto fail; + +	phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id); +	if (!phy->pll) +		dev_info(&pdev->dev, +			"%s: pll init failed, need separate pll clk driver\n", +			__func__); + +	dsi_phy_disable_resource(phy); + +	platform_set_drvdata(pdev, phy); + +	return 0; -	return phy; +fail: +	return ret; +} + +static int dsi_phy_driver_remove(struct platform_device *pdev) +{ +	struct msm_dsi_phy *phy = platform_get_drvdata(pdev); + +	if (phy && phy->pll) { +		msm_dsi_pll_destroy(phy->pll); +		phy->pll = NULL; +	} + +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +static struct platform_driver dsi_phy_platform_driver = { +	.probe      = dsi_phy_driver_probe, +	.remove     = dsi_phy_driver_remove, +	.driver     = { +		.name   = "msm_dsi_phy", +		.of_match_table = dsi_phy_dt_match, +	}, +}; + +void __init msm_dsi_phy_driver_register(void) +{ +	platform_driver_register(&dsi_phy_platform_driver); +} + +void __exit msm_dsi_phy_driver_unregister(void) +{ +	platform_driver_unregister(&dsi_phy_platform_driver);  }  int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,  	const unsigned long bit_rate, const unsigned long esc_rate)  { -	if (!phy || !phy->enable) +	int ret; + +	if (!phy || !phy->cfg->ops.enable)  		return -EINVAL; -	return phy->enable(phy, is_dual_panel, bit_rate, esc_rate); + +	ret = dsi_phy_regulator_enable(phy); +	if (ret) { +		dev_err(&phy->pdev->dev, "%s: regulator enable failed, %d\n", +			__func__, ret); +		return ret; +	} + +	return phy->cfg->ops.enable(phy, is_dual_panel, bit_rate, esc_rate);  }  int msm_dsi_phy_disable(struct msm_dsi_phy *phy)  { -	if (!phy || !phy->disable) +	if (!phy || !phy->cfg->ops.disable)  		return -EINVAL; -	return phy->disable(phy); + +	phy->cfg->ops.disable(phy); +	dsi_phy_regulator_disable(phy); + +	return 0;  }  void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, @@ -350,3 +597,11 @@ void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,  		*clk_post = phy->timing.clk_post;  } +struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy) +{ +	if (!phy) +		return NULL; + +	return phy->pll; +} + diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h index 695f99d4bec2..728152f3ef48 100644 --- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h +++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h @@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013-2014 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c new file mode 100644 index 000000000000..509376fdd112 --- /dev/null +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include "dsi_pll.h" + +static int dsi_pll_enable(struct msm_dsi_pll *pll) +{ +	int i, ret = 0; + +	/* +	 * Certain PLLs do not allow VCO rate update when it is on. +	 * Keep track of their status to turn on/off after set rate success. +	 */ +	if (unlikely(pll->pll_on)) +		return 0; + +	/* Try all enable sequences until one succeeds */ +	for (i = 0; i < pll->en_seq_cnt; i++) { +		ret = pll->enable_seqs[i](pll); +		DBG("DSI PLL %s after sequence #%d", +			ret ? "unlocked" : "locked", i + 1); +		if (!ret) +			break; +	} + +	if (ret) { +		DRM_ERROR("DSI PLL failed to lock\n"); +		return ret; +	} + +	pll->pll_on = true; + +	return 0; +} + +static void dsi_pll_disable(struct msm_dsi_pll *pll) +{ +	if (unlikely(!pll->pll_on)) +		return; + +	pll->disable_seq(pll); + +	pll->pll_on = false; +} + +/* + * DSI PLL Helper functions + */ +long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw, +		unsigned long rate, unsigned long *parent_rate) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + +	if      (rate < pll->min_rate) +		return  pll->min_rate; +	else if (rate > pll->max_rate) +		return  pll->max_rate; +	else +		return rate; +} + +int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); +	int ret; + +	/* +	 * Certain PLLs need to update the same VCO rate and registers +	 * after resume in suspend/resume scenario. +	 */ +	if (pll->restore_state) { +		ret = pll->restore_state(pll); +		if (ret) +			goto error; +	} + +	ret = dsi_pll_enable(pll); + +error: +	return ret; +} + +void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + +	if (pll->save_state) +		pll->save_state(pll); + +	dsi_pll_disable(pll); +} + +void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev, +					struct clk **clks, u32 num_clks) +{ +	of_clk_del_provider(pdev->dev.of_node); + +	if (!num_clks || !clks) +		return; + +	do { +		clk_unregister(clks[--num_clks]); +		clks[num_clks] = NULL; +	} while (num_clks); +} + +/* + * DSI PLL API + */ +int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, +	struct clk **byte_clk_provider, struct clk **pixel_clk_provider) +{ +	if (pll->get_provider) +		return pll->get_provider(pll, +					byte_clk_provider, +					pixel_clk_provider); + +	return -EINVAL; +} + +void msm_dsi_pll_destroy(struct msm_dsi_pll *pll) +{ +	if (pll->destroy) +		pll->destroy(pll); +} + +struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, +			enum msm_dsi_phy_type type, int id) +{ +	struct device *dev = &pdev->dev; +	struct msm_dsi_pll *pll; + +	switch (type) { +	case MSM_DSI_PHY_28NM_HPM: +	case MSM_DSI_PHY_28NM_LP: +		pll = msm_dsi_pll_28nm_init(pdev, type, id); +		break; +	default: +		pll = ERR_PTR(-ENXIO); +		break; +	} + +	if (IS_ERR(pll)) { +		dev_err(dev, "%s: failed to init DSI PLL\n", __func__); +		return NULL; +	} + +	pll->type = type; + +	DBG("DSI:%d PLL registered", id); + +	return pll; +} + diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h new file mode 100644 index 000000000000..5a3bb241c039 --- /dev/null +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#ifndef __DSI_PLL_H__ +#define __DSI_PLL_H__ + +#include <linux/clk.h> +#include <linux/clk-provider.h> + +#include "dsi.h" + +#define NUM_DSI_CLOCKS_MAX	6 +#define MAX_DSI_PLL_EN_SEQS	10 + +struct msm_dsi_pll { +	enum msm_dsi_phy_type type; + +	struct clk_hw	clk_hw; +	bool		pll_on; + +	unsigned long	min_rate; +	unsigned long	max_rate; +	u32		en_seq_cnt; + +	int (*enable_seqs[MAX_DSI_PLL_EN_SEQS])(struct msm_dsi_pll *pll); +	void (*disable_seq)(struct msm_dsi_pll *pll); +	int (*get_provider)(struct msm_dsi_pll *pll, +			struct clk **byte_clk_provider, +			struct clk **pixel_clk_provider); +	void (*destroy)(struct msm_dsi_pll *pll); +	void (*save_state)(struct msm_dsi_pll *pll); +	int (*restore_state)(struct msm_dsi_pll *pll); +}; + +#define hw_clk_to_pll(x) container_of(x, struct msm_dsi_pll, clk_hw) + +static inline void pll_write(void __iomem *reg, u32 data) +{ +	msm_writel(data, reg); +} + +static inline u32 pll_read(const void __iomem *reg) +{ +	return msm_readl(reg); +} + +static inline void pll_write_udelay(void __iomem *reg, u32 data, u32 delay_us) +{ +	pll_write(reg, data); +	udelay(delay_us); +} + +static inline void pll_write_ndelay(void __iomem *reg, u32 data, u32 delay_ns) +{ +	pll_write((reg), data); +	ndelay(delay_ns); +} + +/* + * DSI PLL Helper functions + */ + +/* clock callbacks */ +long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw, +		unsigned long rate, unsigned long *parent_rate); +int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw); +void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw); +/* misc */ +void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev, +					struct clk **clks, u32 num_clks); + +/* + * Initialization for Each PLL Type + */ +struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev, +					enum msm_dsi_phy_type type, int id); + +#endif /* __DSI_PLL_H__ */ + diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c new file mode 100644 index 000000000000..eb8ac3097ff5 --- /dev/null +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> + +#include "dsi_pll.h" +#include "dsi.xml.h" + +/* + * DSI PLL 28nm - clock diagram (eg: DSI0): + * + *         dsi0analog_postdiv_clk + *                             |         dsi0indirect_path_div2_clk + *                             |          | + *                   +------+  |  +----+  |  |\   dsi0byte_mux + *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   | + *                |  +------+     +----+     | m|  |  +----+ + *                |                          | u|--o--| /4 |-- dsi0pllbyte + *                |                          | x|     +----+ + *                o--------------------------| / + *                |                          |/ + *                |          +------+ + *                o----------| DIV3 |------------------------- dsi0pll + *                           +------+ + */ + +#define POLL_MAX_READS			10 +#define POLL_TIMEOUT_US		50 + +#define NUM_PROVIDED_CLKS		2 + +#define VCO_REF_CLK_RATE		19200000 +#define VCO_MIN_RATE			350000000 +#define VCO_MAX_RATE			750000000 + +#define DSI_BYTE_PLL_CLK		0 +#define DSI_PIXEL_PLL_CLK		1 + +#define LPFR_LUT_SIZE			10 +struct lpfr_cfg { +	unsigned long vco_rate; +	u32 resistance; +}; + +/* Loop filter resistance: */ +static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = { +	{ 479500000,  8 }, +	{ 480000000, 11 }, +	{ 575500000,  8 }, +	{ 576000000, 12 }, +	{ 610500000,  8 }, +	{ 659500000,  9 }, +	{ 671500000, 10 }, +	{ 672000000, 14 }, +	{ 708500000, 10 }, +	{ 750000000, 11 }, +}; + +struct pll_28nm_cached_state { +	unsigned long vco_rate; +	u8 postdiv3; +	u8 postdiv1; +	u8 byte_mux; +}; + +struct dsi_pll_28nm { +	struct msm_dsi_pll base; + +	int id; +	struct platform_device *pdev; +	void __iomem *mmio; + +	int vco_delay; + +	/* private clocks: */ +	struct clk *clks[NUM_DSI_CLOCKS_MAX]; +	u32 num_clks; + +	/* clock-provider: */ +	struct clk *provided_clks[NUM_PROVIDED_CLKS]; +	struct clk_onecell_data clk_data; + +	struct pll_28nm_cached_state cached_state; +}; + +#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base) + +static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm, +				u32 nb_tries, u32 timeout_us) +{ +	bool pll_locked = false; +	u32 val; + +	while (nb_tries--) { +		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS); +		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY); + +		if (pll_locked) +			break; + +		udelay(timeout_us); +	} +	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* "); + +	return pll_locked; +} + +static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm) +{ +	void __iomem *base = pll_28nm->mmio; + +	/* +	 * Add HW recommended delays after toggling the software +	 * reset bit off and back on. +	 */ +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, +			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1); +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1); +} + +/* + * Clock Callbacks + */ +static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate, +		unsigned long parent_rate) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	struct device *dev = &pll_28nm->pdev->dev; +	void __iomem *base = pll_28nm->mmio; +	unsigned long div_fbx1000, gen_vco_clk; +	u32 refclk_cfg, frac_n_mode, frac_n_value; +	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3; +	u32 cal_cfg10, cal_cfg11; +	u32 rem; +	int i; + +	VERB("rate=%lu, parent's=%lu", rate, parent_rate); + +	/* Force postdiv2 to be div-4 */ +	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3); + +	/* Configure the Loop filter resistance */ +	for (i = 0; i < LPFR_LUT_SIZE; i++) +		if (rate <= lpfr_lut[i].vco_rate) +			break; +	if (i == LPFR_LUT_SIZE) { +		dev_err(dev, "unable to get loop filter resistance. vco=%lu\n", +				rate); +		return -EINVAL; +	} +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance); + +	/* Loop filter capacitance values : c1 and c2 */ +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70); +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15); + +	rem = rate % VCO_REF_CLK_RATE; +	if (rem) { +		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR; +		frac_n_mode = 1; +		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500); +		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500); +	} else { +		refclk_cfg = 0x0; +		frac_n_mode = 0; +		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000); +		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000); +	} + +	DBG("refclk_cfg = %d", refclk_cfg); + +	rem = div_fbx1000 % 1000; +	frac_n_value = (rem << 16) / 1000; + +	DBG("div_fb = %lu", div_fbx1000); +	DBG("frac_n_value = %d", frac_n_value); + +	DBG("Generated VCO Clock: %lu", gen_vco_clk); +	rem = 0; +	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1); +	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK; +	if (frac_n_mode) { +		sdm_cfg0 = 0x0; +		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0); +		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET( +				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1)); +		sdm_cfg3 = frac_n_value >> 8; +		sdm_cfg2 = frac_n_value & 0xff; +	} else { +		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP; +		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV( +				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1)); +		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0); +		sdm_cfg2 = 0; +		sdm_cfg3 = 0; +	} + +	DBG("sdm_cfg0=%d", sdm_cfg0); +	DBG("sdm_cfg1=%d", sdm_cfg1); +	DBG("sdm_cfg2=%d", sdm_cfg2); +	DBG("sdm_cfg3=%d", sdm_cfg3); + +	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000)); +	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000); +	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11); + +	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06); +	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d); + +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1); +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2, +		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2)); +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3, +		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3)); +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00); + +	/* Add hardware recommended delay for correct PLL configuration */ +	if (pll_28nm->vco_delay) +		udelay(pll_28nm->vco_delay); + +	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg); +	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00); +	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31); +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff); +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff); +	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20); + +	return 0; +} + +static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); + +	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS, +					POLL_TIMEOUT_US); +} + +static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw, +		unsigned long parent_rate) +{ +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw); +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	void __iomem *base = pll_28nm->mmio; +	u32 sdm0, doubler, sdm_byp_div; +	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3; +	u32 ref_clk = VCO_REF_CLK_RATE; +	unsigned long vco_rate; + +	VERB("parent_rate=%lu", parent_rate); + +	/* Check to see if the ref clk doubler is enabled */ +	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) & +			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR; +	ref_clk += (doubler * VCO_REF_CLK_RATE); + +	/* see if it is integer mode or sdm mode */ +	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0); +	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) { +		/* integer mode */ +		sdm_byp_div = FIELD( +				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0), +				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1; +		vco_rate = ref_clk * sdm_byp_div; +	} else { +		/* sdm mode */ +		sdm_dc_off = FIELD( +				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1), +				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET); +		DBG("sdm_dc_off = %d", sdm_dc_off); +		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2), +				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0); +		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3), +				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8); +		sdm_freq_seed = (sdm3 << 8) | sdm2; +		DBG("sdm_freq_seed = %d", sdm_freq_seed); + +		vco_rate = (ref_clk * (sdm_dc_off + 1)) + +			mult_frac(ref_clk, sdm_freq_seed, BIT(16)); +		DBG("vco rate = %lu", vco_rate); +	} + +	DBG("returning vco rate = %lu", vco_rate); + +	return vco_rate; +} + +static const struct clk_ops clk_ops_dsi_pll_28nm_vco = { +	.round_rate = msm_dsi_pll_helper_clk_round_rate, +	.set_rate = dsi_pll_28nm_clk_set_rate, +	.recalc_rate = dsi_pll_28nm_clk_recalc_rate, +	.prepare = msm_dsi_pll_helper_clk_prepare, +	.unprepare = msm_dsi_pll_helper_clk_unprepare, +	.is_enabled = dsi_pll_28nm_clk_is_enabled, +}; + +/* + * PLL Callbacks + */ +static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	struct device *dev = &pll_28nm->pdev->dev; +	void __iomem *base = pll_28nm->mmio; +	u32 max_reads = 5, timeout_us = 100; +	bool locked; +	u32 val; +	int i; + +	DBG("id=%d", pll_28nm->id); + +	pll_28nm_software_reset(pll_28nm); + +	/* +	 * PLL power up sequence. +	 * Add necessary delays recommended by hardware. +	 */ +	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B; +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1); + +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B; +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200); + +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500); + +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE; +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600); + +	for (i = 0; i < 2; i++) { +		/* DSI Uniphy lock detect setting */ +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, +				0x0c, 100); +		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d); + +		/* poll for PLL ready status */ +		locked = pll_28nm_poll_for_ready(pll_28nm, +						max_reads, timeout_us); +		if (locked) +			break; + +		pll_28nm_software_reset(pll_28nm); + +		/* +		 * PLL power up sequence. +		 * Add necessary delays recommended by hardware. +		 */ +		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1); + +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200); + +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250); + +		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200); + +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500); + +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE; +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600); +	} + +	if (unlikely(!locked)) +		dev_err(dev, "DSI PLL lock failed\n"); +	else +		DBG("DSI PLL Lock success"); + +	return locked ? 0 : -EINVAL; +} + +static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	struct device *dev = &pll_28nm->pdev->dev; +	void __iomem *base = pll_28nm->mmio; +	bool locked; +	u32 max_reads = 10, timeout_us = 50; +	u32 val; + +	DBG("id=%d", pll_28nm->id); + +	pll_28nm_software_reset(pll_28nm); + +	/* +	 * PLL power up sequence. +	 * Add necessary delays recommended by hardware. +	 */ +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500); + +	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B; +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500); + +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B; +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500); + +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B | +		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE; +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500); + +	/* DSI PLL toggle lock detect setting */ +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500); +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512); + +	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us); + +	if (unlikely(!locked)) +		dev_err(dev, "DSI PLL lock failed\n"); +	else +		DBG("DSI PLL lock success"); + +	return locked ? 0 : -EINVAL; +} + +static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); + +	DBG("id=%d", pll_28nm->id); +	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00); +} + +static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state; +	void __iomem *base = pll_28nm->mmio; + +	cached_state->postdiv3 = +			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG); +	cached_state->postdiv1 = +			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG); +	cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG); +	cached_state->vco_rate = __clk_get_rate(pll->clk_hw.clk); +} + +static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state; +	void __iomem *base = pll_28nm->mmio; +	int ret; + +	if ((cached_state->vco_rate != 0) && +		(cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) { +		ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw, +						cached_state->vco_rate, 0); +		if (ret) { +			dev_err(&pll_28nm->pdev->dev, +				"restore vco rate failed. ret=%d\n", ret); +			return ret; +		} + +		pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, +				cached_state->postdiv3); +		pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, +				cached_state->postdiv1); +		pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG, +				cached_state->byte_mux); + +		cached_state->vco_rate = 0; +	} + +	return 0; +} + +static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll, +				struct clk **byte_clk_provider, +				struct clk **pixel_clk_provider) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); + +	if (byte_clk_provider) +		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK]; +	if (pixel_clk_provider) +		*pixel_clk_provider = +				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK]; + +	return 0; +} + +static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll) +{ +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll); +	int i; + +	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev, +					pll_28nm->clks, pll_28nm->num_clks); + +	for (i = 0; i < NUM_PROVIDED_CLKS; i++) +		pll_28nm->provided_clks[i] = NULL; + +	pll_28nm->num_clks = 0; +	pll_28nm->clk_data.clks = NULL; +	pll_28nm->clk_data.clk_num = 0; +} + +static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm) +{ +	char clk_name[32], parent1[32], parent2[32], vco_name[32]; +	struct clk_init_data vco_init = { +		.parent_names = (const char *[]){ "xo" }, +		.num_parents = 1, +		.name = vco_name, +		.ops = &clk_ops_dsi_pll_28nm_vco, +	}; +	struct device *dev = &pll_28nm->pdev->dev; +	struct clk **clks = pll_28nm->clks; +	struct clk **provided_clks = pll_28nm->provided_clks; +	int num = 0; +	int ret; + +	DBG("%d", pll_28nm->id); + +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id); +	pll_28nm->base.clk_hw.init = &vco_init; +	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw); + +	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id); +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id); +	clks[num++] = clk_register_divider(dev, clk_name, +			parent1, CLK_SET_RATE_PARENT, +			pll_28nm->mmio + +			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, +			0, 4, 0, NULL); + +	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id); +	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id); +	clks[num++] = clk_register_fixed_factor(dev, clk_name, +			parent1, CLK_SET_RATE_PARENT, +			1, 2); + +	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id); +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id); +	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] = +			clk_register_divider(dev, clk_name, +				parent1, 0, pll_28nm->mmio + +				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, +				0, 8, 0, NULL); + +	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id); +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id); +	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id); +	clks[num++] = clk_register_mux(dev, clk_name, +			(const char *[]){ +				parent1, parent2 +			}, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio + +			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL); + +	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id); +	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id); +	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] = +			clk_register_fixed_factor(dev, clk_name, +				parent1, CLK_SET_RATE_PARENT, 1, 4); + +	pll_28nm->num_clks = num; + +	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS; +	pll_28nm->clk_data.clks = provided_clks; + +	ret = of_clk_add_provider(dev->of_node, +			of_clk_src_onecell_get, &pll_28nm->clk_data); +	if (ret) { +		dev_err(dev, "failed to register clk provider: %d\n", ret); +		return ret; +	} + +	return 0; +} + +struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev, +					enum msm_dsi_phy_type type, int id) +{ +	struct dsi_pll_28nm *pll_28nm; +	struct msm_dsi_pll *pll; +	int ret; + +	if (!pdev) +		return ERR_PTR(-ENODEV); + +	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL); +	if (!pll_28nm) +		return ERR_PTR(-ENOMEM); + +	pll_28nm->pdev = pdev; +	pll_28nm->id = id; + +	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL"); +	if (IS_ERR_OR_NULL(pll_28nm->mmio)) { +		dev_err(&pdev->dev, "%s: failed to map pll base\n", __func__); +		return ERR_PTR(-ENOMEM); +	} + +	pll = &pll_28nm->base; +	pll->min_rate = VCO_MIN_RATE; +	pll->max_rate = VCO_MAX_RATE; +	pll->get_provider = dsi_pll_28nm_get_provider; +	pll->destroy = dsi_pll_28nm_destroy; +	pll->disable_seq = dsi_pll_28nm_disable_seq; +	pll->save_state = dsi_pll_28nm_save_state; +	pll->restore_state = dsi_pll_28nm_restore_state; + +	if (type == MSM_DSI_PHY_28NM_HPM) { +		pll_28nm->vco_delay = 1; + +		pll->en_seq_cnt = 3; +		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm; +		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm; +		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm; +	} else if (type == MSM_DSI_PHY_28NM_LP) { +		pll_28nm->vco_delay = 1000; + +		pll->en_seq_cnt = 1; +		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp; +	} else { +		dev_err(&pdev->dev, "phy type (%d) is not 28nm\n", type); +		return ERR_PTR(-EINVAL); +	} + +	ret = pll_28nm_register(pll_28nm); +	if (ret) { +		dev_err(&pdev->dev, "failed to register PLL: %d\n", ret); +		return ERR_PTR(ret); +	} + +	return pll; +} + diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h index 50ff9851d73d..26f268e2dd3d 100644 --- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h +++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h @@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h index a29f1df15143..f9c71dceb5e2 100644 --- a/drivers/gpu/drm/msm/edp/edp.xml.h +++ b/drivers/gpu/drm/msm/edp/edp.xml.h @@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -288,5 +288,92 @@ static inline uint32_t REG_EDP_PHY_LN_PD_CTL(uint32_t i0) { return 0x00000404 +  #define REG_EDP_PHY_GLB_PHY_STATUS				0x00000598 +#define REG_EDP_28nm_PHY_PLL_REFCLK_CFG				0x00000000 + +#define REG_EDP_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004 + +#define REG_EDP_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008 + +#define REG_EDP_28nm_PHY_PLL_VCOLPF_CFG				0x0000000c + +#define REG_EDP_28nm_PHY_PLL_VREG_CFG				0x00000010 + +#define REG_EDP_28nm_PHY_PLL_PWRGEN_CFG				0x00000014 + +#define REG_EDP_28nm_PHY_PLL_DMUX_CFG				0x00000018 + +#define REG_EDP_28nm_PHY_PLL_AMUX_CFG				0x0000001c + +#define REG_EDP_28nm_PHY_PLL_GLB_CFG				0x00000020 +#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001 +#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002 +#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004 +#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008 + +#define REG_EDP_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024 + +#define REG_EDP_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028 + +#define REG_EDP_28nm_PHY_PLL_LPFR_CFG				0x0000002c + +#define REG_EDP_28nm_PHY_PLL_LPFC1_CFG				0x00000030 + +#define REG_EDP_28nm_PHY_PLL_LPFC2_CFG				0x00000034 + +#define REG_EDP_28nm_PHY_PLL_SDM_CFG0				0x00000038 + +#define REG_EDP_28nm_PHY_PLL_SDM_CFG1				0x0000003c + +#define REG_EDP_28nm_PHY_PLL_SDM_CFG2				0x00000040 + +#define REG_EDP_28nm_PHY_PLL_SDM_CFG3				0x00000044 + +#define REG_EDP_28nm_PHY_PLL_SDM_CFG4				0x00000048 + +#define REG_EDP_28nm_PHY_PLL_SSC_CFG0				0x0000004c + +#define REG_EDP_28nm_PHY_PLL_SSC_CFG1				0x00000050 + +#define REG_EDP_28nm_PHY_PLL_SSC_CFG2				0x00000054 + +#define REG_EDP_28nm_PHY_PLL_SSC_CFG3				0x00000058 + +#define REG_EDP_28nm_PHY_PLL_LKDET_CFG0				0x0000005c + +#define REG_EDP_28nm_PHY_PLL_LKDET_CFG1				0x00000060 + +#define REG_EDP_28nm_PHY_PLL_LKDET_CFG2				0x00000064 + +#define REG_EDP_28nm_PHY_PLL_TEST_CFG				0x00000068 +#define EDP_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG0				0x0000006c + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG1				0x00000070 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG2				0x00000074 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG3				0x00000078 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG4				0x0000007c + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG5				0x00000080 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG6				0x00000084 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG7				0x00000088 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG8				0x0000008c + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG9				0x00000090 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG10				0x00000094 + +#define REG_EDP_28nm_PHY_PLL_CAL_CFG11				0x00000098 + +#define REG_EDP_28nm_PHY_PLL_EFUSE_CFG				0x0000009c + +#define REG_EDP_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0 +  #endif /* EDP_XML */ diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c index 5f5a84f6074c..82789dd249ee 100644 --- a/drivers/gpu/drm/msm/edp/edp_aux.c +++ b/drivers/gpu/drm/msm/edp/edp_aux.c @@ -115,10 +115,12 @@ static int edp_msg_fifo_rx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)   * msm_edp_aux_ctrl() running concurrently in other threads, i.e.   * start transaction only when AUX channel is fully enabled.   */ -ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg) +static ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, +		struct drm_dp_aux_msg *msg)  {  	struct edp_aux *aux = to_edp_aux(drm_aux);  	ssize_t ret; +	unsigned long time_left;  	bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);  	bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); @@ -132,7 +134,7 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)  	/* msg sanity check */  	if ((native && (msg->size > AUX_CMD_NATIVE_MAX)) ||  		(msg->size > AUX_CMD_I2C_MAX)) { -		pr_err("%s: invalid msg: size(%d), request(%x)\n", +		pr_err("%s: invalid msg: size(%zu), request(%x)\n",  			__func__, msg->size, msg->request);  		return -EINVAL;  	} @@ -147,15 +149,17 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)  		goto unlock_exit;  	DBG("wait_for_completion"); -	ret = wait_for_completion_timeout(&aux->msg_comp, 300); -	if (ret <= 0) { +	time_left = wait_for_completion_timeout(&aux->msg_comp, +						msecs_to_jiffies(300)); +	if (!time_left) {  		/*  		 * Clear GO and reset AUX channel  		 * to cancel the current transaction.  		 */  		edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);  		msm_edp_aux_ctrl(aux, 1); -		pr_err("%s: aux timeout, %d\n", __func__, ret); +		pr_err("%s: aux timeout,\n", __func__); +		ret = -ETIMEDOUT;  		goto unlock_exit;  	}  	DBG("completion"); diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c b/drivers/gpu/drm/msm/edp/edp_connector.c index d8812e84da54..b4d1b469862a 100644 --- a/drivers/gpu/drm/msm/edp/edp_connector.c +++ b/drivers/gpu/drm/msm/edp/edp_connector.c @@ -151,6 +151,8 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)  	if (ret)  		goto fail; +	drm_mode_connector_attach_encoder(connector, edp->encoder); +  	return connector;  fail: diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index 0ec5abdba5c4..7991069dd492 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -1018,7 +1018,7 @@ static void edp_ctrl_off_worker(struct work_struct *work)  {  	struct edp_ctrl *ctrl = container_of(  				work, struct edp_ctrl, off_work); -	int ret; +	unsigned long time_left;  	mutex_lock(&ctrl->dev_mutex); @@ -1030,11 +1030,10 @@ static void edp_ctrl_off_worker(struct work_struct *work)  	reinit_completion(&ctrl->idle_comp);  	edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE); -	ret = wait_for_completion_timeout(&ctrl->idle_comp, +	time_left = wait_for_completion_timeout(&ctrl->idle_comp,  						msecs_to_jiffies(500)); -	if (ret <= 0) -		DBG("%s: idle pattern timedout, %d\n", -				__func__, ret); +	if (!time_left) +		DBG("%s: idle pattern timedout\n", __func__);  	edp_state_ctrl(ctrl, 0); @@ -1149,12 +1148,13 @@ int msm_edp_ctrl_init(struct msm_edp *edp)  	ctrl->aux = msm_edp_aux_init(dev, ctrl->base, &ctrl->drm_aux);  	if (!ctrl->aux || !ctrl->drm_aux) {  		pr_err("%s:failed to init aux\n", __func__); -		return ret; +		return -ENOMEM;  	}  	ctrl->phy = msm_edp_phy_init(dev, ctrl->base);  	if (!ctrl->phy) {  		pr_err("%s:failed to init phy\n", __func__); +		ret = -ENOMEM;  		goto err_destory_aux;  	} diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h index 350988740e9f..e6f034808371 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h @@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) @@ -750,5 +750,92 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)  #define REG_HDMI_8x74_BIST_PATN3				0x00000048 +#define REG_HDMI_28nm_PHY_PLL_REFCLK_CFG			0x00000000 + +#define REG_HDMI_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004 + +#define REG_HDMI_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008 + +#define REG_HDMI_28nm_PHY_PLL_VCOLPF_CFG			0x0000000c + +#define REG_HDMI_28nm_PHY_PLL_VREG_CFG				0x00000010 + +#define REG_HDMI_28nm_PHY_PLL_PWRGEN_CFG			0x00000014 + +#define REG_HDMI_28nm_PHY_PLL_DMUX_CFG				0x00000018 + +#define REG_HDMI_28nm_PHY_PLL_AMUX_CFG				0x0000001c + +#define REG_HDMI_28nm_PHY_PLL_GLB_CFG				0x00000020 +#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001 +#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002 +#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004 +#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008 + +#define REG_HDMI_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024 + +#define REG_HDMI_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028 + +#define REG_HDMI_28nm_PHY_PLL_LPFR_CFG				0x0000002c + +#define REG_HDMI_28nm_PHY_PLL_LPFC1_CFG				0x00000030 + +#define REG_HDMI_28nm_PHY_PLL_LPFC2_CFG				0x00000034 + +#define REG_HDMI_28nm_PHY_PLL_SDM_CFG0				0x00000038 + +#define REG_HDMI_28nm_PHY_PLL_SDM_CFG1				0x0000003c + +#define REG_HDMI_28nm_PHY_PLL_SDM_CFG2				0x00000040 + +#define REG_HDMI_28nm_PHY_PLL_SDM_CFG3				0x00000044 + +#define REG_HDMI_28nm_PHY_PLL_SDM_CFG4				0x00000048 + +#define REG_HDMI_28nm_PHY_PLL_SSC_CFG0				0x0000004c + +#define REG_HDMI_28nm_PHY_PLL_SSC_CFG1				0x00000050 + +#define REG_HDMI_28nm_PHY_PLL_SSC_CFG2				0x00000054 + +#define REG_HDMI_28nm_PHY_PLL_SSC_CFG3				0x00000058 + +#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG0			0x0000005c + +#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG1			0x00000060 + +#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG2			0x00000064 + +#define REG_HDMI_28nm_PHY_PLL_TEST_CFG				0x00000068 +#define HDMI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG0				0x0000006c + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG1				0x00000070 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG2				0x00000074 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG3				0x00000078 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG4				0x0000007c + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG5				0x00000080 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG6				0x00000084 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG7				0x00000088 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG8				0x0000008c + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG9				0x00000090 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG10				0x00000094 + +#define REG_HDMI_28nm_PHY_PLL_CAL_CFG11				0x00000098 + +#define REG_HDMI_28nm_PHY_PLL_EFUSE_CFG				0x0000009c + +#define REG_HDMI_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0 +  #endif /* HDMI_XML */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index b62cdb968614..54aa93ff5473 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -16,6 +16,7 @@   */  #include <linux/gpio.h> +#include <linux/pinctrl/consumer.h>  #include "msm_kms.h"  #include "hdmi.h" @@ -29,14 +30,14 @@ struct hdmi_connector {  static int gpio_config(struct hdmi *hdmi, bool on)  { -	struct drm_device *dev = hdmi->dev; +	struct device *dev = &hdmi->pdev->dev;  	const struct hdmi_platform_config *config = hdmi->config;  	int ret;  	if (on) {  		ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");  		if (ret) { -			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", +			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",  				"HDMI_DDC_CLK", config->ddc_clk_gpio, ret);  			goto error1;  		} @@ -44,7 +45,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)  		ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");  		if (ret) { -			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", +			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",  				"HDMI_DDC_DATA", config->ddc_data_gpio, ret);  			goto error2;  		} @@ -52,7 +53,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)  		ret = gpio_request(config->hpd_gpio, "HDMI_HPD");  		if (ret) { -			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", +			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",  				"HDMI_HPD", config->hpd_gpio, ret);  			goto error3;  		} @@ -62,7 +63,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)  		if (config->mux_en_gpio != -1) {  			ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");  			if (ret) { -				dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", +				dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",  					"HDMI_MUX_EN", config->mux_en_gpio, ret);  				goto error4;  			} @@ -72,7 +73,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)  		if (config->mux_sel_gpio != -1) {  			ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");  			if (ret) { -				dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", +				dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",  					"HDMI_MUX_SEL", config->mux_sel_gpio, ret);  				goto error5;  			} @@ -83,7 +84,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)  			ret = gpio_request(config->mux_lpm_gpio,  					"HDMI_MUX_LPM");  			if (ret) { -				dev_err(dev->dev, +				dev_err(dev,  					"'%s'(%d) gpio_request failed: %d\n",  					"HDMI_MUX_LPM",  					config->mux_lpm_gpio, ret); @@ -136,7 +137,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)  {  	struct hdmi *hdmi = hdmi_connector->hdmi;  	const struct hdmi_platform_config *config = hdmi->config; -	struct drm_device *dev = hdmi_connector->base.dev; +	struct device *dev = &hdmi->pdev->dev;  	struct hdmi_phy *phy = hdmi->phy;  	uint32_t hpd_ctrl;  	int i, ret; @@ -144,15 +145,21 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)  	for (i = 0; i < config->hpd_reg_cnt; i++) {  		ret = regulator_enable(hdmi->hpd_regs[i]);  		if (ret) { -			dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", +			dev_err(dev, "failed to enable hpd regulator: %s (%d)\n",  					config->hpd_reg_names[i], ret);  			goto fail;  		}  	} +	ret = pinctrl_pm_select_default_state(dev); +	if (ret) { +		dev_err(dev, "pinctrl state chg failed: %d\n", ret); +		goto fail; +	} +  	ret = gpio_config(hdmi, true);  	if (ret) { -		dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); +		dev_err(dev, "failed to configure GPIOs: %d\n", ret);  		goto fail;  	} @@ -161,13 +168,13 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)  			ret = clk_set_rate(hdmi->hpd_clks[i],  					config->hpd_freq[i]);  			if (ret) -				dev_warn(dev->dev, "failed to set clk %s (%d)\n", +				dev_warn(dev, "failed to set clk %s (%d)\n",  						config->hpd_clk_names[i], ret);  		}  		ret = clk_prepare_enable(hdmi->hpd_clks[i]);  		if (ret) { -			dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n", +			dev_err(dev, "failed to enable hpd clk: %s (%d)\n",  					config->hpd_clk_names[i], ret);  			goto fail;  		} @@ -204,7 +211,7 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)  {  	struct hdmi *hdmi = hdmi_connector->hdmi;  	const struct hdmi_platform_config *config = hdmi->config; -	struct drm_device *dev = hdmi_connector->base.dev; +	struct device *dev = &hdmi->pdev->dev;  	int i, ret = 0;  	/* Disable HPD interrupt */ @@ -217,12 +224,16 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)  	ret = gpio_config(hdmi, false);  	if (ret) -		dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); +		dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret); + +	ret = pinctrl_pm_select_sleep_state(dev); +	if (ret) +		dev_warn(dev, "pinctrl state chg failed: %d\n", ret);  	for (i = 0; i < config->hpd_reg_cnt; i++) {  		ret = regulator_disable(hdmi->hpd_regs[i]);  		if (ret) -			dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", +			dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n",  					config->hpd_reg_names[i], ret);  	}  } @@ -433,7 +444,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)  	ret = hpd_enable(hdmi_connector);  	if (ret) { -		dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret); +		dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);  		goto fail;  	} diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h index 43bb54a9afbf..978c3f70872a 100644 --- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h +++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h @@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h index 1d39174d91fb..153fc487d683 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h @@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -680,18 +680,18 @@ static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P3(uint32_t val)  	return ((val) << MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P3__MASK;  } -static inline uint32_t REG_MDP4_PIPE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; } -#define MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK			0xffff0000 -#define MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT			16 -static inline uint32_t MDP4_PIPE_FRAME_SIZE_HEIGHT(uint32_t val) +static inline uint32_t REG_MDP4_PIPE_SSTILE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; } +#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK		0xffff0000 +#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT		16 +static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(uint32_t val)  { -	return ((val) << MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK; +	return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK;  } -#define MDP4_PIPE_FRAME_SIZE_WIDTH__MASK			0x0000ffff -#define MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT			0 -static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val) +#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK			0x0000ffff +#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT		0 +static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(uint32_t val)  { -	return ((val) << MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_FRAME_SIZE_WIDTH__MASK; +	return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK;  }  static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; } diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 73afa21822b4..c4bb9d9c7667 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -51,6 +51,11 @@ struct mdp4_crtc {  	/* if there is a pending flip, these will be non-null: */  	struct drm_pending_vblank_event *event; +	/* Bits have been flushed at the last commit, +	 * used to decide if a vsync has happened since last commit. +	 */ +	u32 flushed_mask; +  #define PENDING_CURSOR 0x1  #define PENDING_FLIP   0x2  	atomic_t pending; @@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)  	DBG("%s: flush=%08x", mdp4_crtc->name, flush); +	mdp4_crtc->flushed_mask = flush; +  	mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);  } @@ -537,6 +544,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)  	crtc_flush(crtc);  } +static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); +	struct mdp4_kms *mdp4_kms = get_kms(crtc); +	int ret; + +	ret = drm_crtc_vblank_get(crtc); +	if (ret) +		return; + +	ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue, +		!(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) & +			mdp4_crtc->flushed_mask), +		msecs_to_jiffies(50)); +	if (ret <= 0) +		dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id); + +	mdp4_crtc->flushed_mask = 0; + +	drm_crtc_vblank_put(crtc); +} +  uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)  {  	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); @@ -600,6 +630,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)  	mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);  } +void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc) +{ +	/* wait_for_flush_done is the only case for now. +	 * Later we will have command mode CRTC to wait for +	 * other event. +	 */ +	mdp4_crtc_wait_for_flush_done(crtc); +} +  static const char *dma_names[] = {  		"DMA_P", "DMA_S", "DMA_E",  }; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c index 7896323b2631..89614c6a6c1b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c @@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)  	return to_mdp4_kms(to_mdp_kms(priv->kms));  } -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  /* not ironically named at all.. no, really.. */  static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index d847b9436194..531e4acc2a87 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -119,6 +119,8 @@ static int mdp4_hw_init(struct msm_kms *kms)  	if (mdp4_kms->rev > 1)  		mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1); +	dev->mode_config.allow_fb_modifiers = true; +  out:  	pm_runtime_put_sync(dev->dev); @@ -157,6 +159,12 @@ static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s  	mdp4_disable(mdp4_kms);  } +static void mdp4_wait_for_crtc_commit_done(struct msm_kms *kms, +						struct drm_crtc *crtc) +{ +	mdp4_crtc_wait_for_commit_done(crtc); +} +  static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,  		struct drm_encoder *encoder)  { @@ -195,6 +203,7 @@ static const struct mdp_kms_funcs kms_funcs = {  		.disable_vblank  = mdp4_disable_vblank,  		.prepare_commit  = mdp4_prepare_commit,  		.complete_commit = mdp4_complete_commit, +		.wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done,  		.get_format      = mdp_get_format,  		.round_pixclk    = mdp4_round_pixclk,  		.preclose        = mdp4_preclose, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 0a5c58bde7a9..c1ecb9d6bdef 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -206,6 +206,7 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);  void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);  void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);  void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); +void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc);  struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,  		struct drm_plane *plane, int id, int ovlp_id,  		enum mdp4_dma dma_id); @@ -229,7 +230,7 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev)  }  #endif -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  static inline int match_dev_name(struct device *dev, void *data)  {  	return !strcmp(dev_name(dev), data); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c index 60ec8222c9f6..c04843376c54 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c @@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)  	return to_mdp4_kms(to_mdp_kms(priv->kms));  } -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)  { diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index dbc068988377..0d1dbb737933 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -33,6 +33,21 @@ struct mdp4_plane {  };  #define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base) +/* MDP format helper functions */ +static inline +enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb) +{ +	bool is_tile = false; + +	if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) +		is_tile = true; + +	if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile) +		return FRAME_TILE_YCBCR_420; + +	return FRAME_LINEAR; +} +  static void mdp4_plane_set_scanout(struct drm_plane *plane,  		struct drm_framebuffer *fb);  static int mdp4_plane_mode_set(struct drm_plane *plane, @@ -205,6 +220,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,  	uint32_t op_mode = 0;  	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;  	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; +	enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb);  	if (!(crtc && fb)) {  		DBG("%s: disabled!", mdp4_plane->name); @@ -304,6 +320,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,  			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |  			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |  			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) | +			MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |  			COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));  	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe), @@ -324,6 +341,11 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,  	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);  	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step); +	if (frame_type != FRAME_LINEAR) +		mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe), +				MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) | +				MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h)); +  	return 0;  } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h index b9a4ded6e400..50e17527e2e5 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h @@ -8,9 +8,17 @@ http://github.com/freedreno/envytools/  git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are: -- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml            (  29312 bytes, from 2015-03-23 21:18:48) -- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2014-06-02 18:31:15) -- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2015-03-23 20:38:49) +- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49) +- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)  Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark) @@ -120,6 +128,21 @@ enum mdp5_data_format {  	DATA_FORMAT_YUV = 1,  }; +enum mdp5_block_size { +	BLOCK_SIZE_64 = 0, +	BLOCK_SIZE_128 = 1, +}; + +enum mdp5_rotate_mode { +	ROTATE_0 = 0, +	ROTATE_90 = 1, +}; + +enum mdp5_chroma_downsample_method { +	DS_MTHD_NO_PIXEL_DROP = 0, +	DS_MTHD_PIXEL_DROP = 1, +}; +  #define MDP5_IRQ_WB_0_DONE					0x00000001  #define MDP5_IRQ_WB_1_DONE					0x00000002  #define MDP5_IRQ_WB_2_DONE					0x00000010 @@ -314,19 +337,19 @@ static inline uint32_t MDP5_MDP_IGC_LUT_REG_VAL(uint32_t val)  #define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_1			0x20000000  #define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_2			0x40000000 -#define REG_MDP5_SPLIT_DPL_EN					0x000003f4 +static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_EN(uint32_t i0) { return 0x000002f4 + __offset_MDP(i0); } -#define REG_MDP5_SPLIT_DPL_UPPER				0x000003f8 -#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL			0x00000002 -#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN		0x00000004 -#define MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX			0x00000010 -#define MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX			0x00000100 +static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_UPPER(uint32_t i0) { return 0x000002f8 + __offset_MDP(i0); } +#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL			0x00000002 +#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN		0x00000004 +#define MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX		0x00000010 +#define MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX		0x00000100 -#define REG_MDP5_SPLIT_DPL_LOWER				0x000004f0 -#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL			0x00000002 -#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN		0x00000004 -#define MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC			0x00000010 -#define MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC			0x00000100 +static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_LOWER(uint32_t i0) { return 0x000003f0 + __offset_MDP(i0); } +#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL			0x00000002 +#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN		0x00000004 +#define MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC			0x00000010 +#define MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC			0x00000100  static inline uint32_t __offset_CTL(uint32_t idx)  { @@ -782,7 +805,7 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)  #define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB			0x00040000  #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK			0x00180000  #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT			19 -static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_sspp_fetch_type val) +static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_fetch_type val)  {  	return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;  } @@ -1234,6 +1257,351 @@ static inline uint32_t REG_MDP5_PP_FBC_BUDGET_CTL(uint32_t i0) { return 0x000000  static inline uint32_t REG_MDP5_PP_FBC_LOSSY_MODE(uint32_t i0) { return 0x0000003c + __offset_PP(i0); } +static inline uint32_t __offset_WB(uint32_t idx) +{ +	switch (idx) { +		default: return INVALID_IDX(idx); +	} +} +static inline uint32_t REG_MDP5_WB(uint32_t i0) { return 0x00000000 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST_FORMAT(uint32_t i0) { return 0x00000000 + __offset_WB(i0); } +#define MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK			0x00000003 +#define MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT			0 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC0_OUT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK			0x0000000c +#define MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT			2 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC1_OUT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK			0x00000030 +#define MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT			4 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC2_OUT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK			0x000000c0 +#define MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT			6 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC3_OUT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC3_EN				0x00000100 +#define MDP5_WB_DST_FORMAT_DST_BPP__MASK			0x00000600 +#define MDP5_WB_DST_FORMAT_DST_BPP__SHIFT			9 +static inline uint32_t MDP5_WB_DST_FORMAT_DST_BPP(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DST_BPP__SHIFT) & MDP5_WB_DST_FORMAT_DST_BPP__MASK; +} +#define MDP5_WB_DST_FORMAT_PACK_COUNT__MASK			0x00003000 +#define MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT			12 +static inline uint32_t MDP5_WB_DST_FORMAT_PACK_COUNT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT) & MDP5_WB_DST_FORMAT_PACK_COUNT__MASK; +} +#define MDP5_WB_DST_FORMAT_DST_ALPHA_X				0x00004000 +#define MDP5_WB_DST_FORMAT_PACK_TIGHT				0x00020000 +#define MDP5_WB_DST_FORMAT_PACK_ALIGN_MSB			0x00040000 +#define MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK			0x00180000 +#define MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT			19 +static inline uint32_t MDP5_WB_DST_FORMAT_WRITE_PLANES(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT) & MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK; +} +#define MDP5_WB_DST_FORMAT_DST_DITHER_EN			0x00400000 +#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK		0x03800000 +#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT		23 +static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK; +} +#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK		0x3c000000 +#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT		26 +static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SITE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK; +} +#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK			0xc0000000 +#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT			30 +static inline uint32_t MDP5_WB_DST_FORMAT_FRAME_FORMAT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT) & MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK; +} + +static inline uint32_t REG_MDP5_WB_DST_OP_MODE(uint32_t i0) { return 0x00000004 + __offset_WB(i0); } +#define MDP5_WB_DST_OP_MODE_BWC_ENC_EN				0x00000001 +#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK			0x00000006 +#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT			1 +static inline uint32_t MDP5_WB_DST_OP_MODE_BWC_ENC_OP(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT) & MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK; +} +#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK			0x00000010 +#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT			4 +static inline uint32_t MDP5_WB_DST_OP_MODE_BLOCK_SIZE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT) & MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK; +} +#define MDP5_WB_DST_OP_MODE_ROT_MODE__MASK			0x00000020 +#define MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT			5 +static inline uint32_t MDP5_WB_DST_OP_MODE_ROT_MODE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT) & MDP5_WB_DST_OP_MODE_ROT_MODE__MASK; +} +#define MDP5_WB_DST_OP_MODE_ROT_EN				0x00000040 +#define MDP5_WB_DST_OP_MODE_CSC_EN				0x00000100 +#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK		0x00000200 +#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT		9 +static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK; +} +#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK		0x00000400 +#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT		10 +static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK; +} +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_EN		0x00000800 +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK	0x00001000 +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT	12 +static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK; +} +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK	0x00002000 +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT	13 +static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK; +} +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK	0x00004000 +#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT	14 +static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK; +} + +static inline uint32_t REG_MDP5_WB_DST_PACK_PATTERN(uint32_t i0) { return 0x00000008 + __offset_WB(i0); } +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK			0x00000003 +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT		0 +static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT0(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK; +} +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK			0x00000300 +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT		8 +static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT1(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK; +} +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK			0x00030000 +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT		16 +static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT2(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK; +} +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK			0x03000000 +#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT		24 +static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT3(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK; +} + +static inline uint32_t REG_MDP5_WB_DST0_ADDR(uint32_t i0) { return 0x0000000c + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST1_ADDR(uint32_t i0) { return 0x00000010 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST2_ADDR(uint32_t i0) { return 0x00000014 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST3_ADDR(uint32_t i0) { return 0x00000018 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST_YSTRIDE0(uint32_t i0) { return 0x0000001c + __offset_WB(i0); } +#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK			0x0000ffff +#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT		0 +static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK; +} +#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK			0xffff0000 +#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT		16 +static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK; +} + +static inline uint32_t REG_MDP5_WB_DST_YSTRIDE1(uint32_t i0) { return 0x00000020 + __offset_WB(i0); } +#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK			0x0000ffff +#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT		0 +static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK; +} +#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK			0xffff0000 +#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT		16 +static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE(uint32_t val) +{ +	return ((val) << MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK; +} + +static inline uint32_t REG_MDP5_WB_DST_DITHER_BITDEPTH(uint32_t i0) { return 0x00000024 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW0(uint32_t i0) { return 0x00000030 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW1(uint32_t i0) { return 0x00000034 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW2(uint32_t i0) { return 0x00000038 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW3(uint32_t i0) { return 0x0000003c + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST_WRITE_CONFIG(uint32_t i0) { return 0x00000048 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_ROTATION_DNSCALER(uint32_t i0) { return 0x00000050 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_0_3(uint32_t i0) { return 0x00000060 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_1_2(uint32_t i0) { return 0x00000064 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_0_3(uint32_t i0) { return 0x00000068 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_1_2(uint32_t i0) { return 0x0000006c + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_OUT_SIZE(uint32_t i0) { return 0x00000074 + __offset_WB(i0); } +#define MDP5_WB_OUT_SIZE_DST_W__MASK				0x0000ffff +#define MDP5_WB_OUT_SIZE_DST_W__SHIFT				0 +static inline uint32_t MDP5_WB_OUT_SIZE_DST_W(uint32_t val) +{ +	return ((val) << MDP5_WB_OUT_SIZE_DST_W__SHIFT) & MDP5_WB_OUT_SIZE_DST_W__MASK; +} +#define MDP5_WB_OUT_SIZE_DST_H__MASK				0xffff0000 +#define MDP5_WB_OUT_SIZE_DST_H__SHIFT				16 +static inline uint32_t MDP5_WB_OUT_SIZE_DST_H(uint32_t val) +{ +	return ((val) << MDP5_WB_OUT_SIZE_DST_H__SHIFT) & MDP5_WB_OUT_SIZE_DST_H__MASK; +} + +static inline uint32_t REG_MDP5_WB_ALPHA_X_VALUE(uint32_t i0) { return 0x00000078 + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_0(uint32_t i0) { return 0x00000260 + __offset_WB(i0); } +#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK		0x00001fff +#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK; +} +#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK		0x1fff0000 +#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT		16 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_1(uint32_t i0) { return 0x00000264 + __offset_WB(i0); } +#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK		0x00001fff +#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK; +} +#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK		0x1fff0000 +#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT		16 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_2(uint32_t i0) { return 0x00000268 + __offset_WB(i0); } +#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK		0x00001fff +#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK; +} +#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK		0x1fff0000 +#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT		16 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_3(uint32_t i0) { return 0x0000026c + __offset_WB(i0); } +#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK		0x00001fff +#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK; +} +#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK		0x1fff0000 +#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT		16 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_4(uint32_t i0) { return 0x00000270 + __offset_WB(i0); } +#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK		0x00001fff +#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; } + +static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; } +#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK		0x000000ff +#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK; +} +#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK			0x0000ff00 +#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT		8 +static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; } + +static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; } +#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK		0x000000ff +#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK; +} +#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK		0x0000ff00 +#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT		8 +static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; } + +static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS_REG(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; } +#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK		0x000001ff +#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK; +} + +static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; } + +static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS_REG(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; } +#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK		0x000001ff +#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT		0 +static inline uint32_t MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE(uint32_t val) +{ +	return ((val) << MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK; +} +  static inline uint32_t __offset_INTF(uint32_t idx)  {  	switch (idx) { diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index e001e6b2296a..8b9a7931b162 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -72,14 +72,13 @@ const struct mdp5_cfg_hw msm8x74_config = {  		.base = { 0x12d00, 0x12e00, 0x12f00 },  	},  	.intf = { -		.count = 4,  		.base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, -	}, -	.intfs = { -		[0] = INTF_eDP, -		[1] = INTF_DSI, -		[2] = INTF_DSI, -		[3] = INTF_HDMI, +		.connect = { +			[0] = INTF_eDP, +			[1] = INTF_DSI, +			[2] = INTF_DSI, +			[3] = INTF_HDMI, +		},  	},  	.max_clk = 200000000,  }; @@ -142,14 +141,13 @@ const struct mdp5_cfg_hw apq8084_config = {  		.base = { 0x12f00, 0x13000, 0x13100, 0x13200 },  	},  	.intf = { -		.count = 5,  		.base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, -	}, -	.intfs = { -		[0] = INTF_eDP, -		[1] = INTF_DSI, -		[2] = INTF_DSI, -		[3] = INTF_HDMI, +		.connect = { +			[0] = INTF_eDP, +			[1] = INTF_DSI, +			[2] = INTF_DSI, +			[3] = INTF_HDMI, +		},  	},  	.max_clk = 320000000,  }; @@ -196,10 +194,12 @@ const struct mdp5_cfg_hw msm8x16_config = {  	},  	.intf = { -		.count = 1, /* INTF_1 */ -		.base = { 0x6B800 }, +		.base = { 0x00000, 0x6b800 }, +		.connect = { +			[0] = INTF_DISABLED, +			[1] = INTF_DSI, +		},  	}, -	/* TODO enable .intfs[] with [1] = INTF_DSI, once DSI is implemented */  	.max_clk = 320000000,  }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h index 3a551b0892d8..69349abe59f2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h @@ -59,6 +59,11 @@ struct mdp5_smp_block {  #define MDP5_INTF_NUM_MAX	5 +struct mdp5_intf_block { +	uint32_t base[MAX_BASES]; +	u32 connect[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */ +}; +  struct mdp5_cfg_hw {  	char  *name; @@ -72,9 +77,7 @@ struct mdp5_cfg_hw {  	struct mdp5_sub_block dspp;  	struct mdp5_sub_block ad;  	struct mdp5_sub_block pp; -	struct mdp5_sub_block intf; - -	u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */ +	struct mdp5_intf_block intf;  	uint32_t max_clk;  }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c index e4e89567f51d..ee31b16fe7ea 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c @@ -30,7 +30,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)  	return to_mdp5_kms(to_mdp_kms(priv->kms));  } -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  #include <linux/msm-bus.h>  #include <linux/msm-bus-board.h> @@ -216,16 +216,12 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,  static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)  {  	struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder); -	struct mdp5_kms *mdp5_kms = get_kms(encoder);  	struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);  	struct mdp5_interface *intf = &mdp5_cmd_enc->intf; -	int lm = mdp5_crtc_get_lm(encoder->crtc);  	if (WARN_ON(!mdp5_cmd_enc->enabled))  		return; -	/* Wait for the last frame done */ -	mdp_irq_wait(&mdp5_kms->base, lm2ppdone(lm));  	pingpong_tearcheck_disable(encoder);  	mdp5_ctl_set_encoder_state(ctl, false); @@ -281,22 +277,22 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,  	 * start signal for the slave encoder  	 */  	if (intf_num == 1) -		data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX; +		data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;  	else if (intf_num == 2) -		data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX; +		data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;  	else  		return -EINVAL;  	/* Smart Panel, Sync mode */ -	data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL; +	data |= MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL;  	/* Make sure clocks are on when connectors calling this function. */  	mdp5_enable(mdp5_kms); -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), data); -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, -			MDP5_SPLIT_DPL_LOWER_SMART_PANEL); -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0), +			MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);  	mdp5_disable(mdp5_kms);  	return 0; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index c1530772187d..dea3d2e559b1 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.   * Copyright (C) 2013 Red Hat   * Author: Rob Clark <robdclark@gmail.com>   * @@ -46,6 +46,11 @@ struct mdp5_crtc {  	/* if there is a pending flip, these will be non-null: */  	struct drm_pending_vblank_event *event; +	/* Bits have been flushed at the last commit, +	 * used to decide if a vsync has happened since last commit. +	 */ +	u32 flushed_mask; +  #define PENDING_CURSOR 0x1  #define PENDING_FLIP   0x2  	atomic_t pending; @@ -55,6 +60,11 @@ struct mdp5_crtc {  	struct mdp_irq vblank;  	struct mdp_irq err; +	struct mdp_irq pp_done; + +	struct completion pp_completion; + +	bool cmd_mode;  	struct {  		/* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/ @@ -82,12 +92,18 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)  	mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);  } -static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask) +static void request_pp_done_pending(struct drm_crtc *crtc) +{ +	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); +	reinit_completion(&mdp5_crtc->pp_completion); +} + +static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)  {  	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);  	DBG("%s: flush=%08x", mdp5_crtc->name, flush_mask); -	mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask); +	return mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);  }  /* @@ -95,7 +111,7 @@ static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)   * so that we can safely queue unref to current fb (ie. next   * vblank we know hw is done w/ previous scanout_fb).   */ -static void crtc_flush_all(struct drm_crtc *crtc) +static u32 crtc_flush_all(struct drm_crtc *crtc)  {  	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);  	struct drm_plane *plane; @@ -103,7 +119,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)  	/* this should not happen: */  	if (WARN_ON(!mdp5_crtc->ctl)) -		return; +		return 0;  	drm_atomic_crtc_for_each_plane(plane, crtc) {  		flush_mask |= mdp5_plane_get_flush(plane); @@ -111,7 +127,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)  	flush_mask |= mdp_ctl_flush_mask_lm(mdp5_crtc->lm); -	crtc_flush(crtc, flush_mask); +	return crtc_flush(crtc, flush_mask);  }  /* if file!=NULL, this is preclose potential cancel-flip path */ @@ -143,6 +159,8 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)  	}  	if (mdp5_crtc->ctl && !crtc->state->enable) { +		/* set STAGE_UNUSED for all layers */ +		mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);  		mdp5_ctl_release(mdp5_crtc->ctl);  		mdp5_crtc->ctl = NULL;  	} @@ -274,8 +292,8 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)  	if (WARN_ON(!mdp5_crtc->enabled))  		return; -	/* set STAGE_UNUSED for all layers */ -	mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000); +	if (mdp5_crtc->cmd_mode) +		mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);  	mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);  	mdp5_disable(mdp5_kms); @@ -296,6 +314,9 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)  	mdp5_enable(mdp5_kms);  	mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err); +	if (mdp5_crtc->cmd_mode) +		mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done); +  	mdp5_crtc->enabled = true;  } @@ -396,7 +417,18 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)  		return;  	blend_setup(crtc); -	crtc_flush_all(crtc); + +	/* PP_DONE irq is only used by command mode for now. +	 * It is better to request pending before FLUSH and START trigger +	 * to make sure no pp_done irq missed. +	 * This is safe because no pp_done will happen before SW trigger +	 * in command mode. +	 */ +	if (mdp5_crtc->cmd_mode) +		request_pp_done_pending(crtc); + +	mdp5_crtc->flushed_mask = crtc_flush_all(crtc); +  	request_pending(crtc, PENDING_FLIP);  } @@ -601,6 +633,52 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)  	DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);  } +static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus) +{ +	struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, +								pp_done); + +	complete(&mdp5_crtc->pp_completion); +} + +static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); +	int ret; + +	ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion, +						msecs_to_jiffies(50)); +	if (ret == 0) +		dev_warn(dev->dev, "pp done time out, lm=%d\n", mdp5_crtc->lm); +} + +static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); +	int ret; + +	/* Should not call this function if crtc is disabled. */ +	if (!mdp5_crtc->ctl) +		return; + +	ret = drm_crtc_vblank_get(crtc); +	if (ret) +		return; + +	ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue, +		((mdp5_ctl_get_commit_status(mdp5_crtc->ctl) & +		mdp5_crtc->flushed_mask) == 0), +		msecs_to_jiffies(50)); +	if (ret <= 0) +		dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp5_crtc->id); + +	mdp5_crtc->flushed_mask = 0; + +	drm_crtc_vblank_put(crtc); +} +  uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)  {  	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); @@ -622,16 +700,19 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)  	/* now that we know what irq's we want: */  	mdp5_crtc->err.irqmask = intf2err(intf->num); +	mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf); + +	if ((intf->type == INTF_DSI) && +		(intf->mode == MDP5_INTF_DSI_MODE_COMMAND)) { +		mdp5_crtc->pp_done.irqmask = lm2ppdone(lm); +		mdp5_crtc->pp_done.irq = mdp5_crtc_pp_done_irq; +		mdp5_crtc->cmd_mode = true; +	} else { +		mdp5_crtc->pp_done.irqmask = 0; +		mdp5_crtc->pp_done.irq = NULL; +		mdp5_crtc->cmd_mode = false; +	} -	/* Register command mode Pingpong done as vblank for now, -	 * so that atomic commit should wait for it to finish. -	 * Ideally, in the future, we should take rd_ptr done as vblank, -	 * and let atomic commit wait for pingpong done for commond mode. -	 */ -	if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND) -		mdp5_crtc->vblank.irqmask = lm2ppdone(lm); -	else -		mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);  	mdp_irq_update(&mdp5_kms->base);  	mdp5_ctl_set_intf(mdp5_crtc->ctl, intf); @@ -649,6 +730,16 @@ struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)  	return WARN_ON(!crtc) ? NULL : mdp5_crtc->ctl;  } +void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc) +{ +	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); + +	if (mdp5_crtc->cmd_mode) +		mdp5_crtc_wait_for_pp_done(crtc); +	else +		mdp5_crtc_wait_for_flush_done(crtc); +} +  /* initialize crtc */  struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,  		struct drm_plane *plane, int id) @@ -667,6 +758,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,  	spin_lock_init(&mdp5_crtc->lm_lock);  	spin_lock_init(&mdp5_crtc->cursor.lock); +	init_completion(&mdp5_crtc->pp_completion);  	mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;  	mdp5_crtc->err.irq = mdp5_crtc_err_irq; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c index 5488b687c8d1..f2530f224a76 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c @@ -392,8 +392,10 @@ static u32 fix_sw_flush(struct mdp5_ctl *ctl, u32 flush_mask)   * CTL registers need to be flushed in some circumstances; if that is the   * case, some trigger bits will be present in both flush mask and   * ctl->pending_ctl_trigger. + * + * Return H/W flushed bit mask.   */ -int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask) +u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)  {  	struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;  	struct op_mode *pipeline = &ctl->pipeline; @@ -424,7 +426,12 @@ int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)  		refill_start_mask(ctl);  	} -	return 0; +	return flush_mask; +} + +u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl) +{ +	return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id));  }  void mdp5_ctl_release(struct mdp5_ctl *ctl) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h index 7a62000994a1..4678228c4f14 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h @@ -88,7 +88,8 @@ u32 mdp_ctl_flush_mask_cursor(int cursor_id);  u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);  /* @flush_mask: see CTL flush masks definitions below */ -int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask); +u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask); +u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);  void mdp5_ctl_release(struct mdp5_ctl *ctl); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index 1188f4bf1e60..de97c08f3f1f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c @@ -36,7 +36,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)  	return to_mdp5_kms(to_mdp_kms(priv->kms));  } -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  #include <mach/msm_bus.h>  #include <mach/msm_bus_board.h> @@ -144,10 +144,14 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,  			mode->type, mode->flags);  	ctrl_pol = 0; -	if (mode->flags & DRM_MODE_FLAG_NHSYNC) -		ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW; -	if (mode->flags & DRM_MODE_FLAG_NVSYNC) -		ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW; + +	/* DSI controller cannot handle active-low sync signals. */ +	if (mdp5_encoder->intf.type != INTF_DSI) { +		if (mode->flags & DRM_MODE_FLAG_NHSYNC) +			ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW; +		if (mode->flags & DRM_MODE_FLAG_NVSYNC) +			ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW; +	}  	/* probably need to get DATA_EN polarity from panel.. */  	dtv_hsync_skew = 0;  /* get this from panel? */ @@ -304,9 +308,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,  	 * to use the master's enable signal for the slave encoder.  	 */  	if (intf_num == 1) -		data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC; +		data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC;  	else if (intf_num == 2) -		data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC; +		data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC;  	else  		return -EINVAL; @@ -315,9 +319,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,  	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPARE_0(0),  		MDP5_MDP_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN);  	/* Dumb Panel, Sync mode */ -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0); -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data); -	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), 0); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0), data); +	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);  	mdp5_disable(mdp5_kms);  	return 0; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index dfa8beb9343a..206f758f7d64 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -80,6 +80,12 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s  	mdp5_disable(mdp5_kms);  } +static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms, +						struct drm_crtc *crtc) +{ +	mdp5_crtc_wait_for_commit_done(crtc); +} +  static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,  		struct drm_encoder *encoder)  { @@ -141,6 +147,7 @@ static const struct mdp_kms_funcs kms_funcs = {  		.disable_vblank  = mdp5_disable_vblank,  		.prepare_commit  = mdp5_prepare_commit,  		.complete_commit = mdp5_complete_commit, +		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,  		.get_format      = mdp_get_format,  		.round_pixclk    = mdp5_round_pixclk,  		.set_split_display = mdp5_set_split_display, @@ -206,8 +213,8 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,  static int get_dsi_id_from_intf(const struct mdp5_cfg_hw *hw_cfg, int intf_num)  { -	const int intf_cnt = hw_cfg->intf.count; -	const u32 *intfs = hw_cfg->intfs; +	const enum mdp5_intf_type *intfs = hw_cfg->intf.connect; +	const int intf_cnt = ARRAY_SIZE(hw_cfg->intf.connect);  	int id = 0, i;  	for (i = 0; i < intf_cnt; i++) { @@ -228,7 +235,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)  	struct msm_drm_private *priv = dev->dev_private;  	const struct mdp5_cfg_hw *hw_cfg =  					mdp5_cfg_get_hw_config(mdp5_kms->cfg); -	enum mdp5_intf_type intf_type = hw_cfg->intfs[intf_num]; +	enum mdp5_intf_type intf_type = hw_cfg->intf.connect[intf_num];  	struct drm_encoder *encoder;  	int ret = 0; @@ -365,7 +372,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)  	/* Construct encoders and modeset initialize connector devices  	 * for each external display interface.  	 */ -	for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) { +	for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) {  		ret = modeset_init_intf(mdp5_kms, i);  		if (ret)  			goto fail; @@ -514,8 +521,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)  	 */  	mdp5_enable(mdp5_kms);  	for (i = 0; i < MDP5_INTF_NUM_MAX; i++) { -		if (!config->hw->intf.base[i] || -				mdp5_cfg_intf_is_virtual(config->hw->intfs[i])) +		if (mdp5_cfg_intf_is_virtual(config->hw->intf.connect[i]) || +				!config->hw->intf.base[i])  			continue;  		mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);  	} diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 2c0de174cc09..e0eb24587c84 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -237,6 +237,7 @@ int mdp5_crtc_get_lm(struct drm_crtc *crtc);  struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);  void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);  void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf); +void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);  struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,  		struct drm_plane *plane, int id); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 18a3d203b174..57b8f56ae9d0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -273,7 +273,7 @@ static void set_scanout_locked(struct drm_plane *plane,  	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC2_ADDR(pipe),  			msm_framebuffer_iova(fb, mdp5_kms->id, 2));  	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe), -			msm_framebuffer_iova(fb, mdp5_kms->id, 4)); +			msm_framebuffer_iova(fb, mdp5_kms->id, 3));  	plane->fb = fb;  } diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h index a1d35f162c7f..641d036c5bcb 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h @@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git  The rules-ng-ng source files this header was generated from are:  - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)  - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42) +- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03) +- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)  - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)  - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00) +- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23) +- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23) -Copyright (C) 2013-2014 by the following authors: +Copyright (C) 2013-2015 by the following authors:  - Rob Clark <robdclark@gmail.com> (robclark)  Permission is hereby granted, free of charge, to any person obtaining @@ -52,7 +52,7 @@ enum mdp_chroma_samp_type {  	CHROMA_420 = 3,  }; -enum mdp_sspp_fetch_type { +enum mdp_fetch_type {  	MDP_PLANE_INTERLEAVED = 0,  	MDP_PLANE_PLANAR = 1,  	MDP_PLANE_PSEUDO_PLANAR = 2, diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c index f683433b6727..7b0524dc1872 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_format.c +++ b/drivers/gpu/drm/msm/mdp/mdp_format.c @@ -96,6 +96,12 @@ static const struct mdp_format formats[] = {  	/*  name      a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt ... */  	FMT(ARGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  true,   true,  4,  4,  			MDP_PLANE_INTERLEAVED, CHROMA_RGB), +	FMT(ABGR8888, 8, 8, 8, 8,  2, 0, 1, 3,  true,   true,  4,  4, +			MDP_PLANE_INTERLEAVED, CHROMA_RGB), +	FMT(RGBA8888, 8, 8, 8, 8,  3, 1, 0, 2,  true,   true,  4,  4, +			MDP_PLANE_INTERLEAVED, CHROMA_RGB), +	FMT(BGRA8888, 8, 8, 8, 8,  3, 2, 0, 1,  true,   true,  4,  4, +			MDP_PLANE_INTERLEAVED, CHROMA_RGB),  	FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4,  			MDP_PLANE_INTERLEAVED, CHROMA_RGB),  	FMT(RGB888,   0, 8, 8, 8,  1, 0, 2, 0,  false,  true,  3,  3, diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h index 5ae4039d68e4..2d3428cb74d0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h @@ -88,7 +88,7 @@ struct mdp_format {  	uint8_t unpack[4];  	bool alpha_enable, unpack_tight;  	uint8_t cpp, unpack_count; -	enum mdp_sspp_fetch_type fetch_type; +	enum mdp_fetch_type fetch_type;  	enum mdp_chroma_samp_type chroma_sample;  };  #define to_mdp_format(x) container_of(x, struct mdp_format, base) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 5b192128cda2..1b22d8bfe142 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -84,6 +84,33 @@ static void commit_destroy(struct msm_commit *c)  	kfree(c);  } +static void msm_atomic_wait_for_commit_done(struct drm_device *dev, +		struct drm_atomic_state *old_state) +{ +	struct drm_crtc *crtc; +	struct msm_drm_private *priv = old_state->dev->dev_private; +	struct msm_kms *kms = priv->kms; +	int ncrtcs = old_state->dev->mode_config.num_crtc; +	int i; + +	for (i = 0; i < ncrtcs; i++) { +		crtc = old_state->crtcs[i]; + +		if (!crtc) +			continue; + +		if (!crtc->state->enable) +			continue; + +		/* Legacy cursor ioctls are completely unsynced, and userspace +		 * relies on that (by doing tons of cursor updates). */ +		if (old_state->legacy_cursor_update) +			continue; + +		kms->funcs->wait_for_crtc_commit_done(kms, crtc); +	} +} +  /* The (potentially) asynchronous part of the commit.  At this point   * nothing can fail short of armageddon.   */ @@ -115,7 +142,7 @@ static void complete_commit(struct msm_commit *c)  	 * not be critical path)  	 */ -	drm_atomic_helper_wait_for_vblanks(dev, state); +	msm_atomic_wait_for_commit_done(dev, state);  	drm_atomic_helper_cleanup_planes(dev, state); @@ -139,7 +166,6 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)  	c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));  } -  int msm_atomic_check(struct drm_device *dev,  		     struct drm_atomic_state *state)  { @@ -178,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev,  {  	int nplanes = dev->mode_config.num_total_plane;  	int ncrtcs = dev->mode_config.num_crtc; -	struct timespec timeout; +	ktime_t timeout;  	struct msm_commit *c;  	int i, ret; @@ -187,8 +213,10 @@ int msm_atomic_commit(struct drm_device *dev,  		return ret;  	c = commit_init(state); -	if (!c) -		return -ENOMEM; +	if (!c) { +		ret = -ENOMEM; +		goto error; +	}  	/*  	 * Figure out what crtcs we have: @@ -221,7 +249,7 @@ int msm_atomic_commit(struct drm_device *dev,  	ret = start_atomic(dev->dev_private, c->crtc_mask);  	if (ret) {  		kfree(c); -		return ret; +		goto error;  	}  	/* @@ -253,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev,  		return 0;  	} -	jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout); +	timeout = ktime_add_ms(ktime_get(), 1000);  	ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);  	if (ret) { @@ -265,4 +293,8 @@ int msm_atomic_commit(struct drm_device *dev,  	complete_commit(c);  	return 0; + +error: +	drm_atomic_helper_cleanup_planes(dev, state); +	return ret;  } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 47f4dd407671..b7ef56ed8d1c 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -21,9 +21,11 @@  static void msm_fb_output_poll_changed(struct drm_device *dev)  { +#ifdef CONFIG_DRM_MSM_FBDEV  	struct msm_drm_private *priv = dev->dev_private;  	if (priv->fbdev)  		drm_fb_helper_hotplug_event(priv->fbdev); +#endif  }  static const struct drm_mode_config_funcs mode_config_funcs = { @@ -94,7 +96,7 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,  	}  	if (reglog) -		printk(KERN_DEBUG "IO:region %s %08x %08lx\n", dbgname, (u32)ptr, size); +		printk(KERN_DEBUG "IO:region %s %p %08lx\n", dbgname, ptr, size);  	return ptr;  } @@ -102,7 +104,7 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,  void msm_writel(u32 data, void __iomem *addr)  {  	if (reglog) -		printk(KERN_DEBUG "IO:W %08x %08x\n", (u32)addr, data); +		printk(KERN_DEBUG "IO:W %p %08x\n", addr, data);  	writel(data, addr);  } @@ -110,7 +112,7 @@ u32 msm_readl(const void __iomem *addr)  {  	u32 val = readl(addr);  	if (reglog) -		printk(KERN_ERR "IO:R %08x %08x\n", (u32)addr, val); +		printk(KERN_ERR "IO:R %p %08x\n", addr, val);  	return val;  } @@ -143,8 +145,8 @@ static int msm_unload(struct drm_device *dev)  	if (gpu) {  		mutex_lock(&dev->struct_mutex);  		gpu->funcs->pm_suspend(gpu); -		gpu->funcs->destroy(gpu);  		mutex_unlock(&dev->struct_mutex); +		gpu->funcs->destroy(gpu);  	}  	if (priv->vram.paddr) { @@ -177,7 +179,7 @@ static int get_mdp_ver(struct platform_device *pdev)  	const struct of_device_id *match;  	match = of_match_node(match_types, dev->of_node);  	if (match) -		return (int)match->data; +		return (int)(unsigned long)match->data;  #endif  	return 4;  } @@ -216,7 +218,7 @@ static int msm_init_vram(struct drm_device *dev)  		if (ret)  			return ret;  		size = r.end - r.start; -		DRM_INFO("using VRAM carveout: %lx@%08x\n", size, r.start); +		DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start);  	} else  #endif @@ -283,10 +285,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)  	drm_mode_config_init(dev); -	ret = msm_init_vram(dev); -	if (ret) -		goto fail; -  	platform_set_drvdata(pdev, dev);  	/* Bind all our sub-components: */ @@ -294,6 +292,10 @@ static int msm_load(struct drm_device *dev, unsigned long flags)  	if (ret)  		return ret; +	ret = msm_init_vram(dev); +	if (ret) +		goto fail; +  	switch (get_mdp_ver(pdev)) {  	case 4:  		kms = mdp4_kms_init(dev); @@ -419,9 +421,11 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)  static void msm_lastclose(struct drm_device *dev)  { +#ifdef CONFIG_DRM_MSM_FBDEV  	struct msm_drm_private *priv = dev->dev_private;  	if (priv->fbdev)  		drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); +#endif  }  static irqreturn_t msm_irq(int irq, void *arg) @@ -634,7 +638,7 @@ static void msm_debugfs_cleanup(struct drm_minor *minor)   */  int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, -		struct timespec *timeout) +		ktime_t *timeout)  {  	struct msm_drm_private *priv = dev->dev_private;  	int ret; @@ -652,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,  		/* no-wait: */  		ret = fence_completed(dev, fence) ? 0 : -EBUSY;  	} else { -		unsigned long timeout_jiffies = timespec_to_jiffies(timeout); -		unsigned long start_jiffies = jiffies; +		ktime_t now = ktime_get();  		unsigned long remaining_jiffies; -		if (time_after(start_jiffies, timeout_jiffies)) +		if (ktime_compare(*timeout, now) < 0) {  			remaining_jiffies = 0; -		else -			remaining_jiffies = timeout_jiffies - start_jiffies; +		} else { +			ktime_t rem = ktime_sub(*timeout, now); +			struct timespec ts = ktime_to_timespec(rem); +			remaining_jiffies = timespec_to_jiffies(&ts); +		}  		ret = wait_event_interruptible_timeout(priv->fence_event,  				fence_completed(dev, fence), @@ -768,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,  			args->flags, &args->handle);  } -#define TS(t) ((struct timespec){ .tv_sec = (t).tv_sec, .tv_nsec = (t).tv_nsec }) +static inline ktime_t to_ktime(struct drm_msm_timespec timeout) +{ +	return ktime_set(timeout.tv_sec, timeout.tv_nsec); +}  static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,  		struct drm_file *file)  {  	struct drm_msm_gem_cpu_prep *args = data;  	struct drm_gem_object *obj; +	ktime_t timeout = to_ktime(args->timeout);  	int ret;  	if (args->op & ~MSM_PREP_FLAGS) { @@ -786,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,  	if (!obj)  		return -ENOENT; -	ret = msm_gem_cpu_prep(obj, args->op, &TS(args->timeout)); +	ret = msm_gem_cpu_prep(obj, args->op, &timeout);  	drm_gem_object_unreference_unlocked(obj); @@ -836,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,  		struct drm_file *file)  {  	struct drm_msm_wait_fence *args = data; +	ktime_t timeout = to_ktime(args->timeout);  	if (args->pad) {  		DRM_ERROR("invalid pad: %08x\n", args->pad);  		return -EINVAL;  	} -	return msm_wait_fence_interruptable(dev, args->fence, -			&TS(args->timeout)); +	return msm_wait_fence_interruptable(dev, args->fence, &timeout);  }  static const struct drm_ioctl_desc msm_ioctls[] = { @@ -881,6 +891,7 @@ static struct drm_driver msm_driver = {  				DRIVER_GEM |  				DRIVER_PRIME |  				DRIVER_RENDER | +				DRIVER_ATOMIC |  				DRIVER_MODESET,  	.load               = msm_load,  	.unload             = msm_unload, diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 04db4bd1b5b6..e7c5ea125d45 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -165,7 +165,7 @@ int msm_atomic_commit(struct drm_device *dev,  int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);  int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, -		struct timespec *timeout); +		ktime_t *timeout);  int msm_queue_fence_cb(struct drm_device *dev,  		struct msm_fence_cb *cb, uint32_t fence);  void msm_update_fence(struct drm_device *dev, uint32_t fence); @@ -205,7 +205,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj,  		struct msm_gpu *gpu, bool write, uint32_t fence);  void msm_gem_move_to_inactive(struct drm_gem_object *obj);  int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, -		struct timespec *timeout); +		ktime_t *timeout);  int msm_gem_cpu_fini(struct drm_gem_object *obj);  void msm_gem_free_object(struct drm_gem_object *obj);  int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 6b573e612f27..121713281417 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -172,8 +172,8 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,  {  	struct msm_drm_private *priv = dev->dev_private;  	struct msm_kms *kms = priv->kms; -	struct msm_framebuffer *msm_fb; -	struct drm_framebuffer *fb = NULL; +	struct msm_framebuffer *msm_fb = NULL; +	struct drm_framebuffer *fb;  	const struct msm_format *format;  	int ret, i, n;  	unsigned int hsub, vsub; @@ -239,8 +239,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,  	return fb;  fail: -	if (fb) -		msm_framebuffer_destroy(fb); +	kfree(msm_fb);  	return ERR_PTR(ret);  } diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 479d8af72bcb..f211b80e3a1e 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -448,8 +448,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)  	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);  } -int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, -		struct timespec *timeout) +int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)  {  	struct drm_device *dev = obj->dev;  	struct msm_gem_object *msm_obj = to_msm_bo(obj); @@ -483,7 +482,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)  	uint64_t off = drm_vma_node_start(&obj->vma_node);  	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); -	seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n", +	seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n",  			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',  			msm_obj->read_fence, msm_obj->write_fence,  			obj->name, obj->refcount.refcount.counter, @@ -540,6 +539,7 @@ void msm_gem_free_object(struct drm_gem_object *obj)  		if (msm_obj->pages)  			drm_free_large(msm_obj->pages); +		drm_prime_gem_destroy(obj, msm_obj->sgt);  	} else {  		vunmap(msm_obj->vaddr);  		put_pages(obj); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 85d481e29276..6fc59bfeedeb 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -96,6 +96,7 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,  struct msm_gem_submit {  	struct drm_device *dev;  	struct msm_gpu *gpu; +	struct list_head node;   /* node in gpu submit_list */  	struct list_head bo_list;  	struct ww_acquire_ctx ticket;  	uint32_t fence; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index cd0554f68316..6d7cd3fe21e7 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -314,7 +314,6 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail)  	}  	ww_acquire_fini(&submit->ticket); -	kfree(submit);  }  int msm_ioctl_gem_submit(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4a0dce587745..8f70d9248ac5 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -24,7 +24,7 @@   * Power Management:   */ -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  static void bs_init(struct msm_gpu *gpu)  { @@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu)   * Hangcheck detection for locked gpu:   */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence); +  static void recover_worker(struct work_struct *work)  {  	struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); @@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work)  	mutex_lock(&dev->struct_mutex);  	if (msm_gpu_active(gpu)) { +		struct msm_gem_submit *submit; +		uint32_t fence = gpu->funcs->last_fence(gpu); + +		/* retire completed submits, plus the one that hung: */ +		retire_submits(gpu, fence + 1); +  		inactive_cancel(gpu);  		gpu->funcs->recover(gpu); + +		/* replay the remaining submits after the one that hung: */ +		list_for_each_entry(submit, &gpu->submit_list, node) { +			gpu->funcs->submit(gpu, submit, NULL); +		}  	}  	mutex_unlock(&dev->struct_mutex); @@ -418,6 +431,27 @@ out:   * Cmdstream submission/retirement:   */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence) +{ +	struct drm_device *dev = gpu->dev; + +	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + +	while (!list_empty(&gpu->submit_list)) { +		struct msm_gem_submit *submit; + +		submit = list_first_entry(&gpu->submit_list, +				struct msm_gem_submit, node); + +		if (submit->fence <= fence) { +			list_del(&submit->node); +			kfree(submit); +		} else { +			break; +		} +	} +} +  static void retire_worker(struct work_struct *work)  {  	struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work); @@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work)  	mutex_lock(&dev->struct_mutex); +	retire_submits(gpu, fence); +  	while (!list_empty(&gpu->active_list)) {  		struct msm_gem_object *obj; @@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,  	struct msm_drm_private *priv = dev->dev_private;  	int i, ret; +	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); +  	submit->fence = ++priv->next_fence;  	gpu->submitted_fence = submit->fence;  	inactive_cancel(gpu); +	list_add_tail(&submit->node, &gpu->submit_list); +  	msm_rd_dump_submit(submit);  	gpu->submitted_fence = submit->fence;  	update_sw_cntrs(gpu); -	ret = gpu->funcs->submit(gpu, submit, ctx); -	priv->lastctx = ctx; -  	for (i = 0; i < submit->nr_bos; i++) {  		struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,  		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)  			msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);  	} + +	ret = gpu->funcs->submit(gpu, submit, ctx); +	priv->lastctx = ctx; +  	hangcheck_timer_reset(gpu);  	return ret; @@ -522,6 +563,7 @@ static irqreturn_t irq_handler(int irq, void *data)  static const char *clk_names[] = {  		"src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk", +		"alt_mem_iface_clk",  };  int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, @@ -544,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	INIT_WORK(&gpu->inactive_work, inactive_worker);  	INIT_WORK(&gpu->recover_work, recover_worker); +	INIT_LIST_HEAD(&gpu->submit_list); +  	setup_timer(&gpu->inactive_timer, inactive_handler,  			(unsigned long)gpu);  	setup_timer(&gpu->hangcheck_timer, hangcheck_handler, diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index fd1e4b4a6d40..2bbe85a3d6f6 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -100,10 +100,10 @@ struct msm_gpu {  	/* Power Control: */  	struct regulator *gpu_reg, *gpu_cx; -	struct clk *ebi1_clk, *grp_clks[5]; +	struct clk *ebi1_clk, *grp_clks[6];  	uint32_t fast_rate, slow_rate, bus_freq; -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  	struct msm_bus_scale_pdata *bus_scale_table;  	uint32_t bsc;  #endif @@ -119,6 +119,8 @@ struct msm_gpu {  	struct timer_list hangcheck_timer;  	uint32_t hangcheck_fence;  	struct work_struct recover_work; + +	struct list_head submit_list;  };  static inline bool msm_gpu_active(struct msm_gpu *gpu) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 7acdaa5688b7..7ac2f1997e4a 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -60,7 +60,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,  		u32 pa = sg_phys(sg) - sg->offset;  		size_t bytes = sg->length + sg->offset; -		VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes); +		VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);  		ret = iommu_map(domain, da, pa, bytes, prot);  		if (ret) @@ -99,7 +99,7 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,  		if (unmapped < bytes)  			return unmapped; -		VERB("unmap[%d]: %08x(%x)", i, iova, bytes); +		VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);  		BUG_ON(!PAGE_ALIGNED(bytes)); diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index a9f17bdb4530..9bcabaada179 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -43,6 +43,9 @@ struct msm_kms_funcs {  	/* modeset, bracketing atomic_commit(): */  	void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);  	void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state); +	/* functions to wait for atomic commit completed on each CRTC */ +	void (*wait_for_crtc_commit_done)(struct msm_kms *kms, +					struct drm_crtc *crtc);  	/* misc: */  	const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);  	long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 8171537dd7d1..1f14b908b221 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -56,6 +56,6 @@ fail:  void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)  {  	if (ring->bo) -		drm_gem_object_unreference(ring->bo); +		drm_gem_object_unreference_unlocked(ring->bo);  	kfree(ring);  } | 
