Video: worked around the random CTS failures with AVC decoding.

Bug: 37283516, 62788295, 38138788, 32717946
BZ: IMINAN-51520, IMINAN-51500, IMINAN-51528

When running CTS cases testOtherH264ImageReader or DecodeAccuracyTest,
randomly some bytes of the decoded U/V couldn't be flushed into system
memory from SLC (system level cache). So worked around this issue by
disabling SLC for video decoder for the specific AVC clips/streams.

Need to check whether it's video decoder hardware issue or not.

Change-Id: If44d8c112a88652858b588c4e62fcd25b1ba3ce6
Signed-off-by: Austin Hu <austin.hu@intel.com>
diff --git a/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c b/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
index 9c1aaae..4f3e23a 100644
--- a/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
+++ b/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
@@ -160,7 +160,8 @@
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
 
-	if (atomic_read(&msvdx_priv->vc1_workaround_ctx)) {
+	if (!(msvdx_priv->msvdx_ctx->ctx_type & VA_RT_FORMAT_PROTECTED) &&
+			atomic_read(&msvdx_priv->slc_workaround_ctx)) {
 		uint32_t reg, data;
 
 		/* soc.gfx_wrapper.gbypassenable_sw = 1 */
diff --git a/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c b/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
index 576f270..5ee6d39 100644
--- a/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
+++ b/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
@@ -50,8 +50,15 @@
 extern int sepapp_drm_playback(bool ied_status);
 static int ied_enabled;
 
-static void ann_rm_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type);
-static void ann_add_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type);
+enum slc_setting {
+	enable_slc,
+	disable_slc,
+};
+
+static void ann_workaround_ctx_set_slc(struct drm_psb_private *dev_priv,
+		uint64_t ctx_type, enum slc_setting slc_set);
+
+#define MB_SIZE 16
 
 #ifdef MERRIFIELD
 struct psb_fpriv *psb_fpriv(struct drm_file *file_priv)
@@ -295,7 +302,8 @@
 				  (found_ctx->ctx_type >> 8) & 0xff,
 				  (found_ctx->ctx_type & 0xff));
 		if (IS_ANN(dev))
-			ann_rm_workaround_ctx(dev_priv, found_ctx->ctx_type);
+			ann_workaround_ctx_set_slc(dev_priv, ctx_type,
+					enable_slc);
 #ifndef CONFIG_DRM_VXD_BYT
 		/* if current ctx points to it, set to NULL */
 		if ((VAEntrypointEncSlice ==
@@ -459,7 +467,8 @@
 		video_ctx->ctx_type = ctx_type;
 		video_ctx->cur_sequence = 0xffffffff;
 		if (IS_ANN(dev))
-			ann_add_workaround_ctx(dev_priv, ctx_type);
+			ann_workaround_ctx_set_slc(dev_priv, ctx_type,
+					disable_slc);
 #ifdef CONFIG_SLICE_HEADER_PARSING
 		video_ctx->frame_end_seq = 0xffffffff;
 		if (ctx_type & VA_RT_FORMAT_PROTECTED) {
@@ -753,19 +762,22 @@
 	return 0;
 }
 
-/* SLC bug: there is green corruption for vc1 decode if width is not 64 aligned
- * Recode the number of VC1 ctx whose width is not 64 aligned
+/*
+ * SLC bug: there is green corruption for VC1/VP8/H.264 decode if:
+ * 1. VC1/VP8 width is not 64 aligned. Recode the number of VC1 ctx whose width
+ * is not 64 aligned;
+ * 2. H.264 resolution <= 720p.
  */
-static void ann_add_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type)
+static void ann_workaround_ctx_set_slc(struct drm_psb_private *dev_priv,
+		uint64_t ctx_type, enum slc_setting slc_set)
 {
 
 	struct msvdx_private *msvdx_priv;
 	int profile = (ctx_type >> 8) & 0xff;
-
-	if (profile != VAProfileVC1Simple &&
-	    profile != VAProfileVC1Main &&
-	    profile != VAProfileVC1Advanced)
-		return;
+	/* ctx_type >> 32 is width_in_mb */
+	uint64_t width = ((ctx_type >> 32) & 0xffff) * MB_SIZE;
+	/* ctx_type >> 48 is height_in_mb */
+	uint64_t height = ((ctx_type >> 48) & 0xffff) * MB_SIZE;
 
 	if (unlikely(!dev_priv))
 		return;
@@ -774,41 +786,32 @@
 	if (unlikely(!msvdx_priv))
 		return;
 
-	PSB_DEBUG_GENERAL(
-	    "add vc1 ctx, ctx_type is 0x%llx\n",
-		ctx_type);
+	switch (profile) {
+	case VAProfileVC1Simple:
+	case VAProfileVC1Main:
+	case VAProfileVC1Advanced:
+	case VAProfileVP8Version0_3:
+		if (width % 64) {
+			if (slc_set == disable_slc)
+				atomic_inc(&msvdx_priv->slc_workaround_ctx);
+			else
+				atomic_dec(&msvdx_priv->slc_workaround_ctx);
+		}
+		break;
 
-	/* ctx_type >> 32 is width_in_mb */
-	if ((ctx_type >> 32) % 4) {
-		atomic_inc(&msvdx_priv->vc1_workaround_ctx);
-		PSB_DEBUG_GENERAL("add workaround ctx %p in ctx\n", msvdx_priv);
-	}
-}
+	case VAProfileH264Baseline:
+	case VAProfileH264Main:
+	case VAProfileH264High:
+		if (((height == 128) && (width > 112) && (width <= 128)) ||
+				((width <= 1280) && (height <= 736))) {
+			if (slc_set == disable_slc)
+				atomic_inc(&msvdx_priv->slc_workaround_ctx);
+			else
+				atomic_dec(&msvdx_priv->slc_workaround_ctx);
+		}
+		break;
 
-static void ann_rm_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type)
-{
-
-	struct msvdx_private *msvdx_priv;
-	int profile = (ctx_type >> 8) & 0xff;
-
-	if (profile != VAProfileVC1Simple &&
-	    profile != VAProfileVC1Main &&
-	    profile != VAProfileVC1Advanced)
-		return;
-
-	if (unlikely(!dev_priv))
-		return;
-
-	msvdx_priv = dev_priv->msvdx_private;
-	if (unlikely(!msvdx_priv))
-		return;
-
-	PSB_DEBUG_GENERAL(
-	    "rm vc1 ctx, ctx_type is 0x%llx\n",
-		ctx_type);
-	/* ctx_type >> 32 is width_in_mb */
-	if ((ctx_type >> 32) % 4) {
-		atomic_dec(&msvdx_priv->vc1_workaround_ctx);
-		PSB_DEBUG_GENERAL("dec workaround ctx %p in ctx\n", msvdx_priv);
+	default:
+		break;
 	}
 }
diff --git a/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h b/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
index 0dc8fed..6cb6376 100644
--- a/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
+++ b/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
@@ -276,7 +276,7 @@
 	uint32_t term_buf_addr;
 #endif
 
-	atomic_t vc1_workaround_ctx;
+	atomic_t slc_workaround_ctx;
 
 #ifdef CONFIG_ION
 	struct list_head ion_buffers_list;