pmaports/device/linux-meizu-turbo/0005-Use-Samsung-MFC-from-A810.patch
elelel 7597fa7a22 new device: meizu-turbo (Meizu Pro 5) (!106)
The device boots till USB networking.
2019-02-21 20:25:18 +00:00

6547 lines
215 KiB
Diff

From e9eb0f878b6c2173654d6d7780fd1babc427ccea Mon Sep 17 00:00:00 2001
From: "elel@3wh.net" <elel@3wh.net>
Date: Thu, 27 Dec 2018 14:37:10 +0000
Subject: [PATCH 5/5] Use Samsung MFC from A810
---
drivers/media/platform/exynos/mfc/Kconfig | 0
drivers/media/platform/exynos/mfc/Makefile | 0
.../media/platform/exynos/mfc/regs-mfc-v5.h | 3 +
.../media/platform/exynos/mfc/regs-mfc-v6.h | 34 +-
.../media/platform/exynos/mfc/regs-mfc-v8.h | 32 +-
.../media/platform/exynos/mfc/regs-mfc-v9.h | 42 +-
drivers/media/platform/exynos/mfc/s5p_mfc.c | 509 +++--
.../media/platform/exynos/mfc/s5p_mfc_cmd.h | 0
.../platform/exynos/mfc/s5p_mfc_cmd_v5.c | 0
.../platform/exynos/mfc/s5p_mfc_cmd_v6.c | 0
.../platform/exynos/mfc/s5p_mfc_common.h | 145 +-
.../media/platform/exynos/mfc/s5p_mfc_ctrl.c | 42 +-
.../media/platform/exynos/mfc/s5p_mfc_ctrl.h | 0
.../media/platform/exynos/mfc/s5p_mfc_debug.h | 7 -
.../media/platform/exynos/mfc/s5p_mfc_dec.c | 170 +-
.../media/platform/exynos/mfc/s5p_mfc_dec.h | 2 +-
.../media/platform/exynos/mfc/s5p_mfc_enc.c | 1764 +++++++++++++----
.../media/platform/exynos/mfc/s5p_mfc_enc.h | 2 +-
.../media/platform/exynos/mfc/s5p_mfc_inst.c | 0
.../media/platform/exynos/mfc/s5p_mfc_inst.h | 0
.../media/platform/exynos/mfc/s5p_mfc_intr.c | 0
.../media/platform/exynos/mfc/s5p_mfc_intr.h | 0
.../media/platform/exynos/mfc/s5p_mfc_mem.c | 0
.../media/platform/exynos/mfc/s5p_mfc_mem.h | 0
.../platform/exynos/mfc/s5p_mfc_opr_v5.c | 4 +-
.../platform/exynos/mfc/s5p_mfc_opr_v5.h | 1 +
.../platform/exynos/mfc/s5p_mfc_opr_v6.c | 1154 ++++++-----
.../platform/exynos/mfc/s5p_mfc_opr_v6.h | 1 +
.../platform/exynos/mfc/s5p_mfc_opr_v8.h | 1 +
.../platform/exynos/mfc/s5p_mfc_opr_v9.h | 25 -
.../media/platform/exynos/mfc/s5p_mfc_pm.c | 0
.../media/platform/exynos/mfc/s5p_mfc_pm.h | 0
.../media/platform/exynos/mfc/s5p_mfc_qos.c | 15 +-
.../media/platform/exynos/mfc/s5p_mfc_reg.c | 0
.../media/platform/exynos/mfc/s5p_mfc_reg.h | 0
.../media/platform/exynos/mfc/s5p_mfc_shm.c | 0
.../media/platform/exynos/mfc/s5p_mfc_shm.h | 0
include/uapi/linux/v4l2-controls.h | 6 +-
include/uapi/linux/videodev2_exynos_media.h | 128 +-
39 files changed, 2820 insertions(+), 1267 deletions(-)
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/Kconfig
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/Makefile
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/regs-mfc-v5.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/regs-mfc-v6.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/regs-mfc-v8.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/regs-mfc-v9.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v5.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v6.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_common.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_inst.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_intr.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_intr.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_mem.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_mem.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v8.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_opr_v9.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_pm.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_pm.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_reg.h
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_shm.c
mode change 100644 => 100755 drivers/media/platform/exynos/mfc/s5p_mfc_shm.h
mode change 100644 => 100755 include/uapi/linux/v4l2-controls.h
mode change 100644 => 100755 include/uapi/linux/videodev2_exynos_media.h
diff --git a/drivers/media/platform/exynos/mfc/Kconfig b/drivers/media/platform/exynos/mfc/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/Makefile b/drivers/media/platform/exynos/mfc/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/regs-mfc-v5.h b/drivers/media/platform/exynos/mfc/regs-mfc-v5.h
old mode 100644
new mode 100755
index d7a16b816b88..1e63a2f79548
--- a/drivers/media/platform/exynos/mfc/regs-mfc-v5.h
+++ b/drivers/media/platform/exynos/mfc/regs-mfc-v5.h
@@ -128,6 +128,7 @@
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 1
#define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2
#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_HIGH 5
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
#define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
@@ -398,6 +399,8 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_MFC_VERSION 0
#define S5P_FIMV_ERR_FRAME_CONCEAL -1
#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET -2
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0 -1
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1 -1
/* for compatibility */
#define S5P_FIMV_E_GOP_CONFIG2 -1
diff --git a/drivers/media/platform/exynos/mfc/regs-mfc-v6.h b/drivers/media/platform/exynos/mfc/regs-mfc-v6.h
old mode 100644
new mode 100755
index bce2f1571dc2..15f83e965b76
--- a/drivers/media/platform/exynos/mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/exynos/mfc/regs-mfc-v6.h
@@ -140,6 +140,8 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_RET_INSTANCE_ID 0xF070
#define S5P_FIMV_ERROR_CODE 0xF074
+#define S5P_FIMV_ERR_HEADER_NOT_FOUND 102
+#define S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED 190
#define S5P_FIMV_ERR_WARNINGS_START 160
#define S5P_FIMV_ERR_WARNINGS_END 222
#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
@@ -173,6 +175,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_D_SEI_ENABLE 0xF0C4
#define S5P_FIMV_D_SEI_NEED_INIT_BUFFER_SHIFT 1
+#define S5P_FIMV_D_SEI_RECOVERY_PARSING_ENABLE 2
/* Buffer setting registers */
#define S5P_FIMV_D_MIN_NUM_DPB 0xF0F0
@@ -337,6 +340,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_ENC_PROFILE_H264_MAIN 1
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 2
#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_HIGH 5
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
#define S5P_FIMV_E_FIXED_PICTURE_QP 0xF790
@@ -405,12 +409,15 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_MPEG4_OPTIONS 0xFB10
#define S5P_FIMV_E_MPEG4_HEC_PERIOD 0xFB14
+
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0 0xFB44
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1 0xFB48
+#define S5P_FIMV_E_H264_OPTIONS_2 0xFB4C
#define S5P_FIMV_E_ASPECT_RATIO 0xFB50
#define S5P_FIMV_E_EXTENDED_SAR 0xFB54
#define S5P_FIMV_E_IDR_H264_IDR 0
#define S5P_FIMV_E_H264_OPTIONS 0xFB58
-#define S5P_FIMV_E_H264_OPTIONS_2 0xFB4C
#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET 0xFB5C
#define S5P_FIMV_E_H264_LF_BETA_OFFSET 0xFB60
#define S5P_FIMV_E_H264_I_PERIOD 0xFB64
@@ -432,13 +439,10 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5 0xFB9C
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6 0xFBA0
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7 0xFBA4
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
#define S5P_FIMV_E_NUM_T_LAYER 0xFBAC
-/* For backward compatibility */
-#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
-#define S5P_FIMV_E_H264_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 0xFBB0
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1 0xFBB4
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2 0xFBB8
@@ -448,23 +452,8 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6 0xFBC8
/* For backward compatibility */
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3 S5P_FIMV_E_HIERARCHICAL_QP_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4 S5P_FIMV_E_HIERARCHICAL_QP_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5 S5P_FIMV_E_HIERARCHICAL_QP_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6 S5P_FIMV_E_HIERARCHICAL_QP_LAYER6
-
#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER1 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER2 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER3 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER4 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER5 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER6 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 0xFD18
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1 0xFD1C
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2 0xFD20
@@ -828,11 +817,6 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_VP8_OPTION 0xFDB0
#define S5P_FIMV_E_VP8_FILTER_OPTIONS 0xFDB4
#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION 0xFDB8
-/* For backward compatibility */
-#define S5P_FIMV_E_VP8_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
/* for compatibility */
#define S5P_FIMV_E_HEVC_OPTIONS -1
#define S5P_FIMV_E_HEVC_REFRESH_PERIOD -1
diff --git a/drivers/media/platform/exynos/mfc/regs-mfc-v8.h b/drivers/media/platform/exynos/mfc/regs-mfc-v8.h
old mode 100644
new mode 100755
index 53c38ba1f1ca..195df530aa8e
--- a/drivers/media/platform/exynos/mfc/regs-mfc-v8.h
+++ b/drivers/media/platform/exynos/mfc/regs-mfc-v8.h
@@ -144,6 +144,8 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_RET_INSTANCE_ID 0xF070
#define S5P_FIMV_ERROR_CODE 0xF074
+#define S5P_FIMV_ERR_HEADER_NOT_FOUND 102
+#define S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED 190
#define S5P_FIMV_ERR_WARNINGS_START 160
#define S5P_FIMV_ERR_WARNINGS_END 222
#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
@@ -178,6 +180,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_D_SEI_ENABLE 0xF0C4
#define S5P_FIMV_D_SEI_NEED_INIT_BUFFER_SHIFT 1
+#define S5P_FIMV_D_SEI_RECOVERY_PARSING_ENABLE 2
/* Buffer setting registers */
/* Session return */
@@ -372,6 +375,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_ENC_PROFILE_H264_MAIN 1
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 2
#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_HIGH 5
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
#define S5P_FIMV_E_FIXED_PICTURE_QP 0xF794
@@ -453,6 +457,9 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_MPEG4_OPTIONS 0xFB10
#define S5P_FIMV_E_MPEG4_HEC_PERIOD 0xFB14
+
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0 0xFB44
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1 0xFB48
#define S5P_FIMV_E_ASPECT_RATIO 0xFB4C
#define S5P_FIMV_E_EXTENDED_SAR 0xFB50
@@ -480,13 +487,10 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5 0xFB9C
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6 0xFBA0
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7 0xFBA4
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
#define S5P_FIMV_E_NUM_T_LAYER 0xFBAC
-/* For backward compatibility */
-#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
-#define S5P_FIMV_E_H264_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 0xFBB0
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1 0xFBB4
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2 0xFBB8
@@ -496,23 +500,8 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6 0xFBC8
/* For backward compatibility */
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3 S5P_FIMV_E_HIERARCHICAL_QP_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4 S5P_FIMV_E_HIERARCHICAL_QP_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5 S5P_FIMV_E_HIERARCHICAL_QP_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6 S5P_FIMV_E_HIERARCHICAL_QP_LAYER6
-
#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER1 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER2 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER3 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER4 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER5 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER6 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 0xFD18
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1 0xFD1C
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2 0xFD20
@@ -531,11 +520,6 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_VP8_OPTION 0xFDB0
#define S5P_FIMV_E_VP8_FILTER_OPTIONS 0xFDB4
#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION 0xFDB8
-/* For backward compatibility */
-#define S5P_FIMV_E_VP8_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
/* for compatibility */
#define S5P_FIMV_E_HEVC_OPTIONS -1
#define S5P_FIMV_E_HEVC_REFRESH_PERIOD -1
diff --git a/drivers/media/platform/exynos/mfc/regs-mfc-v9.h b/drivers/media/platform/exynos/mfc/regs-mfc-v9.h
old mode 100644
new mode 100755
index 5dab5fc9a45e..dbfb8933e42d
--- a/drivers/media/platform/exynos/mfc/regs-mfc-v9.h
+++ b/drivers/media/platform/exynos/mfc/regs-mfc-v9.h
@@ -75,6 +75,7 @@
#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET 13
#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET 14
#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET 15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET 16
#define S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET 20
#define S5P_FIMV_R2H_CMD_ERR_RET 32
@@ -100,7 +101,8 @@ static inline unsigned int h2r_to_r2h_bits(int cmd)
case S5P_FIMV_CH_FRAME_START:
mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FRAME_DONE_RET) |
R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
- R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET));
+ R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
+ R2H_BIT(S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET));
break;
case S5P_FIMV_CH_LAST_FRAME:
mask |= R2H_BIT(S5P_FIMV_R2H_CMD_FRAME_DONE_RET);
@@ -118,7 +120,8 @@ static inline unsigned int r2h_bits(int cmd)
mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
R2H_BIT(S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET) |
R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
- R2H_BIT(S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET));
+ R2H_BIT(S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET) |
+ R2H_BIT(S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET));
/* FIXME: Temporal mask for S3D SEI processing */
else if (cmd == S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET)
mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
@@ -150,6 +153,9 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_RET_INSTANCE_ID 0xF070
#define S5P_FIMV_ERROR_CODE 0xF074
+#define S5P_FIMV_ERR_HEADER_NOT_FOUND 102
+#define S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED 190
+#define S5P_FIMV_ERR_NON_PAIRED_FIELD 191
#define S5P_FIMV_ERR_WARNINGS_START 160
#define S5P_FIMV_ERR_WARNINGS_END 222
#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
@@ -176,6 +182,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT 0
#define S5P_FIMV_D_OPT_DYNAMIC_DPB_SET_SHIFT 3
#define S5P_FIMV_D_OPT_NOT_CODED_SET_SHIFT 4
+#define S5P_FIMV_D_OPT_SPECIAL_PARSING_SHIFT 15
#define S5P_FIMV_D_DISPLAY_DELAY 0xF0B8
@@ -184,6 +191,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_D_SEI_ENABLE 0xF0C4
#define S5P_FIMV_D_SEI_NEED_INIT_BUFFER_SHIFT 1
+#define S5P_FIMV_D_SEI_RECOVERY_PARSING_ENABLE 2
/* Buffer setting registers */
/* Session return */
@@ -367,6 +375,7 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_ENC_PROFILE_H264_MAIN 1
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 2
#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_HIGH 5
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
#define S5P_FIMV_E_FIXED_PICTURE_QP 0xF794
@@ -457,6 +466,9 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_MPEG4_OPTIONS 0xFB10
#define S5P_FIMV_E_MPEG4_HEC_PERIOD 0xFB14
+
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0 0xFB44
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1 0xFB48
#define S5P_FIMV_E_ASPECT_RATIO 0xFB4C
#define S5P_FIMV_E_EXTENDED_SAR 0xFB50
@@ -485,13 +497,10 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5 0xFB9C
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6 0xFBA0
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7 0xFBA4
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
#define S5P_FIMV_E_NUM_T_LAYER 0xFBAC
-/* For backward compatibility */
-#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET 0xFBA8
-#define S5P_FIMV_E_H264_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 0xFBB0
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1 0xFBB4
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2 0xFBB8
@@ -501,24 +510,9 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6 0xFBC8
/* For backward compatibility */
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3 S5P_FIMV_E_HIERARCHICAL_QP_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4 S5P_FIMV_E_HIERARCHICAL_QP_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5 S5P_FIMV_E_HIERARCHICAL_QP_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6 S5P_FIMV_E_HIERARCHICAL_QP_LAYER6
-
#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
#define S5P_FIMV_E_H264_NAL_CONTROL 0xFD14
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER1 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER2 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER3 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER4 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER5 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5
-#define S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER6 S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 0xFD18
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1 0xFD1C
#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2 0xFD20
@@ -538,12 +532,6 @@ static inline unsigned int r2h_bits(int cmd)
#define S5P_FIMV_E_VP8_FILTER_OPTIONS 0xFDB4
#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION 0xFDB8
-/* For backward compatibility */
-#define S5P_FIMV_E_VP8_NUM_T_LAYER S5P_FIMV_E_NUM_T_LAYER
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER0 S5P_FIMV_E_HIERARCHICAL_QP_LAYER0
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER1 S5P_FIMV_E_HIERARCHICAL_QP_LAYER1
-#define S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER2 S5P_FIMV_E_HIERARCHICAL_QP_LAYER2
-
#define S5P_FIMV_E_HEVC_OPTIONS 0xFDD4
#define S5P_FIMV_E_HEVC_REFRESH_PERIOD 0xFDD8
#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET 0xFDDC
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc.c b/drivers/media/platform/exynos/mfc/s5p_mfc.c
old mode 100644
new mode 100755
index 5b07d11ec5b7..3ff3d4c7d0a3
--- a/drivers/media/platform/exynos/mfc/s5p_mfc.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc.c
@@ -160,20 +160,21 @@ int exynos_mfc_sysmmu_fault_handler(struct iommu_domain *iodmn, struct device *d
/*
* A framerate table determines framerate by the interval(us) of each frame.
* Framerate is not accurate, just rough value to seperate overload section.
- * Base line of each section are selected from 25fps(40000us), 45fps(22222us)
- * and 100fps(10000us).
+ * Base line of each section are selected from 40fps(25000us), 80fps(12500us),
+ * 145fps(6940us) and 205fps(4860us).
*
- * interval(us) | 0 10000 22222 40000 |
- * framerate | 120fps | 60fps | 30fps | 25fps |
+ * interval(us) | 0 4860 6940 12500 25000 |
+ * framerate | 240fps | 180fps | 120fps | 60fps | 30fps |
*/
#define COL_FRAME_RATE 0
#define COL_FRAME_INTERVAL 1
static unsigned long framerate_table[][2] = {
- { 25000, 40000 },
- { 30000, 22222 },
- { 60000, 10000 },
- { 120000, 0 },
+ { 30000, 25000 },
+ { 60000, 12500 },
+ { 120000, 6940 },
+ { 180000, 4860 },
+ { 240000, 0 },
};
static inline unsigned long timeval_diff(struct timeval *to,
@@ -280,6 +281,7 @@ int get_framerate_by_timestamp(struct s5p_mfc_ctx *ctx, struct v4l2_buffer *buf)
if (list_empty(&ctx->ts_list)) {
dec_add_timestamp(ctx, buf, &ctx->ts_list);
+ return get_framerate_by_interval(0);
} else {
found = 0;
list_for_each_entry_reverse(temp_ts, &ctx->ts_list, list) {
@@ -324,6 +326,12 @@ int get_framerate_by_timestamp(struct s5p_mfc_ctx *ctx, struct v4l2_buffer *buf)
min_interval, max_framerate);
}
+ if (!ctx->ts_is_full) {
+ if (debug_ts == 1)
+ mfc_info_ctx("ts doesn't full, keep %d fps\n", ctx->framerate);
+ return ctx->framerate;
+ }
+
return max_framerate;
}
@@ -557,10 +565,8 @@ static int s5p_mfc_check_hw_state(struct s5p_mfc_dev *dev)
clk_state = mfc_check_clock_state(dev);
mfc_disp_dev_state(dev);
- if (!pwr_state || !clk_state)
- mfc_err("power or clock state is unstable\n");
-
- s5p_mfc_dump_regs(dev);
+ if (pwr_state && clk_state)
+ s5p_mfc_dump_regs(dev);
return 0;
}
@@ -725,7 +731,7 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
struct s5p_mfc_dev *dev;
struct s5p_mfc_buf *dst_buf;
int index, is_first = 1;
- unsigned int interlace_type, is_interlace = 0;
+ unsigned int interlace_type = 0, is_interlace = 0;
if (!ctx) {
mfc_err("no mfc context to run\n");
@@ -809,7 +815,9 @@ static void mfc_check_ref_frame(struct s5p_mfc_ctx *ctx,
{
struct s5p_mfc_dec *dec = ctx->dec_priv;
struct s5p_mfc_buf *ref_buf, *tmp_buf;
+ struct list_head *dst_list;
int index;
+ int found = 0;
list_for_each_entry_safe(ref_buf, tmp_buf, ref_list, list) {
index = ref_buf->vb.v4l2_buf.index;
@@ -825,9 +833,26 @@ static void mfc_check_ref_frame(struct s5p_mfc_ctx *ctx,
clear_bit(index, &dec->dpb_status);
mfc_debug(2, "Move buffer[%d], fd[%d] to dst queue\n",
index, dec->assigned_fd[index]);
+ found = 1;
break;
}
}
+
+ if (is_h264(ctx) && !found) {
+ dst_list = &ctx->dst_queue;
+ list_for_each_entry_safe(ref_buf, tmp_buf, dst_list, list) {
+ index = ref_buf->vb.v4l2_buf.index;
+ if (index == ref_index && ref_buf->already) {
+ dec->assigned_fd[index] =
+ ref_buf->vb.v4l2_planes[0].m.fd;
+ clear_bit(index, &dec->dpb_status);
+ mfc_debug(2, "re-assigned buffer[%d], fd[%d] for H264\n",
+ index, dec->assigned_fd[index]);
+ found = 1;
+ break;
+ }
+ }
+ }
}
/* Process the released reference information */
@@ -844,11 +869,17 @@ static void mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
if (released_flag) {
for (t = 0; t < MFC_MAX_DPBS; t++) {
if (released_flag & (1 << t)) {
- mfc_debug(2, "Release FD[%d] = %03d !! ",
- t, dec->assigned_fd[t]);
- refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
+ if (dec->err_sync_flag & (1 << t)) {
+ mfc_debug(2, "Released, but reuse. FD[%d] = %03d\n",
+ t, dec->assigned_fd[t]);
+ dec->err_sync_flag &= ~(1 << t);
+ } else {
+ mfc_debug(2, "Release FD[%d] = %03d\n",
+ t, dec->assigned_fd[t]);
+ refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
+ ncount++;
+ }
dec->assigned_fd[t] = MFC_INFO_INIT_FD;
- ncount++;
mfc_check_ref_frame(ctx, dst_queue_addr, t);
}
}
@@ -906,7 +937,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
dma_addr_t dspl_y_addr;
unsigned int index;
unsigned int frame_type;
- unsigned int interlace_type, is_interlace = 0;
+ unsigned int interlace_type = 0, is_interlace = 0;
int mvc_view_id;
unsigned int dst_frame_status, last_frame_status;
struct list_head *dst_queue_addr;
@@ -994,6 +1025,24 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
if (s5p_mfc_mem_plane_addr(ctx, &dst_buf->vb, 0)
== dspl_y_addr) {
index = dst_buf->vb.v4l2_buf.index;
+ if (ctx->codec_mode == S5P_FIMV_CODEC_VC1RCV_DEC &&
+ s5p_mfc_err_dspl(err) == S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED) {
+ if (released_flag & (1 << index)) {
+ list_del(&dst_buf->list);
+ dec->ref_queue_cnt--;
+ list_add_tail(&dst_buf->list, &ctx->dst_queue);
+ ctx->dst_queue_cnt++;
+ dec->dpb_status &= ~(1 << index);
+ released_flag &= ~(1 << index);
+ mfc_debug(2, "SYNC_POINT_NOT_RECEIVED, released.\n");
+ } else {
+ dec->err_sync_flag |= 1 << index;
+ mfc_debug(2, "SYNC_POINT_NOT_RECEIVED, used.\n");
+ }
+ dec->dynamic_used |= released_flag;
+ break;
+ }
+
list_del(&dst_buf->list);
if (dec->is_dynamic_dpb)
@@ -1024,7 +1073,8 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
dst_buf->vb.v4l2_buf.flags &=
~(V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
- V4L2_BUF_FLAG_BFRAME);
+ V4L2_BUF_FLAG_BFRAME |
+ V4L2_BUF_FLAG_ERROR);
switch (frame_type) {
case S5P_FIMV_DISPLAY_FRAME_I:
@@ -1043,9 +1093,12 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
break;
}
- if (s5p_mfc_err_dspl(err))
+ if (s5p_mfc_err_dspl(err)) {
mfc_err_ctx("Warning for displayed frame: %d\n",
s5p_mfc_err_dspl(err));
+ dst_buf->vb.v4l2_buf.flags |=
+ V4L2_BUF_FLAG_ERROR;
+ }
if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
mfc_err_ctx("failed in get_buf_ctrls_val\n");
@@ -1142,19 +1195,6 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
}
}
-static int s5p_mfc_find_start_code(unsigned char *src_mem, unsigned int remainSize)
-{
- unsigned int index = 0;
-
- for (index = 0; index < remainSize - 3; index++) {
- if ((src_mem[index] == 0x00) && (src_mem[index+1] == 0x00) &&
- (src_mem[index+2] == 0x01))
- return index;
- }
-
- return -1;
-}
-
static void s5p_mfc_handle_frame_error(struct s5p_mfc_ctx *ctx,
unsigned int reason, unsigned int err)
{
@@ -1306,6 +1346,52 @@ static void s5p_mfc_handle_ref_frame(struct s5p_mfc_ctx *ctx)
}
}
+static void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
+{
+ struct s5p_mfc_dec *dec = ctx->dec_priv;
+ struct s5p_mfc_buf *ref_mb, *tmp_mb;
+ int index;
+
+ list_for_each_entry_safe(ref_mb, tmp_mb, &dec->ref_queue, list) {
+ index = ref_mb->vb.v4l2_buf.index;
+ if (index == release_index) {
+ ref_mb->used = 0;
+
+ list_del(&ref_mb->list);
+ dec->ref_queue_cnt--;
+
+ list_add_tail(&ref_mb->list, &ctx->dst_queue);
+ ctx->dst_queue_cnt++;
+
+ clear_bit(index, &dec->dpb_status);
+ mfc_debug(2, "buffer[%d] is moved to dst queue for reuse\n", index);
+ }
+ }
+}
+
+static void s5p_mfc_handle_reuse_buffer(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_dec *dec = ctx->dec_priv;
+ unsigned int prev_flag, released_flag = 0;
+ int i;
+
+ if (!dec->is_dynamic_dpb)
+ return;
+
+ prev_flag = dec->dynamic_used;
+ dec->dynamic_used = mfc_get_dec_used_flag();
+ released_flag = prev_flag & (~dec->dynamic_used);
+
+ if (!released_flag)
+ return;
+
+ /* reuse not referenced buf anymore */
+ for (i = 0; i < MFC_MAX_DPBS; i++)
+ if (released_flag & (1 << i))
+ s5p_mfc_move_reuse_buffer(ctx, i);
+}
+
/* Handle frame decoding interrupt */
static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
unsigned int reason, unsigned int err)
@@ -1399,9 +1485,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
/* All frames remaining in the buffer have been extracted */
if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) {
if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
+ struct mfc_timestamp *temp_ts = NULL;
+
mfc_debug(2, "Last frame received after resolution change.\n");
s5p_mfc_handle_frame_all_extracted(ctx);
ctx->state = MFCINST_RES_CHANGE_END;
+
+ /* empty the timestamp queue */
+ while (!list_empty(&ctx->ts_list)) {
+ temp_ts = list_entry((&ctx->ts_list)->next,
+ struct mfc_timestamp, list);
+ list_del(&temp_ts->list);
+ }
+ ctx->ts_count = 0;
+ ctx->ts_is_full = 0;
+ ctx->last_framerate = 0;
+ ctx->framerate = DEC_MAX_FPS;
+
goto leave_handle_frame;
} else {
s5p_mfc_handle_frame_all_extracted(ctx);
@@ -1410,12 +1510,18 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
if (dec->is_dynamic_dpb) {
switch (dst_frame_status) {
- case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
- dec->dynamic_used |= mfc_get_dec_used_flag();
- /* Fall through */
case S5P_FIMV_DEC_STATUS_DECODING_DISPLAY:
s5p_mfc_handle_ref_frame(ctx);
break;
+ case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
+ s5p_mfc_handle_ref_frame(ctx);
+ /*
+ * Some cases can have many decoding only frames like VP9
+ * alt-ref frame. So need handling release buffer
+ * because of DPB full.
+ */
+ s5p_mfc_handle_reuse_buffer(ctx);
+ break;
default:
break;
}
@@ -1444,52 +1550,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
dec->consumed += s5p_mfc_get_consumed_stream();
remained = (unsigned int)(src_buf->vb.v4l2_planes[0].bytesused - dec->consumed);
- if ((prev_offset == 0) && dec->is_packedpb && remained > STUFF_BYTE &&
- dec->consumed < src_buf->vb.v4l2_planes[0].bytesused &&
- s5p_mfc_get_dec_frame_type() ==
- S5P_FIMV_DECODED_FRAME_P) {
- unsigned char *stream_vir;
- int offset = 0;
-
+ if ((dec->consumed > 0) && (remained > STUFF_BYTE) && (err == 0) &&
+ (src_buf->vb.v4l2_planes[0].bytesused > dec->consumed)) {
/* Run MFC again on the same buffer */
mfc_debug(2, "Running again the same buffer.\n");
- if (IS_MFCv7X(dev) && dec->is_dual_dpb)
- dec->y_addr_for_pb = mfc_get_dec_first_addr();
- else
+ if (dec->is_packedpb)
dec->y_addr_for_pb = (dma_addr_t)MFC_GET_ADR(DEC_DECODED_Y);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- stream_vir = vb2_plane_vaddr(&src_buf->vb, 0);
- s5p_mfc_mem_inv_vb(&src_buf->vb, 1);
- spin_lock_irqsave(&dev->irqlock, flags);
-
- if (ctx->codec_mode != S5P_FIMV_CODEC_VP9_DEC) {
- offset = s5p_mfc_find_start_code(
- stream_vir + dec->consumed, remained);
- }
-
- if (offset > STUFF_BYTE)
- dec->consumed += offset;
-
-#if 0
- s5p_mfc_set_dec_stream_buffer(ctx,
- src_buf->planes.stream, dec->consumed,
- src_buf->vb.v4l2_planes[0].bytesused -
- dec->consumed);
- dev->curr_ctx = ctx->num;
- dev->curr_ctx_drm = ctx->is_drm;
- s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_clear_int_flags();
- wake_up_ctx(ctx, reason, err);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- s5p_mfc_decode_one_frame(ctx, 0);
- return;
-#else
dec->remained_size = src_buf->vb.v4l2_planes[0].bytesused -
dec->consumed;
/* Do not move src buffer to done_list */
-#endif
+ } else if (s5p_mfc_err_dec(err) == S5P_FIMV_ERR_NON_PAIRED_FIELD) {
+ /*
+ * For non-paired field, the same buffer need to be
+ * resumitted and the consumed stream will be 0
+ */
+ mfc_debug(2, "Not paired field. Running again the same buffer.\n");
} else {
index = src_buf->vb.v4l2_buf.index;
if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
@@ -1548,32 +1625,50 @@ static inline void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
mfc_err_ctx("Interrupt Error: %d\n", err);
s5p_mfc_clear_int_flags();
- wake_up_dev(dev, reason, err);
/* Error recovery is dependent on the state of context */
switch (ctx->state) {
- case MFCINST_INIT:
- /* This error had to happen while acquireing instance */
+ case MFCINST_RES_CHANGE_END:
case MFCINST_GOT_INST:
- /* This error had to happen while parsing vps only */
+ /* This error had to happen while parsing the header */
if (err == S5P_FIMV_VPS_ONLY_ERROR) {
ctx->state = MFCINST_VPS_PARSED_ONLY;
if (!list_empty(&ctx->src_queue)) {
- src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
- list);
+ src_buf = list_entry(ctx->src_queue.next,
+ struct s5p_mfc_buf, list);
list_del(&src_buf->list);
ctx->src_queue_cnt--;
vb2_buffer_done(&src_buf->vb, VB2_BUF_STATE_DONE);
}
+ } else if (!ctx->is_drm) {
+ unsigned char *stream_vir = NULL;
+ unsigned int strm_size = 0;
+ spin_lock_irqsave(&dev->irqlock, flags);
+ if (!list_empty(&ctx->src_queue)) {
+ src_buf = list_entry(ctx->src_queue.next,
+ struct s5p_mfc_buf, list);
+ stream_vir = src_buf->vir_addr;
+ strm_size = src_buf->vb.v4l2_planes[0].bytesused;
+ if (strm_size > 32)
+ strm_size = 32;
+ }
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ if (stream_vir && strm_size)
+ print_hex_dump(KERN_ERR, "No header: ",
+ DUMP_PREFIX_ADDRESS, strm_size, 4,
+ stream_vir, strm_size, false);
}
- case MFCINST_RES_CHANGE_END:
- /* This error had to happen while parsing the header */
+ case MFCINST_INIT:
+ /* This error had to happen while acquireing instance */
case MFCINST_HEAD_PARSED:
/* This error had to happen while setting dst buffers */
case MFCINST_RETURN_INST:
/* This error had to happen while releasing instance */
case MFCINST_DPB_FLUSHING:
/* This error had to happen while flushing DPB */
+ case MFCINST_SPECIAL_PARSING:
+ case MFCINST_SPECIAL_PARSING_NAL:
+ /* this error had to happen while special parsing */
clear_work_bit(ctx);
if (clear_hw_bit(ctx) == 0)
BUG();
@@ -1611,9 +1706,31 @@ static inline void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
break;
}
+ wake_up_dev(dev, reason, err);
+
return;
}
+static irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv)
+{
+ struct s5p_mfc_dev *dev = priv;
+ struct s5p_mfc_ctx *ctx;
+ unsigned int err;
+ unsigned int reason;
+
+ ctx = dev->ctx[dev->curr_ctx];
+ if (!ctx)
+ mfc_err("no mfc context to run\n");
+
+ reason = s5p_mfc_get_int_reason();
+ err = s5p_mfc_get_int_err();
+ mfc_debug(2, "[c:%d] Int reason: %d (err: %d)\n",
+ dev->curr_ctx, reason, err);
+ MFC_TRACE_DEV("<< Int reason(top): %d\n", reason);
+
+ return IRQ_WAKE_THREAD;
+}
+
/* Interrupt processing */
static irqreturn_t s5p_mfc_irq(int irq, void *priv)
{
@@ -1625,6 +1742,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
unsigned int reason;
unsigned int err;
unsigned long flags;
+ unsigned int reg = 0;
mfc_debug_enter();
@@ -1696,19 +1814,87 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET:
+ case S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET:
if (ctx->type == MFCINST_DECODER) {
+ if (ctx->state == MFCINST_SPECIAL_PARSING_NAL) {
+ s5p_mfc_clear_int_flags();
+ spin_lock_irq(&dev->condlock);
+ clear_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+ ctx->state = MFCINST_RUNNING;
+ if (clear_hw_bit(ctx) == 0)
+ BUG();
+ s5p_mfc_clock_off(dev);
+ wake_up_ctx(ctx, reason, err);
+ goto done;
+ }
s5p_mfc_handle_frame(ctx, reason, err);
} else if (ctx->type == MFCINST_ENCODER) {
if (reason == S5P_FIMV_R2H_CMD_SLICE_DONE_RET) {
dev->preempt_ctx = ctx->num;
+ enc->buf_full = 0;
enc->in_slice = 1;
+ } else if (reason == S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET) {
+ mfc_err_ctx("stream buffer size(%d) isn't enough\n",
+ s5p_mfc_get_enc_strm_size());
+ dev->preempt_ctx = ctx->num;
+ enc->buf_full = 1;
+ enc->in_slice = 0;
} else {
+ enc->buf_full = 0;
enc->in_slice = 0;
}
if (ctx->c_ops->post_frame_start) {
- if (ctx->c_ops->post_frame_start(ctx))
- mfc_err_ctx("post_frame_start() failed\n");
+ if (ctx->enc_res_change || ctx->enc_res_change_state) {
+ /* Right after the first NAL_START finished with the new resolution,
+ * We need to reset the fields
+ */
+ if (ctx->enc_res_change) {
+ reg = s5p_mfc_read_reg(dev, S5P_FIMV_E_PARAM_CHANGE);
+ reg &= ~(0x7 << 6); /* clear resolution change bits */
+ s5p_mfc_write_reg(dev, reg, S5P_FIMV_E_PARAM_CHANGE);
+
+ ctx->enc_res_change_state = ctx->enc_res_change;
+ ctx->enc_res_change = 0;
+ }
+
+ if (ctx->enc_res_change_state == 1) { /* resolution swap */
+ ctx->enc_res_change_state = 0;
+ } else if (ctx->enc_res_change_state == 2) { /* resolution change */
+ reg = s5p_mfc_read_reg(dev, S5P_FIMV_E_NAL_DONE_INFO);
+ reg = (reg & (0x3 << 4)) >> 4;
+
+ mfc_debug(2, "Encoding Resolution Status : %d\n", reg);
+
+ if (reg == 1) { /* Resolution Change for B-frame */
+ /* Encode with previous resolution */
+ /* NOTHING TO-DO */
+ } else if (reg == 2) { /* Resolution Change for B-frame */
+ s5p_mfc_release_codec_buffers(ctx);
+ ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+
+ ctx->enc_res_change_state = 0;
+ ctx->min_scratch_buf_size = s5p_mfc_read_reg(dev, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE);
+ mfc_debug(2, "S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE = 0x%x\n",
+ (unsigned int)ctx->min_scratch_buf_size);
+ } else if (reg == 3) { /* Resolution Change for only P-frame */
+ s5p_mfc_release_codec_buffers(ctx);
+ ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+
+ ctx->enc_res_change_state = 0;
+ ctx->min_scratch_buf_size = s5p_mfc_read_reg(dev, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE);
+ ctx->enc_res_change_re_input = 1;
+ mfc_debug(2, "S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE = 0x%x\n",
+ (unsigned int)ctx->min_scratch_buf_size);
+ }
+ }
+ if (ctx->c_ops->post_frame_start(ctx))
+ mfc_err_ctx("post_frame_start() failed\n");
+ } else {
+ if (ctx->c_ops->post_frame_start(ctx))
+ mfc_err_ctx("post_frame_start() failed\n");
+ }
s5p_mfc_clear_int_flags();
if (clear_hw_bit(ctx) == 0)
@@ -1797,8 +1983,18 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
goto irq_cleanup_hw;
break;
case S5P_FIMV_R2H_CMD_NAL_ABORT_RET:
- ctx->state = MFCINST_ABORT;
- clear_work_bit(ctx);
+ if (ctx->type == MFCINST_ENCODER) {
+ ctx->state = MFCINST_RUNNING_BUF_FULL;
+ enc->buf_full = 0;
+ if (ctx->codec_mode == S5P_FIMV_CODEC_VP8_ENC)
+ mfc_err_ctx("stream buffer size isn't enough\n");
+ if (ctx->c_ops->post_frame_start)
+ if (ctx->c_ops->post_frame_start(ctx))
+ mfc_err_ctx("post_frame_start() failed\n");
+ } else {
+ ctx->state = MFCINST_ABORT;
+ clear_work_bit(ctx);
+ }
if (clear_hw_bit(ctx) == 0)
BUG();
goto irq_cleanup_hw;
@@ -2197,8 +2393,8 @@ static int s5p_mfc_open(struct file *file)
}
}
- mfc_info_ctx("MFC open completed [%d:%d] dev = %p, ctx = %p\n",
- dev->num_drm_inst, dev->num_inst, dev, ctx);
+ mfc_info_ctx("MFC open completed [%d:%d] dev = %p, ctx = %p, version = %d\n",
+ dev->num_drm_inst, dev->num_inst, dev, ctx, MFC_DRIVER_INFO);
mutex_unlock(&dev->mfc_mutex);
return ret;
@@ -2270,19 +2466,14 @@ err_no_device:
return ret;
}
-#define need_to_wait_frame_start(ctx) \
- (((ctx->state == MFCINST_FINISHING) || \
- (ctx->state == MFCINST_RUNNING)) && \
- test_bit(ctx->num, &ctx->dev->hw_lock))
/* Release MFC context */
static int s5p_mfc_release(struct file *file)
{
struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
struct s5p_mfc_dev *dev = NULL;
struct s5p_mfc_enc *enc = NULL;
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
int ret = 0;
-#endif
+
dev = ctx->dev;
if (!dev) {
mfc_err("no mfc device to run\n");
@@ -2294,22 +2485,33 @@ static int s5p_mfc_release(struct file *file)
mfc_info_ctx("MFC driver release is called [%d:%d], is_drm(%d)\n",
dev->num_drm_inst, dev->num_inst, ctx->is_drm);
- if (need_to_wait_frame_start(ctx)) {
- ctx->state = MFCINST_ABORT;
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_stop_bits);
+ clear_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ /* If a H/W operation is in progress, wait for it complete */
+ if (need_to_wait_nal_abort(ctx)) {
if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_FRAME_DONE_RET))
+ S5P_FIMV_R2H_CMD_NAL_ABORT_RET))
s5p_mfc_cleanup_timeout(ctx);
+ } else if (test_bit(ctx->num, &dev->hw_lock)) {
+ ret = wait_event_timeout(ctx->queue,
+ (test_bit(ctx->num, &dev->hw_lock) == 0),
+ msecs_to_jiffies(MFC_INT_TIMEOUT));
+ if (ret == 0)
+ mfc_err_ctx("wait for event failed\n");
}
if (ctx->type == MFCINST_ENCODER) {
enc = ctx->enc_priv;
if (!enc) {
mfc_err_ctx("no mfc encoder to run\n");
- mutex_unlock(&dev->mfc_mutex);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_release;
}
- if (enc->in_slice) {
+ if (enc->in_slice || enc->buf_full) {
ctx->state = MFCINST_ABORT_INST;
spin_lock_irq(&dev->condlock);
set_bit(ctx->num, &dev->ctx_work_bits);
@@ -2320,6 +2522,7 @@ static int s5p_mfc_release(struct file *file)
s5p_mfc_cleanup_timeout(ctx);
enc->in_slice = 0;
+ enc->buf_full = 0;
}
}
@@ -2362,77 +2565,36 @@ static int s5p_mfc_release(struct file *file)
if (!atomic_read(&dev->watchdog_run) &&
(ctx->inst_no != MFC_NO_INSTANCE_SET)) {
/* Wait for hw_lock == 0 for this context */
- wait_event_timeout(ctx->queue,
- (test_bit(ctx->num, &dev->hw_lock) == 0),
+ ret = wait_event_timeout(ctx->queue,
+ (dev->hw_lock == 0),
msecs_to_jiffies(MFC_INT_SHORT_TIMEOUT));
+ if (ret == 0) {
+ mfc_err_ctx("Waiting for hardware to finish timed out\n");
+ ret = -EBUSY;
+ goto err_release;
+ }
+ s5p_mfc_clean_ctx_int_flags(ctx);
ctx->state = MFCINST_RETURN_INST;
spin_lock_irq(&dev->condlock);
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irq(&dev->condlock);
/* To issue the command 'CLOSE_INSTANCE' */
- s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_try_run(dev);
/* Wait until instance is returned or timeout occured */
if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
- dev->curr_ctx_drm = ctx->is_drm;
- set_bit(ctx->num, &dev->hw_lock);
- s5p_mfc_clock_on(dev);
- s5p_mfc_close_inst(ctx);
+ S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET) == 1) {
+ mfc_err_ctx("It was expired to wait for a CLOSE_INSTANCE\n");
if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
- mfc_err_ctx("Abnormal h/w state.\n");
-
- /* cleanup for the next open */
- if (dev->curr_ctx == ctx->num)
- clear_bit(ctx->num, &dev->hw_lock);
- if (ctx->is_drm)
- dev->num_drm_inst--;
- dev->num_inst--;
-
- mfc_info_dev("Failed to release MFC inst[%d:%d]\n",
- dev->num_drm_inst, dev->num_inst);
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
- if (ctx->is_drm && dev->num_drm_inst == 0) {
- ret = s5p_mfc_secmem_isolate_and_protect(0);
- if (ret)
- mfc_err("Failed to unprotect secure memory\n");
- }
-#endif
- if (dev->num_inst == 0) {
- s5p_mfc_deinit_hw(dev);
- del_timer_sync(&dev->watchdog_timer);
-
- flush_workqueue(dev->sched_wq);
-
- s5p_mfc_clock_off(dev);
- mfc_debug(2, "power off\n");
- s5p_mfc_power_off(dev);
-
- s5p_mfc_release_dev_context_buffer(dev);
- dev->drm_fw_status = 0;
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
- if (dev->is_support_smc) {
- s5p_mfc_release_sec_pgtable(dev);
- dev->is_support_smc = 0;
- }
-#endif
- } else {
- s5p_mfc_clock_off(dev);
- }
-
-
- mutex_unlock(&dev->mfc_mutex);
-
- return -EIO;
+ S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
+ mfc_err_ctx("It was once more expired. stop H/W\n");
+ s5p_mfc_check_hw_state(dev);
+ /* Stop */
+ BUG();
}
}
-
ctx->inst_no = MFC_NO_INSTANCE_SET;
}
/* hardware locking scheme */
@@ -2490,6 +2652,11 @@ static int s5p_mfc_release(struct file *file)
enc_cleanup_user_shared_handle(ctx);
kfree(ctx->enc_priv);
}
+
+ spin_lock_irq(&dev->condlock);
+ clear_bit(ctx->num, &dev->ctx_stop_bits);
+ spin_unlock_irq(&dev->condlock);
+
dev->ctx[ctx->num] = 0;
kfree(ctx);
@@ -2499,6 +2666,15 @@ static int s5p_mfc_release(struct file *file)
mutex_unlock(&dev->mfc_mutex);
return 0;
+
+err_release:
+ spin_lock_irq(&dev->condlock);
+ clear_bit(ctx->num, &dev->ctx_stop_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ mutex_unlock(&dev->mfc_mutex);
+
+ return ret;
}
/* Poll */
@@ -2788,8 +2964,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_res_irq;
}
dev->irq = res->start;
- ret = request_threaded_irq(dev->irq, NULL, s5p_mfc_irq, IRQF_ONESHOT, pdev->name,
- dev);
+ ret = request_threaded_irq(dev->irq, s5p_mfc_top_half_irq, s5p_mfc_irq,
+ IRQF_ONESHOT, pdev->name, dev);
if (ret != 0) {
dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
goto err_req_irq;
@@ -3164,8 +3340,6 @@ static int s5p_mfc_suspend(struct device *dev)
{
struct s5p_mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
int ret;
- int i = 0;
- struct s5p_mfc_ctx *ctx = NULL;
if (!m_dev) {
mfc_err("no mfc device to run\n");
@@ -3175,20 +3349,6 @@ static int s5p_mfc_suspend(struct device *dev)
if (m_dev->num_inst == 0)
return 0;
- ctx = m_dev->ctx[m_dev->curr_ctx];
- if (!ctx) {//may be, we got the instance just after release
- for(i = 0; i < MFC_NUM_CONTEXTS; i++)
- {
- ctx = m_dev->ctx[i];
- if(ctx)
- {
- mfc_info_ctx("MFC Find a not null ctx, and the curr_ctx changed to %d\n",i);
- m_dev->curr_ctx = i;
- break;
- }
- }
- }
-
ret = s5p_mfc_sleep(m_dev);
return ret;
@@ -3365,6 +3525,7 @@ static struct platform_driver s5p_mfc_driver = {
.owner = THIS_MODULE,
.pm = &s5p_mfc_pm_ops,
.of_match_table = exynos_mfc_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v5.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd_v6.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h
old mode 100644
new mode 100755
index 38797515a390..78ebff85a12d
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h
@@ -37,6 +37,8 @@
#include <linux/pm_qos.h>
#endif
+#define MFC_DRIVER_INFO 180315
+
#define MFC_MAX_BUFFERS 32
#define MFC_MAX_REF_BUFS 2
#define MFC_FRAME_PLANES 2
@@ -47,15 +49,15 @@
#define MFC_NUM_CONTEXTS 32
#define MFC_MAX_DRM_CTX 2
/* Interrupt timeout */
-#define MFC_INT_TIMEOUT 2000
+#define MFC_INT_TIMEOUT 15000
/* Interrupt short timeout */
-#define MFC_INT_SHORT_TIMEOUT 800
+#define MFC_INT_SHORT_TIMEOUT 3000
/* Busy wait timeout */
#define MFC_BW_TIMEOUT 500
/* Watchdog interval */
#define MFC_WATCHDOG_INTERVAL 1000
/* After how many executions watchdog should assume lock up */
-#define MFC_WATCHDOG_CNT 5
+#define MFC_WATCHDOG_CNT 15
#define MFC_NO_INSTANCE_SET -1
@@ -71,6 +73,7 @@
#define MFC_BASE_MASK ((1 << 17) - 1)
#define FLAG_LAST_FRAME 0x80000000
+#define FLAG_CSD 0x20000000
#define MFC_MAX_INTERVAL (2 * USEC_PER_SEC)
/* Maximum number of temporal layers */
@@ -125,7 +128,7 @@ enum s5p_mfc_inst_state {
MFCINST_INIT = 100,
MFCINST_GOT_INST,
MFCINST_HEAD_PARSED,
- MFCINST_BUFS_SET,
+ MFCINST_RUNNING_BUF_FULL,
MFCINST_RUNNING,
MFCINST_FINISHING,
MFCINST_FINISHED,
@@ -139,6 +142,8 @@ enum s5p_mfc_inst_state {
MFCINST_ABORT_INST,
MFCINST_DPB_FLUSHING,
MFCINST_VPS_PARSED_ONLY,
+ MFCINST_SPECIAL_PARSING,
+ MFCINST_SPECIAL_PARSING_NAL,
};
/**
@@ -182,15 +187,6 @@ enum mfc_buf_usage_type {
MFCBUF_DRM,
};
-enum mfc_buf_process_type {
- MFCBUFPROC_DEFAULT = 0x0,
- MFCBUFPROC_COPY = (1 << 0),
- MFCBUFPROC_SHARE = (1 << 1),
- MFCBUFPROC_META = (1 << 2),
- MFCBUFPROC_ANBSHARE = (1 << 3),
- MFCBUFPROC_ANBSHARE_NV12L = (1 << 4),
-};
-
struct s5p_mfc_ctx;
struct s5p_mfc_extra_buf;
struct s5p_mfc_dev;
@@ -237,6 +233,7 @@ struct s5p_mfc_buf {
int used;
int already;
int consumed;
+ unsigned char *vir_addr;
};
#define vb_to_mfc_buf(x) \
@@ -363,6 +360,7 @@ struct s5p_mfc_dev {
int curr_ctx;
int preempt_ctx;
unsigned long ctx_work_bits;
+ unsigned long ctx_stop_bits;
atomic_t watchdog_cnt;
atomic_t watchdog_run;
@@ -434,6 +432,10 @@ struct s5p_mfc_h264_enc_params {
u8 rc_frame_qp;
u8 rc_min_qp;
u8 rc_max_qp;
+ u8 rc_min_qp_p;
+ u8 rc_max_qp_p;
+ u8 rc_min_qp_b;
+ u8 rc_max_qp_b;
u8 rc_mb_dark;
u8 rc_mb_smooth;
u8 rc_mb_static;
@@ -446,11 +448,12 @@ struct s5p_mfc_h264_enc_params {
u16 ext_sar_height;
u8 open_gop;
u16 open_gop_size;
- u8 hier_qp;
+ u8 hier_qp_enable;
enum v4l2_mpeg_video_h264_hierarchical_coding_type hier_qp_type;
- u8 hier_qp_layer;
- u8 hier_qp_layer_qp[7];
- u32 hier_qp_layer_bit[7];
+ u8 num_hier_layer;
+ u8 hier_ref_type;
+ u8 hier_qp_layer[7];
+ u32 hier_bit_layer[7];
u8 sei_gen_enable;
u8 sei_fp_curr_frame_0;
enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_arrangement_type;
@@ -464,6 +467,11 @@ struct s5p_mfc_h264_enc_params {
u32 aso_slice_order[8];
u32 prepend_sps_pps_to_idr;
+ u8 enable_ltr;
+ u8 num_of_ltr;
+ u32 set_priority;
+ u32 base_priority;
+ u32 vui_enable;
};
/**
@@ -482,6 +490,10 @@ struct s5p_mfc_mpeg4_enc_params {
u8 rc_frame_qp;
u8 rc_min_qp;
u8 rc_max_qp;
+ u8 rc_min_qp_p;
+ u8 rc_max_qp_p;
+ u8 rc_min_qp_b;
+ u8 rc_max_qp_b;
u8 rc_p_frame_qp;
};
@@ -494,19 +506,21 @@ struct s5p_mfc_vp8_enc_params {
u8 vp8_version;
u8 rc_min_qp;
u8 rc_max_qp;
+ u8 rc_min_qp_p;
+ u8 rc_max_qp_p;
u8 rc_frame_qp;
u8 rc_p_frame_qp;
u8 vp8_numberofpartitions;
u8 vp8_filterlevel;
u8 vp8_filtersharpness;
u8 vp8_goldenframesel;
- u8 vp8_gfrefreshperiod;
- u8 hierarchy_qp_enable;
- u8 hier_qp_layer_qp[3];
- u32 hier_qp_layer_bit[3];
+ u16 vp8_gfrefreshperiod;
+ u8 hier_qp_enable;
+ u8 hier_qp_layer[3];
+ u32 hier_bit_layer[3];
u8 num_refs_for_p;
u8 intra_4x4mode_disable;
- u8 num_temporal_layer;
+ u8 num_hier_layer;
};
/**
@@ -519,6 +533,10 @@ struct s5p_mfc_hevc_enc_params {
u32 rc_framerate;
u8 rc_min_qp;
u8 rc_max_qp;
+ u8 rc_min_qp_p;
+ u8 rc_max_qp_p;
+ u8 rc_min_qp_b;
+ u8 rc_max_qp_b;
u8 rc_lcu_dark;
u8 rc_lcu_smooth;
u8 rc_lcu_static;
@@ -529,11 +547,9 @@ struct s5p_mfc_hevc_enc_params {
u8 max_partition_depth;
u8 num_refs_for_p;
u8 refreshtype;
- u8 refreshperiod;
- s8 croma_qp_offset_cr;
- s8 croma_qp_offset_cb;
- s8 lf_beta_offset_div2;
- s8 lf_tc_offset_div2;
+ u16 refreshperiod;
+ s32 lf_beta_offset_div2;
+ s32 lf_tc_offset_div2;
u8 loopfilter_disable;
u8 loopfilter_across;
u8 nal_control_length_filed;
@@ -542,12 +558,13 @@ struct s5p_mfc_hevc_enc_params {
u8 const_intra_period_enable;
u8 lossless_cu_enable;
u8 wavefront_enable;
- u8 longterm_ref_enable;
- u8 hier_qp;
- u8 hier_qp_type;
- u8 hier_qp_layer;
- u8 hier_qp_layer_qp;
- u8 hier_qp_layer_bit;
+ u8 enable_ltr;
+ u8 hier_qp_enable;
+ enum v4l2_mpeg_video_hevc_hierarchical_coding_type hier_qp_type;
+ u8 hier_ref_type;
+ u8 num_hier_layer;
+ u8 hier_qp_layer[7];
+ u32 hier_bit_layer[7];
u8 sign_data_hiding;
u8 general_pb_enable;
u8 temporal_id_enable;
@@ -560,6 +577,7 @@ struct s5p_mfc_hevc_enc_params {
u8 size_of_length_field;
u8 user_ref;
u8 store_ref;
+ u8 prepend_sps_pps_to_idr;
};
/**
@@ -571,9 +589,10 @@ struct s5p_mfc_enc_params {
u32 gop_size;
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
- u16 slice_mb;
+ u32 slice_mb;
u32 slice_bit;
- u16 intra_refresh_mb;
+ u32 slice_mb_row;
+ u32 intra_refresh_mb;
u8 pad;
u8 pad_luma;
u8 pad_cb;
@@ -581,6 +600,8 @@ struct s5p_mfc_enc_params {
u8 rc_frame;
u32 rc_bitrate;
u16 rc_reaction_coeff;
+ u32 config_qp;
+ u32 dynamic_qp;
u8 frame_tag;
u8 num_b_frame; /* H.264/MPEG4 */
@@ -589,6 +610,7 @@ struct s5p_mfc_enc_params {
enum v4l2_mpeg_video_header_mode seq_hdr_mode;
enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
u8 fixed_target_bit;
+ u8 num_hier_max_layer;
u16 rc_frame_delta; /* MFC6.1 Only */
@@ -652,6 +674,7 @@ struct s5p_mfc_buf_ctrl {
int has_new;
int val;
unsigned int old_val; /* only for MFC_CTRL_TYPE_SET */
+ unsigned int old_val2; /* only for MFC_CTRL_TYPE_SET */
unsigned int is_volatile; /* only for MFC_CTRL_TYPE_SET */
unsigned int updated;
unsigned int mode;
@@ -740,7 +763,7 @@ struct s5p_mfc_raw_info {
int plane_size[3];
};
-#define MFC_TIME_INDEX 8
+#define MFC_TIME_INDEX 15
struct mfc_timestamp {
struct list_head list;
struct timeval timestamp;
@@ -805,6 +828,8 @@ struct s5p_mfc_dec {
struct mfc_user_shared_handle sh_handle;
int dynamic_ref_filled;
+
+ unsigned int err_sync_flag;
};
struct s5p_mfc_enc {
@@ -831,6 +856,7 @@ struct s5p_mfc_enc {
unsigned int bits;
} slice_size;
unsigned int in_slice;
+ unsigned int buf_full;
int stored_tag;
struct mfc_user_shared_handle sh_handle;
@@ -872,6 +898,15 @@ struct s5p_mfc_ctx {
int dpb_count;
int buf_stride;
+ int old_img_width;
+ int old_img_height;
+
+ unsigned int enc_drc_flag;
+ int enc_res_change;
+ int enc_res_change_state;
+ int enc_res_change_re_input;
+ size_t min_scratch_buf_size;
+
struct s5p_mfc_raw_info raw_buf;
int mv_size;
@@ -879,10 +914,12 @@ struct s5p_mfc_ctx {
void *port_a_buf;
size_t port_a_phys;
size_t port_a_size;
+ void *port_a_virt;
void *port_b_buf;
size_t port_b_phys;
size_t port_b_size;
+ void *port_b_virt;
enum s5p_mfc_queue_state capture_state;
enum s5p_mfc_queue_state output_state;
@@ -926,16 +963,15 @@ struct s5p_mfc_ctx {
struct list_head qos_list;
#endif
int qos_ratio;
+ int qos_changed;
int framerate;
int last_framerate;
int avg_framerate;
int frame_count;
struct timeval last_timestamp;
- int qp_min_change;
- int qp_max_change;
int is_max_fps;
- int buf_process_type;
+ int use_extra_qos;
struct mfc_timestamp ts_array[MFC_TIME_INDEX];
struct list_head ts_list;
@@ -1054,8 +1090,6 @@ static inline unsigned int mfc_version(struct s5p_mfc_dev *dev)
(dev->fw.date >= 0x121005)) || \
(IS_MFCv5X(dev) && \
(dev->fw.date >= 0x120823)))
-#define FW_HAS_VUI_PARAMS(dev) (IS_MFCV6(dev) && \
- (dev->fw.date >= 0x121214))
#define FW_HAS_ADV_RC_MODE(dev) (IS_MFCV6(dev) && \
(dev->fw.date >= 0x130329))
#define FW_HAS_I_LIMIT_RC_MODE(dev) ((IS_MFCv7X(dev) && \
@@ -1080,12 +1114,19 @@ static inline unsigned int mfc_version(struct s5p_mfc_dev *dev)
#define FW_NEED_SHARED_MEMORY(dev) (IS_MFCv5X(dev) || IS_MFCv6X(dev) || \
IS_MFCv7X(dev) || IS_MFCv78(dev))
+#if 0 /* Do not use last frame info */
#define FW_HAS_LAST_DISP_INFO(dev) (IS_MFCv9X(dev) && \
- (dev->fw.date >= 0x141205))
+ (dev->fw.date >= 0x141205))
+#else
+#define FW_HAS_LAST_DISP_INFO(dev) 0
+#endif
#define FW_HAS_GOP2(dev) (IS_MFCv9X(dev) && \
(dev->fw.date >= 0x150316))
#define FW_HAS_E_MIN_SCRATCH_BUF(dev) IS_MFCv9X(dev)
+#define FW_SUPPORT_SKYPE(dev) IS_MFCv9X(dev) && \
+ (dev->fw.date >= 0x150603)
+
#define HW_LOCK_CLEAR_MASK (0xFFFFFFFF)
#define is_h264(ctx) ((ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) ||\
@@ -1102,15 +1143,30 @@ static inline unsigned int mfc_version(struct s5p_mfc_dev *dev)
#define interlaced_cond(ctx) is_mpeg4vc1(ctx) || is_mpeg2(ctx) || is_h264(ctx)
#define on_res_change(ctx) ((ctx)->state >= MFCINST_RES_CHANGE_INIT && \
(ctx)->state <= MFCINST_RES_CHANGE_END)
+#define need_to_wait_frame_start(ctx) \
+ (((ctx->state == MFCINST_FINISHING) || \
+ (ctx->state == MFCINST_RUNNING)) && \
+ test_bit(ctx->num, &ctx->dev->hw_lock))
+#define need_to_wait_nal_abort(ctx) \
+ (ctx->state == MFCINST_ABORT_INST)
+#define need_to_special_parsing(ctx) \
+ ((ctx->state == MFCINST_GOT_INST) || \
+ (ctx->state == MFCINST_HEAD_PARSED))
+#define need_to_special_parsing_nal(ctx) \
+ ((ctx->state == MFCINST_RUNNING) || \
+ (ctx->state == MFCINST_ABORT))
/* Extra information for Decoder */
#define DEC_SET_DUAL_DPB (1 << 0)
#define DEC_SET_DYNAMIC_DPB (1 << 1)
#define DEC_SET_LAST_FRAME_INFO (1 << 2)
+#define DEC_SET_SKYPE_FLAG (1 << 3)
/* Extra information for Encoder */
#define ENC_SET_RGB_INPUT (1 << 0)
#define ENC_SET_SPARE_SIZE (1 << 1)
#define ENC_SET_TEMP_SVC_CH (1 << 2)
+#define ENC_SET_SKYPE_FLAG (1 << 3)
+#define ENC_SET_QP_BOUND_PB (1 << 5)
#define MFC_QOS_FLAG_NODATA 0xFFFFFFFF
@@ -1129,8 +1185,11 @@ static inline int clear_hw_bit(struct s5p_mfc_ctx *ctx)
struct s5p_mfc_dev *dev = ctx->dev;
int ret = -1;
- if (!atomic_read(&dev->watchdog_run))
+ if (!atomic_read(&dev->watchdog_run)) {
ret = test_and_clear_bit(ctx->num, &dev->hw_lock);
+ /* Reset the timeout watchdog */
+ atomic_set(&dev->watchdog_cnt, 0);
+ }
return ret;
}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c b/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
old mode 100644
new mode 100755
index 53677ca4248d..e3bf79c1e8b5
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
@@ -512,7 +512,8 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
{
struct s5p_mfc_ctx *ctx;
int ret;
- int old_state;
+ int old_state, i;
+ int need_cache_flush = 0;
mfc_debug_enter();
@@ -523,8 +524,25 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
ctx = dev->ctx[dev->curr_ctx];
if (!ctx) {
- mfc_err("no mfc context to run\n");
- return -EINVAL;
+ for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+ if (dev->ctx[i]) {
+ ctx = dev->ctx[i];
+ break;
+ }
+ }
+ if (!ctx) {
+ mfc_err("no mfc context to run\n");
+ return -EINVAL;
+ } else {
+ mfc_info_dev("ctx is changed %d -> %d\n",
+ dev->curr_ctx, ctx->num);
+ dev->curr_ctx = ctx->num;
+ if (dev->curr_ctx_drm != ctx->is_drm) {
+ need_cache_flush = 1;
+ mfc_info_dev("DRM attribute is changed %d->%d\n",
+ dev->curr_ctx_drm, ctx->is_drm);
+ }
+ }
}
old_state = ctx->state;
ctx->state = MFCINST_ABORT;
@@ -545,6 +563,22 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
ctx->state = old_state;
s5p_mfc_clock_on(dev);
s5p_mfc_clean_dev_int_flags(dev);
+
+ if (need_cache_flush) {
+ s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_CACHE_FLUSH, NULL);
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) {
+ mfc_err_ctx("Failed to flush cache\n");
+ ret = -EINVAL;
+ goto err_mfc_sleep;
+ }
+
+ s5p_mfc_init_memctrl(dev, (ctx->is_drm ? MFCBUF_DRM : MFCBUF_NORMAL));
+ s5p_mfc_clock_off(dev);
+
+ dev->curr_ctx_drm = ctx->is_drm;
+ s5p_mfc_clock_on(dev);
+ }
+
ret = s5p_mfc_sleep_cmd(dev);
if (ret) {
mfc_err_dev("Failed to send command to MFC - timeout.\n");
@@ -584,7 +618,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
mfc_err("no mfc device to run\n");
return -EINVAL;
}
- mfc_info_dev("curr_ctx_drm:%d\n", dev->curr_ctx_drm);
+ mfc_info_dev("curr_ctx_drm:%d\n", dev->curr_ctx_drm);
dev->wakeup_status = 1;
/* Set clock source again after wake up */
s5p_mfc_set_clock_parent(dev);
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h b/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h b/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
old mode 100644
new mode 100755
index c41996e6f8ea..fbc065cbc7b9
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
@@ -67,11 +67,4 @@ extern int debug;
__func__, __LINE__, ##args); \
} while (0)
-#define mfc_dbg_ctx(fmt, args...) \
- do { \
- printk(KERN_DEBUG "[d:%d, c:%d] %s:%d: " fmt, \
- ctx->dev->id, ctx->num, \
- __func__, __LINE__, ##args); \
- } while (0)
-
#endif /* S5P_MFC_DEBUG_H_ */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
old mode 100644
new mode 100755
index db53120b7531..c9ea937bdfcd
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
@@ -392,7 +392,7 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "QoS ratio value",
- .minimum = 20,
+ .minimum = 0,
.maximum = 1000,
.step = 10,
.default_value = 100,
@@ -424,15 +424,6 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 0,
},
- {
- .id = V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Set buffer process type",
- .minimum = INT_MIN,
- .maximum = INT_MAX,
- .step = 1,
- .default_value = 0,
- },
};
#define NUM_CTRLS ARRAY_SIZE(controls)
@@ -631,12 +622,21 @@ static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
/* Check whether a context should be run on hardware */
int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx)
{
+ struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_dec *dec = ctx->dec_priv;
mfc_debug(2, "src=%d, dst=%d, ref=%d, state=%d capstat=%d\n",
ctx->src_queue_cnt, ctx->dst_queue_cnt, dec->ref_queue_cnt,
ctx->state, ctx->capture_state);
mfc_debug(2, "wait_state = %d\n", ctx->wait_state);
+ /* Skip ready check temprally */
+ spin_lock_irq(&dev->condlock);
+ if (test_bit(ctx->num, &dev->ctx_stop_bits)) {
+ spin_unlock_irq(&dev->condlock);
+ return 0;
+ }
+ spin_unlock_irq(&dev->condlock);
+
/* Context is to parse header */
if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)
return 1;
@@ -1453,7 +1453,6 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
spin_lock_irq(&dev->condlock);
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irq(&dev->condlock);
- s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_try_run(dev);
/* Wait until instance is returned or timeout occured */
if (s5p_mfc_wait_for_done_ctx(ctx,
@@ -1514,7 +1513,6 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
spin_lock_irq(&dev->condlock);
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irq(&dev->condlock);
- s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_try_run(dev);
if (s5p_mfc_wait_for_done_ctx(ctx,
S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET)) {
@@ -1729,6 +1727,11 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
return -EIO;
}
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+ mfc_err_ctx("multiplanar but length is zero\n");
+ return -EIO;
+ }
+
if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (buf->m.planes[0].bytesused > ctx->vq_src.plane_sizes[0]) {
mfc_err_ctx("data size (%d) must be less than "
@@ -1751,9 +1754,10 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
sizeof(struct timeval));
}
if (ctx->last_framerate != 0 &&
- ctx->last_framerate != ctx->framerate) {
- mfc_debug(2, "fps changed: %d -> %d\n",
- ctx->framerate, ctx->last_framerate);
+ ((ctx->last_framerate != ctx->framerate) || ctx->qos_changed)) {
+ mfc_debug(2, "fps changed: %d -> %d (%s)\n",
+ ctx->framerate, ctx->last_framerate,
+ ctx->use_extra_qos ? "extra" : "normal");
ctx->framerate = ctx->last_framerate;
s5p_mfc_qos_on(ctx);
}
@@ -1788,7 +1792,13 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
} else {
ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+
/* Memcpy from dec->ref_info to shared memory */
+ if (buf->index >= MFC_MAX_DPBS) {
+ mfc_err_ctx("buffer index[%d] range over\n", buf->index);
+ return -EINVAL;
+ }
+
srcBuf = &dec->ref_info[buf->index];
for (ncount = 0; ncount < MFC_MAX_DPBS; ncount++) {
if (srcBuf->dpb[ncount].fd[0] == MFC_INFO_INIT_FD)
@@ -1854,7 +1864,7 @@ static int vidioc_streamoff(struct file *file, void *priv,
} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
ret = vb2_streamoff(&ctx->vq_dst, type);
if (!ret) {
- if (!(ctx->buf_process_type & MFCBUFPROC_COPY))
+ if (!ctx->use_extra_qos)
s5p_mfc_qos_off(ctx);
}
} else {
@@ -1891,6 +1901,8 @@ static int dec_ext_info(struct s5p_mfc_ctx *ctx)
val |= DEC_SET_DYNAMIC_DPB;
if (FW_HAS_LAST_DISP_INFO(dev))
val |= DEC_SET_LAST_FRAME_INFO;
+ if (FW_SUPPORT_SKYPE(dev))
+ val |= DEC_SET_SKYPE_FLAG;
return val;
}
@@ -2001,6 +2013,9 @@ static int get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
ctrl->value = dec_ext_info(ctx);
break;
+ case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+ ctrl->value = MFC_DRIVER_INFO;
+ break;
default:
list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
@@ -2177,8 +2192,16 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
if (ctrl->value > 150)
ctrl->value = 1000;
- mfc_info_ctx("set %d qos_ratio.\n", ctrl->value);
+ if (ctrl->value == 0) {
+ ctrl->value = 100;
+ ctx->use_extra_qos = 1;
+ mfc_info_ctx("QOS_RATIO is 0, use extra qos!\n");
+ } else {
+ ctx->use_extra_qos = 0;
+ mfc_info_ctx("QOS_RATIO is %d, use normal qos!\n", ctrl->value);
+ }
ctx->qos_ratio = ctrl->value;
+ ctx->qos_changed = 1;
break;
case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
if (FW_HAS_DYNAMIC_DPB(dev))
@@ -2193,9 +2216,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return -EINVAL;
}
break;
- case V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE:
- ctx->buf_process_type = ctrl->value;
- break;
default:
list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
@@ -2736,8 +2756,8 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
struct s5p_mfc_ctx *ctx = q->drv_priv;
struct s5p_mfc_dec *dec;
struct s5p_mfc_dev *dev;
- int aborted = 0;
int index = 0;
+ int ret = 0;
int prev_state;
if (!ctx) {
@@ -2755,15 +2775,22 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
return -EINVAL;
}
- if (need_to_wait_frame_start(ctx)) {
- ctx->state = MFCINST_ABORT;
- if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_FRAME_DONE_RET))
- s5p_mfc_cleanup_timeout(ctx);
- if (on_res_change(ctx))
- mfc_debug(2, "stop on res change(state:%d)\n", ctx->state);
- else
- aborted = 1;
+ mfc_info_ctx("dec stop_streaming is called, hw_lock : %d, type : %d\n",
+ test_bit(ctx->num, &dev->hw_lock), q->type);
+ MFC_TRACE_CTX("** DEC streamoff(type:%d)\n", q->type);
+
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_stop_bits);
+ clear_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ /* If a H/W operation is in progress, wait for it complete */
+ if (test_bit(ctx->num, &dev->hw_lock)) {
+ ret = wait_event_timeout(ctx->queue,
+ (test_bit(ctx->num, &dev->hw_lock) == 0),
+ msecs_to_jiffies(MFC_INT_TIMEOUT));
+ if (ret == 0)
+ mfc_err_ctx("wait for event failed\n");
}
spin_lock_irqsave(&dev->irqlock, flags);
@@ -2773,6 +2800,7 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
cleanup_assigned_fd(ctx);
cleanup_ref_queue(ctx);
dec->dynamic_used = 0;
+ dec->err_sync_flag = 0;
}
s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
@@ -2801,7 +2829,44 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
mfc_debug(2, "Decoding can be started now\n");
}
} else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+ while (!list_empty(&ctx->src_queue)) {
+ struct s5p_mfc_buf *src_buf;
+ int csd, condition = 0;
+
+ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ csd = src_buf->vb.v4l2_buf.reserved2 & FLAG_CSD ? 1 : 0;
+
+ if (csd) {
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ if (need_to_special_parsing(ctx)) {
+ ctx->state = MFCINST_SPECIAL_PARSING;
+ condition = S5P_FIMV_R2H_CMD_SEQ_DONE_RET;
+ mfc_info_ctx("try to special parsing! (before NAL_START)\n");
+ } else if (need_to_special_parsing_nal(ctx)) {
+ ctx->state = MFCINST_SPECIAL_PARSING_NAL;
+ condition = S5P_FIMV_R2H_CMD_FRAME_DONE_RET;
+ mfc_info_ctx("try to special parsing! (after NAL_START)\n");
+ } else {
+ mfc_info_ctx("can't parsing CSD!, state = %d\n", ctx->state);
+ }
+ if (condition) {
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+ s5p_mfc_try_run(dev);
+ if (s5p_mfc_wait_for_done_ctx(ctx, condition)) {
+ mfc_err_ctx("special parsing time out\n");
+ s5p_mfc_cleanup_timeout(ctx);
+ }
+ }
+ spin_lock_irqsave(&dev->irqlock, flags);
+ }
+ vb2_set_plane_payload(&src_buf->vb, 0, 0);
+ vb2_buffer_done(&src_buf->vb, VB2_BUF_STATE_ERROR);
+ list_del(&src_buf->list);
+ }
+
INIT_LIST_HEAD(&ctx->src_queue);
ctx->src_queue_cnt = 0;
@@ -2814,13 +2879,30 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
}
}
- if (aborted)
+ if (ctx->state == MFCINST_FINISHING)
ctx->state = MFCINST_RUNNING;
spin_unlock_irqrestore(&dev->irqlock, flags);
if (IS_MFCV6(dev) && q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
need_to_dpb_flush(ctx)) {
+ int ret = 0;
+
+ /* If a H/W operation is in progress, wait for it complete */
+ if (dev->hw_lock) {
+ struct s5p_mfc_ctx *wait_ctx;
+
+ index = find_first_bit(&dev->hw_lock, MFC_NUM_CONTEXTS);
+ wait_ctx = dev->ctx[index];
+ ret = wait_event_interruptible_timeout(wait_ctx->queue,
+ (dev->hw_lock == 0),
+ msecs_to_jiffies(MFC_INT_TIMEOUT));
+ if (ret == 0) {
+ mfc_err_dev("Waiting for hardware to finish timed out\n");
+ return -EIO;
+ }
+ }
+
prev_state = ctx->state;
ctx->state = MFCINST_DPB_FLUSHING;
spin_lock_irq(&dev->condlock);
@@ -2833,6 +2915,23 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
s5p_mfc_cleanup_timeout(ctx);
ctx->state = prev_state;
}
+
+ spin_lock_irq(&dev->condlock);
+ clear_bit(ctx->num, &dev->ctx_stop_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ mfc_debug(2, "buffer cleanup & flush is done in stop_streaming, type : %d\n", q->type);
+
+ if (s5p_mfc_dec_ctx_ready(ctx)) {
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+ }
+ spin_lock_irq(&dev->condlock);
+ if (dev->ctx_work_bits)
+ queue_work(dev->sched_wq, &dev->sched_work);
+ spin_unlock_irq(&dev->condlock);
+
return 0;
}
@@ -2868,6 +2967,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
int remove_flag = 0;
int index;
int skip_add = 0;
+ unsigned char *stream_vir = NULL;
mfc_debug_enter();
if (!ctx) {
@@ -2892,9 +2992,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
mfc_debug(2, "Adding to src: %p (0x%08lx, 0x%08lx)\n", vb,
(unsigned long)s5p_mfc_mem_plane_addr(ctx, vb, 0),
(unsigned long)buf->planes.stream);
+ if (ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm) {
+ stream_vir = vb2_plane_vaddr(vb, 0);
+ s5p_mfc_mem_inv_vb(vb, 1);
+ }
spin_lock_irqsave(&dev->irqlock, flags);
list_add_tail(&buf->list, &ctx->src_queue);
ctx->src_queue_cnt++;
+ buf->vir_addr = stream_vir;
spin_unlock_irqrestore(&dev->irqlock, flags);
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
buf->used = 0;
@@ -3052,6 +3157,7 @@ int s5p_mfc_init_dec_ctx(struct s5p_mfc_ctx *ctx)
dec->is_dts_mode = 0;
dec->is_dual_dpb = 0;
dec->tiled_buf_cnt = 0;
+ dec->err_sync_flag = 0;
dec->is_dynamic_dpb = 0;
dec->dynamic_used = 0;
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
old mode 100644
new mode 100755
index 584b2a4117fb..14b436624e92
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
@@ -15,7 +15,7 @@
#define MAX_FRAME_SIZE (2*1024*1024)
#define DEFAULT_TAG (0xE05)
-#define DEC_MAX_FPS (60000)
+#define DEC_MAX_FPS (240000)
const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
int s5p_mfc_init_dec_ctx(struct s5p_mfc_ctx *ctx);
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
old mode 100644
new mode 100755
index 72172a419903..145c32b74284
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
@@ -198,7 +198,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "The slice partitioning method",
.minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
- .maximum = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES,
+ .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW,
.step = 1,
.default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
},
@@ -207,7 +207,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "The number of MB in a slice",
.minimum = 1,
- .maximum = ENC_MULTI_SLICE_MB_MAX,
+ .maximum = INT_MAX,
.step = 1,
.default_value = 1,
},
@@ -215,17 +215,26 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "The maximum bits per slices",
- .minimum = ENC_MULTI_SLICE_BYTE_MIN,
- .maximum = (1 << 30) - 1,
+ .minimum = 350,
+ .maximum = INT_MAX / 8,
+ .step = 1,
+ .default_value = 350,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "The number of MB row in a slice",
+ .minimum = 1,
+ .maximum = INT_MAX / 256,
.step = 1,
- .default_value = ENC_MULTI_SLICE_BYTE_MIN,
+ .default_value = 1,
},
{
.id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "The number of intra refresh MBs",
.minimum = 0,
- .maximum = ENC_INTRA_REFRESH_MB_MAX,
+ .maximum = (1 << 18) - 1,
.step = 1,
.default_value = 0,
},
@@ -243,7 +252,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Padding Color YUV Value",
.minimum = 0,
- .maximum = (1 << 25) - 1,
+ .maximum = (1 << 24) - 1,
.step = 1,
.default_value = 0,
},
@@ -261,7 +270,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Target bit rate rate-control",
.minimum = 1,
- .maximum = (1 << 30) - 1,
+ .maximum = INT_MAX,
.step = 1,
.default_value = 1,
},
@@ -279,7 +288,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Encoded stream size",
.minimum = 0,
- .maximum = (1 << 30) - 1,
+ .maximum = INT_MAX,
.step = 1,
.default_value = 0,
.flags = V4L2_CTRL_FLAG_READ_ONLY,
@@ -289,7 +298,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Encoded frame count",
.minimum = 0,
- .maximum = (1 << 30) - 1,
+ .maximum = INT_MAX,
.step = 1,
.default_value = 0,
.flags = V4L2_CTRL_FLAG_READ_ONLY,
@@ -319,7 +328,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "VBV buffer size (1Kbits)",
.minimum = 0,
- .maximum = ENC_VBV_BUF_SIZE_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0,
},
@@ -373,7 +382,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "H264 profile",
.minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
- .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
.step = 1,
.default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
},
@@ -408,8 +417,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "H264 loop filter alpha offset",
- .minimum = ENC_H264_LOOP_FILTER_AB_MIN,
- .maximum = ENC_H264_LOOP_FILTER_AB_MAX,
+ .minimum = -12,
+ .maximum = 12,
.step = 1,
.default_value = 0,
},
@@ -417,8 +426,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "H264 loop filter beta offset",
- .minimum = ENC_H264_LOOP_FILTER_AB_MIN,
- .maximum = ENC_H264_LOOP_FILTER_AB_MAX,
+ .minimum = -12,
+ .maximum = 12,
.step = 1,
.default_value = 0,
},
@@ -463,7 +472,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "H264 Frame rate",
.minimum = 1,
- .maximum = ENC_H264_RC_FRAME_RATE_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 1,
},
@@ -476,25 +485,6 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 0,
},
- {
- .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "H264 Minimum QP value",
- .minimum = 0,
- .maximum = 51,
- .step = 1,
- .default_value = 0,
- },
- {
- /* MAX_QP must be greater than or equal to MIN_QP */
- .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "H264 Maximum QP value",
- .minimum = 0,
- .maximum = 51,
- .step = 1,
- .default_value = 0,
- },
{
.id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -619,7 +609,7 @@ static struct v4l2_queryctrl controls[] = {
.minimum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
.maximum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
.step = 1,
- .default_value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
+ .default_value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
@@ -775,24 +765,6 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 1,
},
- {
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "MPEG4 Minimum QP value",
- .minimum = 1,
- .maximum = 31,
- .step = 1,
- .default_value = 1,
- },
- {
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "MPEG4 Maximum QP value",
- .minimum = 1,
- .maximum = 31,
- .step = 1,
- .default_value = 1,
- },
{ /* MFC5.x Only */
.id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -825,7 +797,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "MPEG4 vop time resolution",
.minimum = 0,
- .maximum = ENC_MPEG4_VOP_TIME_RES_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0,
},
@@ -843,7 +815,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "H263 Frame rate",
.minimum = 1,
- .maximum = ENC_H263_RC_FRAME_RATE_MAX,
+ .maximum = (1 << 8) - 1,
.step = 1,
.default_value = 1,
},
@@ -856,24 +828,6 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 1,
},
- {
- .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "H263 Minimum QP value",
- .minimum = 1,
- .maximum = 31,
- .step = 1,
- .default_value = 1,
- },
- {
- .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "H263 Maximum QP value",
- .minimum = 1,
- .maximum = 31,
- .step = 1,
- .default_value = 1,
- },
{
.id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -905,8 +859,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "QoS ratio value",
- .minimum = 20,
- .maximum = 200,
+ .minimum = 0,
+ .maximum = 1000,
.step = 10,
.default_value = 100,
},
@@ -937,30 +891,12 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 0,
},
- {
- .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "VP8 Frame QP MAX value",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 0,
- },
- {
- .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "VP8 Frame QP MIN value",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 0,
- },
{
.id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "VP8 Frame rate",
.minimum = 1,
- .maximum = ENC_H264_RC_FRAME_RATE_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0,
},
@@ -1005,7 +941,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "VP8 indication of golden frame",
.minimum = 0,
- .maximum = ((1 << 16) - 1),
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0,
},
@@ -1099,26 +1035,6 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 0,
},
-
- {
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "HEVC Minimum QP value",
- .minimum = 0,
- .maximum = 51,
- .step = 1,
- .default_value = 0,
- },
- {
- /* MAX_QP must be greater than or equal to MIN_QP */
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "HEVC Maximum QP value",
- .minimum = 0,
- .maximum = 51,
- .step = 1,
- .default_value = 0,
- },
{
.id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -1187,7 +1103,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "HEVC Frame rate",
.minimum = 1,
- .maximum = ENC_HEVC_RC_FRAME_RATE_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0,
},
@@ -1285,8 +1201,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Hierarchical Coding Type",
- .minimum = 0,
- .maximum = 1,
+ .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+ .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
.step = 1,
.default_value = 0, /* need to check defualt value */
},
@@ -1309,13 +1225,76 @@ static struct v4l2_queryctrl controls[] = {
.default_value = 0, /* need to check defualt value */
},
{
- .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Hierarchical Coding Layer BIT",
+ .name = "Hierarchical Coding Layer BIT0",
.minimum = INT_MIN,
.maximum = INT_MAX,
.step = 1,
- .default_value = 0, /* need to check defualt value */
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT1",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT2",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT3",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT4",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT5",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT6",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer Change",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
},
{
.id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING,
@@ -1394,25 +1373,7 @@ static struct v4l2_queryctrl controls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "HEVC Number of reference picture",
.minimum = 0,
- .maximum = 10, /* need to check maximum size */
- .step = 1,
- .default_value = 0, /* need to check defualt value */
- },
- {
- .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CR,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Chroma QP index offset Cr",
- .minimum = ENC_HEVC_QP_INDEX_MIN,
- .maximum = ENC_HEVC_QP_INDEX_MAX,
- .step = 1,
- .default_value = 0, /* need to check defualt value */
- },
- {
- .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CB,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Chroma QP index offset Cb",
- .minimum = ENC_HEVC_QP_INDEX_MIN,
- .maximum = ENC_HEVC_QP_INDEX_MAX,
+ .maximum = (1 << 16) - 1,
.step = 1,
.default_value = 0, /* need to check defualt value */
},
@@ -1420,8 +1381,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "HEVC loop filter beta offset",
- .minimum = ENC_HEVC_LOOP_FILTER_MIN,
- .maximum = ENC_HEVC_LOOP_FILTER_MAX,
+ .minimum = -6,
+ .maximum = 6,
.step = 1,
.default_value = 0, /* need to check defualt value */
},
@@ -1429,8 +1390,8 @@ static struct v4l2_queryctrl controls[] = {
.id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "HEVC loop filter tc offset",
- .minimum = ENC_HEVC_LOOP_FILTER_MIN,
- .maximum = ENC_HEVC_LOOP_FILTER_MAX,
+ .minimum = -6,
+ .maximum = 6,
.step = 1,
.default_value = 0, /* need to check defualt value */
},
@@ -1596,90 +1557,422 @@ static struct v4l2_queryctrl controls[] = {
.step = 1,
.default_value = 0,
},
-};
-
-#define NUM_CTRLS ARRAY_SIZE(controls)
-
-static struct v4l2_queryctrl *get_ctrl(int id)
-{
- unsigned long i;
-
- for (i = 0; i < NUM_CTRLS; ++i)
- if (id == controls[i].id)
- return &controls[i];
- return NULL;
-}
-
-static int check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct v4l2_queryctrl *c;
-
- c = get_ctrl(ctrl->id);
- if (!c)
- return -EINVAL;
- if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
- && ctrl->value > c->maximum) {
- mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
- ctrl->value, c->maximum);
- ctrl->value = c->maximum;
- }
-
- if (ctrl->value < c->minimum || ctrl->value > c->maximum
- || (c->step != 0 && ctrl->value % c->step != 0)) {
- v4l2_err(&dev->v4l2_dev, "Invalid control value\n");
- return -ERANGE;
- }
- if (!FW_HAS_ENC_SPSPPS_CTRL(dev) && ctrl->id == \
- V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR) {
- mfc_err_ctx("Not support feature(0x%x) for F/W\n", ctrl->id);
- return -ERANGE;
- }
-
- return 0;
-}
-
-static int enc_ctrl_read_cst(struct s5p_mfc_ctx *ctx,
- struct s5p_mfc_buf_ctrl *buf_ctrl)
-{
- int ret;
- struct s5p_mfc_enc *enc = ctx->enc_priv;
-
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
- ret = !enc->in_slice;
- break;
- default:
- mfc_err_ctx("not support custom per-buffer control\n");
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
- { /* set frame tag */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_SHARED_SET_E_FRAME_TAG,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_ENABLE_LTR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Enable LTR",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
},
- { /* get frame tag */
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_SHARED_GET_E_FRAME_TAG,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Number of LTR",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Set the frame as a LTRP",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Specify a LTRP for encoding",
+ .minimum = 0,
+ .maximum = 0xF,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Base Layer Priority",
+ .minimum = 0,
+ .maximum = (1 << 6) - 1 - 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "QP control per each frame",
+ .minimum = 0,
+ .maximum = (1 << 7) - 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 vui generation enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Prepend SPS/PPS to every IDR",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "set dynamic qp control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Min QP value for I frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Max QP value for I frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Min QP value for I frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Max QP value for I frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Min QP value for I frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Max QP value for I frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H263 Min QP value for I frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H263 Max QP value for I frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "VP8 Min QP value for I frame",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "VP8 Max QP value for I frame",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Min QP value for P frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Max QP value for P frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Min QP value for P frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Max QP value for P frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Min QP value for P frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Max QP value for P frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H263 Min QP value for P frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H263 Max QP value for P frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "VP8 Min QP value for P frame",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "VP8 Max QP value for P frame",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Min QP value for B frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "H264 Max QP value for B frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Min QP value for B frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Max QP value for B frame",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Min QP value for B frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "MPEG4 Max QP value for B frame",
+ .minimum = 1,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding max layer",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+
+static struct v4l2_queryctrl *get_ctrl(int id)
+{
+ unsigned long i;
+
+ for (i = 0; i < NUM_CTRLS; ++i)
+ if (id == controls[i].id)
+ return &controls[i];
+ return NULL;
+}
+
+static int check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct v4l2_queryctrl *c;
+
+ c = get_ctrl(ctrl->id);
+ if (!c)
+ return -EINVAL;
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
+ && ctrl->value > c->maximum) {
+ mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
+ ctrl->value, c->maximum);
+ ctrl->value = c->maximum;
+ }
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER) {
+ if ((ctrl->value & ~(1 << 16)) < c->minimum || (ctrl->value & ~(1 << 16)) > c->maximum
+ || (c->step != 0 && (ctrl->value & ~(1 << 16)) % c->step != 0)) {
+ v4l2_err(&dev->v4l2_dev, "Invalid control value\n");
+ return -ERANGE;
+ } else {
+ return 0;
+ }
+ }
+ if (ctrl->value < c->minimum || ctrl->value > c->maximum
+ || (c->step != 0 && ctrl->value % c->step != 0)) {
+ v4l2_err(&dev->v4l2_dev, "Invalid control value\n");
+ return -ERANGE;
+ }
+ if (!FW_HAS_ENC_SPSPPS_CTRL(dev) && ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR) {
+ mfc_err_ctx("Not support feature(0x%x) for F/W\n", ctrl->id);
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+static int enc_ctrl_read_cst(struct s5p_mfc_ctx *ctx,
+ struct s5p_mfc_buf_ctrl *buf_ctrl)
+{
+ int ret;
+ struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+ ret = !enc->in_slice;
+ break;
+ default:
+ mfc_err_ctx("not support custom per-buffer control\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
+ { /* set frame tag */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_SHARED_SET_E_FRAME_TAG,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* get frame tag */
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_SHARED_GET_E_FRAME_TAG,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
.flag_addr = 0,
.flag_shft = 0,
},
@@ -1769,149 +2062,426 @@ static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
.read_cst = enc_ctrl_read_cst,
.write_cst = NULL,
},
- { /* H.264 QP Max change */
+ { /* H.264 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* H.264 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* H.263 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* H.263 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* VP8 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* VP8 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* HEVC I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* HEVC I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .flag_shft = 4,
+ },
+ { /* H.264 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 B frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 B frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 B frame QP Max change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
.flag_shft = 4,
},
- { /* H.264 QP Min change */
+ { /* MPEG4 B frame QP Min change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
.flag_shft = 4,
},
- { /* H.263 QP Max change */
+ { /* HEVC B frame QP Max change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
.flag_shft = 4,
},
- { /* H.263 QP Min change */
+ { /* HEVC B frame QP Min change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+ .mask = 0x7F,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
.flag_shft = 4,
},
- { /* MPEG4 QP Max change */
+
+ { /* H.264 Dynamic Temporal Layer & bitrate change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+ .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
.is_volatile = 1,
.mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
.mask = 0xFFFFFFFF,
.shft = 0,
.flag_mode = MFC_CTRL_MODE_CUSTOM,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .flag_shft = 10,
},
- { /* MPEG4 QP Min change */
+ { /* HEVC Dynamic Temporal Layer & bitrate change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
.is_volatile = 1,
.mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
.mask = 0xFFFFFFFF,
.shft = 0,
.flag_mode = MFC_CTRL_MODE_CUSTOM,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .flag_shft = 10,
},
- { /* VP8 QP Max change */
+ { /* VP8 Dynamic Temporal Layer change */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
.is_volatile = 1,
.mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
+ .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
.mask = 0xFFFFFFFF,
.shft = 0,
.flag_mode = MFC_CTRL_MODE_CUSTOM,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .flag_shft = 10,
},
- { /* VP8 QP Min change */
+ { /* set level */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+ .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
.is_volatile = 1,
.mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .addr = S5P_FIMV_E_PICTURE_PROFILE,
+ .mask = 0x000000FF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .flag_shft = 5,
},
- { /* H.264 Dynamic Temporal Layer change */
+ { /* set profile */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
+ .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
.is_volatile = 1,
.mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
+ .addr = S5P_FIMV_E_PICTURE_PROFILE,
+ .mask = 0x0000000F,
.shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_mode = MFC_CTRL_MODE_SFR,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 10,
+ .flag_shft = 5,
},
- { /* HEVC QP Max change */
+ { /* set store LTR */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_H264_NAL_CONTROL,
+ .mask = 0x00000003,
.shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
},
- { /* HEVC QP Min change */
+ { /* set use LTR */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_NEW_RC_QP_BOUND,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
- .flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 4,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_H264_NAL_CONTROL,
+ .mask = 0x00000003,
+ .shft = 2,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
},
- { /* VP8 Dynamic Temporal Layer change */
+ { /* set base layer priority */
.type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
+ .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
.is_volatile = 1,
- .mode = MFC_CTRL_MODE_CUSTOM,
- .addr = S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_H264_HD_SVC_EXTENSION_0,
+ .mask = 0x0000003F,
.shft = 0,
- .flag_mode = MFC_CTRL_MODE_CUSTOM,
+ .flag_mode = MFC_CTRL_MODE_SFR,
.flag_addr = S5P_FIMV_PARAM_CHANGE_FLAG,
- .flag_shft = 10,
+ .flag_shft = 12,
+ },
+ { /* set QP per each frame */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = S5P_FIMV_E_FIXED_PICTURE_QP,
+ .mask = 0x0000007F,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
},
};
@@ -1919,12 +2489,21 @@ static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
{
+ struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_enc *enc = ctx->enc_priv;
struct s5p_mfc_enc_params *p = &enc->params;
mfc_debug(2, "src=%d, dst=%d, state=%d\n",
ctx->src_queue_cnt, ctx->dst_queue_cnt, ctx->state);
+ /* Skip ready check temporally */
+ spin_lock_irq(&dev->condlock);
+ if (test_bit(ctx->num, &dev->ctx_stop_bits)) {
+ spin_unlock_irq(&dev->condlock);
+ return 0;
+ }
+ spin_unlock_irq(&dev->condlock);
+
/* context is ready to make header */
if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1) {
if (p->seq_hdr_mode == \
@@ -1946,6 +2525,10 @@ int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
if (ctx->state == MFCINST_RUNNING_NO_OUTPUT &&
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
return 1;
+ /* context is ready to encode a frame for NAL_ABORT command */
+ if (ctx->state == MFCINST_ABORT_INST &&
+ ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
+ return 1;
/* context is ready to encode remain frames */
if (ctx->state == MFCINST_FINISHING &&
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
@@ -1956,6 +2539,40 @@ int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
return 0;
}
+static inline int h264_profile(struct s5p_mfc_ctx *ctx, enum v4l2_mpeg_video_h264_profile profile)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int ret = 0;
+
+ switch (profile) {
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+ ret = S5P_FIMV_ENC_PROFILE_H264_MAIN;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+ ret = S5P_FIMV_ENC_PROFILE_H264_HIGH;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+ ret =S5P_FIMV_ENC_PROFILE_H264_BASELINE;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+ if (IS_MFCV6(dev))
+ ret = S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+ else
+ ret = -EINVAL;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
+ if (IS_MFCV6(dev))
+ ret = S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_HIGH;
+ else
+ ret = -EINVAL;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int enc_cleanup_ctx_ctrls(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_ctx_ctrl *ctx_ctrl;
@@ -2265,9 +2882,10 @@ static int enc_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head
struct s5p_mfc_buf_ctrl *buf_ctrl;
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_enc *enc = ctx->enc_priv;
- unsigned int value = 0;
+ unsigned int value = 0, value2 = 0;
struct temporal_layer_info temporal_LC;
unsigned int i;
+ struct s5p_mfc_enc_params *p = &enc->params;
list_for_each_entry(buf_ctrl, head, list) {
if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
@@ -2312,44 +2930,91 @@ static int enc_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head
if (buf_ctrl->id
== V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) {
+ == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
memcpy(&temporal_LC,
enc->sh_handle.virt, sizeof(struct temporal_layer_info));
- if((temporal_LC.temporal_layer_count < 1) ||
- ((temporal_LC.temporal_layer_count > 7) &&
- (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)) ||
+ if(((temporal_LC.temporal_layer_count & 0x7) < 1) ||
((temporal_LC.temporal_layer_count > 3) &&
(ctx->codec_mode == S5P_FIMV_CODEC_VP8_ENC))) {
+ /* claer NUM_T_LAYER_CHANGE */
value = s5p_mfc_read_reg(dev, buf_ctrl->flag_addr);
value &= ~(1 << 10);
s5p_mfc_write_reg(dev, value, buf_ctrl->flag_addr);
- mfc_err_ctx("temporal layer count is invalid : %d\n"
- , temporal_LC.temporal_layer_count);
+ mfc_err_ctx("Temporal SVC: layer count is invalid : %d\n",
+ temporal_LC.temporal_layer_count);
goto invalid_layer_count;
}
- value = s5p_mfc_read_reg(dev, buf_ctrl->flag_addr);
+ if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+ p->codec.h264.num_hier_layer = temporal_LC.temporal_layer_count & 0x7;
+
/* enable RC_BIT_RATE_CHANGE */
- value |= (1 << 2);
+ value = s5p_mfc_read_reg(dev, buf_ctrl->flag_addr);
+ if (temporal_LC.temporal_layer_bitrate[0] > 0)
+ /* set RC_BIT_RATE_CHANGE */
+ value |= (1 << 2);
+ else
+ /* claer RC_BIT_RATE_CHANGE */
+ value &= ~(1 << 2);
s5p_mfc_write_reg(dev, value, buf_ctrl->flag_addr);
- mfc_debug(2, "temporal layer count : %d\n", temporal_LC.temporal_layer_count);
- if(ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
- s5p_mfc_write_reg(dev,
- temporal_LC.temporal_layer_count, S5P_FIMV_E_H264_NUM_T_LAYER);
- else if(ctx->codec_mode == S5P_FIMV_CODEC_VP8_ENC)
- s5p_mfc_write_reg(dev,
- temporal_LC.temporal_layer_count, S5P_FIMV_E_VP8_NUM_T_LAYER);
- for(i = 0; i < temporal_LC.temporal_layer_count; i++) {
- mfc_debug(2, "temporal layer bitrate[%d] : %d\n",
+ mfc_debug(3, "Temporal SVC: layer count %d, E_PARAM_CHANGE %#x\n",
+ temporal_LC.temporal_layer_count & 0x7, value);
+
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_NUM_T_LAYER);
+ buf_ctrl->old_val2 = value;
+ value &= ~(0x7);
+ value |= (temporal_LC.temporal_layer_count & 0x7);
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_NUM_T_LAYER);
+ mfc_debug(3, "Temporal SVC: E_NUM_T_LAYER %#x\n", value);
+ for(i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+ mfc_debug(3, "Temporal SVC: layer bitrate[%d] %d\n",
i, temporal_LC.temporal_layer_bitrate[i]);
s5p_mfc_write_reg(dev,
temporal_LC.temporal_layer_bitrate[i], buf_ctrl->addr + i * 4);
}
+
+ /* priority change */
+ if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
+ value = 0;
+ value2 = 0;
+ for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+ if (i <= 4)
+ value |= ((p->codec.h264.base_priority & 0x3F) + i) << (6 * i);
+ else
+ value2 |= ((p->codec.h264.base_priority & 0x3F) + i) << (6 * (i - 5));
+ }
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+ s5p_mfc_write_reg(dev, value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+ mfc_debug(3, "Temporal SVC: EXTENSION0 %#x, EXTENSION1 %#x\n",
+ value, value2);
+
+ value = s5p_mfc_read_reg(dev, buf_ctrl->flag_addr);
+ value |= (1 << 12);
+ s5p_mfc_write_reg(dev, value, buf_ctrl->flag_addr);
+ mfc_debug(3, "Temporal SVC: E_PARAM_CHANGE %#x\n", value);
+ }
}
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_NAL_CONTROL);
+ buf_ctrl->old_val2 = (value >> 8) & 0x7;
+ value &= ~(0x7 << 8);
+ value |= (buf_ctrl->val & 0x7) << 8;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_NAL_CONTROL);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_NAL_CONTROL);
+ buf_ctrl->old_val2 = (value >> 11) & 0xF;
+ value &= ~(0xF << 11);
+ value |= (buf_ctrl->val & 0xF) << 11;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_NAL_CONTROL);
+ }
+
if ((buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) && FW_HAS_GOP2(dev)) {
- value = 0;
value = s5p_mfc_read_reg(dev, S5P_FIMV_E_GOP_CONFIG2);
buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
value &= ~(0x3FFF);
@@ -2357,12 +3022,61 @@ static int enc_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head
s5p_mfc_write_reg(dev, value, S5P_FIMV_E_GOP_CONFIG2);
}
+ /* PROFILE & LEVEL have to be set up together */
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_PICTURE_PROFILE);
+ buf_ctrl->old_val |= (value & 0x000F) << 8;
+ value &= ~(0x000F);
+ value |= p->codec.h264.profile & 0x000F;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_PICTURE_PROFILE);
+ p->codec.h264.level = buf_ctrl->val;
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_PICTURE_PROFILE);
+ buf_ctrl->old_val |= value & 0xFF00;
+ value &= ~(0x00FF << 8);
+ value |= (p->codec.h264.level << 8) & 0xFF00;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_PICTURE_PROFILE);
+ p->codec.h264.profile = buf_ctrl->val;
+ }
+
+ /* temproral layer priority */
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+ buf_ctrl->old_val |= value & 0x3FFFFFC0;
+ value &= ~(0x3FFFFFC0);
+ value2 = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+ buf_ctrl->old_val2 = value2 & 0x0FFF;
+ value2 &= ~(0x0FFF);
+ for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+ if (i <= 4)
+ value |= ((buf_ctrl->val & 0x3F) + i) << (6 * i);
+ else
+ value2 |= ((buf_ctrl->val & 0x3F) + i) << (6 * (i - 5));
+ }
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+ s5p_mfc_write_reg(dev, value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+ p->codec.h264.base_priority = buf_ctrl->val;
+ mfc_debug(3, "Temporal SVC: EXTENSION0 %#x, EXTENSION1 %#x\n",
+ value, value2);
+ }
+ /* per buffer QP setting change */
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
+ p->config_qp = buf_ctrl->val;
+
invalid_layer_count:
mfc_debug(8, "Set buffer control "\
"id: 0x%08x val: %d\n",
buf_ctrl->id, buf_ctrl->val);
}
+ if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_FIXED_PICTURE_QP);
+ value &= ~(0xFF000000);
+ value |= (p->config_qp & 0xFF) << 24;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_FIXED_PICTURE_QP);
+ }
+
return 0;
}
@@ -2438,12 +3152,51 @@ static int enc_recover_buf_ctrls_val(struct s5p_mfc_ctx *ctx,
"id: 0x%08x old val: %d\n",
buf_ctrl->id, buf_ctrl->old_val);
if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH && FW_HAS_GOP2(dev)) {
- value = 0;
value = s5p_mfc_read_reg(dev, S5P_FIMV_E_GOP_CONFIG2);
value &= ~(0x3FFF);
value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
s5p_mfc_write_reg(dev, value, S5P_FIMV_E_GOP_CONFIG2);
}
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_PICTURE_PROFILE);
+ value &= ~(0x000F);
+ value |= (buf_ctrl->old_val >> 8) & 0x000F;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_PICTURE_PROFILE);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_PICTURE_PROFILE);
+ value &= ~(0xFF00);
+ value |= buf_ctrl->old_val & 0xFF00;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_PICTURE_PROFILE);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+ s5p_mfc_write_reg(dev, buf_ctrl->old_val, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+ s5p_mfc_write_reg(dev, buf_ctrl->old_val2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+ }
+ if (buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
+ s5p_mfc_write_reg(dev, buf_ctrl->old_val2, S5P_FIMV_E_NUM_T_LAYER);
+ /* clear RC_BIT_RATE_CHANGE */
+ value = s5p_mfc_read_reg(dev, buf_ctrl->flag_addr);
+ value &= ~(1 << 2);
+ s5p_mfc_write_reg(dev, value, buf_ctrl->flag_addr);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_NAL_CONTROL);
+ value &= ~(0x7 << 8);
+ value |= (buf_ctrl->old_val2 & 0x7) << 8;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_NAL_CONTROL);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+ value = s5p_mfc_read_reg(dev, S5P_FIMV_E_H264_NAL_CONTROL);
+ value &= ~(0xF << 11);
+ value |= (buf_ctrl->old_val2 & 0xF) << 11;
+ s5p_mfc_write_reg(dev, value, S5P_FIMV_E_H264_NAL_CONTROL);
+ }
}
return 0;
@@ -2597,9 +3350,14 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
strm_size = s5p_mfc_get_enc_strm_size();
pic_count = s5p_mfc_get_enc_pic_count();
- mfc_debug(2, "encoded slice type: %d", slice_type);
- mfc_debug(2, "encoded stream size: %d", strm_size);
- mfc_debug(2, "display order: %d", pic_count);
+ mfc_debug(2, "encoded slice type: %d\n", slice_type);
+ mfc_debug(2, "encoded stream size: %d\n", strm_size);
+ mfc_debug(2, "display order: %d\n", pic_count);
+
+ if (enc->buf_full) {
+ ctx->state = MFCINST_ABORT_INST;
+ return 0;
+ }
/* set encoded frame type */
enc->frame_type = slice_type;
@@ -2608,7 +3366,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
ctx->sequence++;
- if (strm_size > 0 || ctx->state == MFCINST_FINISHING) {
+ if (strm_size > 0 || ctx->state == MFCINST_FINISHING
+ || ctx->state == MFCINST_RUNNING_BUF_FULL) {
/* at least one more dest. buffers exist always */
mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
@@ -2666,9 +3425,10 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
return 0;
}
- if (slice_type >= 0 &&
+ if (!ctx->enc_res_change_re_input && slice_type >= 0 &&
ctx->state != MFCINST_FINISHING) {
- if (ctx->state == MFCINST_RUNNING_NO_OUTPUT)
+ if (ctx->state == MFCINST_RUNNING_NO_OUTPUT ||
+ ctx->state == MFCINST_RUNNING_BUF_FULL)
ctx->state = MFCINST_RUNNING;
s5p_mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
@@ -2725,9 +3485,13 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
vb2_buffer_done(&mb_entry->vb, VB2_BUF_STATE_DONE);
}
+ if (ctx->enc_res_change_re_input)
+ ctx->enc_res_change_re_input = 0;
+
if ((ctx->src_queue_cnt > 0) &&
((ctx->state == MFCINST_RUNNING) ||
- (ctx->state == MFCINST_RUNNING_NO_OUTPUT))) {
+ (ctx->state == MFCINST_RUNNING_NO_OUTPUT) ||
+ (ctx->state == MFCINST_RUNNING_BUF_FULL))) {
mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
if (mb_entry->used) {
@@ -2946,10 +3710,18 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
if (ret)
return ret;
- if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
- v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
- ret = -EBUSY;
- goto out;
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (ctx->vq_dst.streaming) {
+ v4l2_err(&dev->v4l2_dev, "%s dst queue busy\n", __func__);
+ ret = -EBUSY;
+ goto out;
+ }
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (ctx->vq_src.streaming) {
+ v4l2_err(&dev->v4l2_dev, "%s src queue busy\n", __func__);
+ ret = -EBUSY;
+ goto out;
+ }
}
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -3014,6 +3786,12 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
ctx->img_height = pix_fmt_mp->height;
ctx->buf_stride = pix_fmt_mp->plane_fmt[0].bytesperline;
+ if ((ctx->state == MFCINST_RUNNING)
+ && (((ctx->old_img_width != 0) && (ctx->old_img_width != ctx->img_width))
+ || ((ctx->old_img_height != 0) && (ctx->old_img_height != ctx->img_height)))) {
+ ctx->enc_drc_flag = 1;
+ }
+
mfc_info_ctx("Enc input pixelformat : %s\n", ctx->src_fmt->name);
mfc_info_ctx("fmt - w: %d, h: %d, stride: %d\n",
pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
@@ -3184,11 +3962,18 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
int ret = -EINVAL;
mfc_debug_enter();
+
mfc_debug(2, "Enqueued buf: %d (type = %d)\n", buf->index, buf->type);
if (ctx->state == MFCINST_ERROR) {
mfc_err_ctx("Call on QBUF after unrecoverable error.\n");
return -EIO;
}
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+ mfc_err_ctx("multiplanar but length is zero\n");
+ return -EIO;
+ }
+
if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
ret = vb2_qbuf(&ctx->vq_src, buf);
if (!ret) {
@@ -3236,9 +4021,10 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
calc_again:
#endif
if (ctx->last_framerate != 0 &&
- ctx->last_framerate != ctx->framerate) {
- mfc_debug(2, "fps changed: %d -> %d\n",
- ctx->framerate, ctx->last_framerate);
+ ((ctx->last_framerate != ctx->framerate) || ctx->qos_changed)) {
+ mfc_debug(2, "fps changed: %d -> %d (%s)\n",
+ ctx->framerate, ctx->last_framerate,
+ ctx->use_extra_qos ? "extra" : "normal");
ctx->framerate = ctx->last_framerate;
s5p_mfc_qos_on(ctx);
}
@@ -3313,6 +4099,13 @@ static int vidioc_streamoff(struct file *file, void *priv,
if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
ctx->last_framerate = 0;
memset(&ctx->last_timestamp, 0, sizeof(struct timeval));
+
+ ctx->old_img_width = ctx->img_width;
+ ctx->old_img_height = ctx->img_height;
+
+ mfc_debug(2, "vidioc_streamoff ctx->old_img_width = %d\n", ctx->old_img_width);
+ mfc_debug(2, "vidioc_streamoff ctx->old_img_height = %d\n", ctx->old_img_height);
+
ret = vb2_streamoff(&ctx->vq_src, type);
if (!ret)
s5p_mfc_qos_off(ctx);
@@ -3351,6 +4144,11 @@ static int enc_ext_info(struct s5p_mfc_ctx *ctx)
if (FW_HAS_TEMPORAL_SVC_CH(dev))
val |= ENC_SET_TEMP_SVC_CH;
+ if (FW_SUPPORT_SKYPE(dev))
+ val |= ENC_SET_SKYPE_FLAG;
+
+ val |= ENC_SET_QP_BOUND_PB;
+
return val;
}
@@ -3414,6 +4212,9 @@ static int get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
ctrl->value = mfc_version(dev);
break;
+ case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+ ctrl->value = MFC_DRIVER_INFO;
+ break;
case V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE:
ctrl->value = mfc_linear_buf_size(mfc_version(dev));
break;
@@ -3530,6 +4331,9 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
p->slice_bit = ctrl->value * 8;
break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW:
+ p->slice_mb_row = ctrl->value;
+ break;
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
p->intra_refresh_mb = ctrl->value;
break;
@@ -3572,29 +4376,8 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
p->num_b_frame = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- switch ((enum v4l2_mpeg_video_h264_profile)(ctrl->value)) {
- case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
- p->codec.h264.profile =
- S5P_FIMV_ENC_PROFILE_H264_MAIN;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
- p->codec.h264.profile =
- S5P_FIMV_ENC_PROFILE_H264_HIGH;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
- p->codec.h264.profile =
- S5P_FIMV_ENC_PROFILE_H264_BASELINE;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
- if (IS_MFCV6(dev))
- p->codec.h264.profile =
- S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
- else
- ret = -EINVAL;
- break;
- default:
- ret = -EINVAL;
- }
+ p->codec.h264.profile =
+ h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
break;
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
p->codec.h264.level =
@@ -3638,6 +4421,18 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
p->codec.h264.rc_max_qp = ctrl->value;
break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+ p->codec.h264.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+ p->codec.h264.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+ p->codec.h264.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+ p->codec.h264.rc_max_qp_b = ctrl->value;
+ break;
case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
p->codec.h264.rc_mb_dark = ctrl->value;
break;
@@ -3676,39 +4471,40 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
p->codec.h264.open_gop_size = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
- p->codec.h264.hier_qp = ctrl->value;
+ p->codec.h264.hier_qp_enable = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
p->codec.h264.hier_qp_type =
(enum v4l2_mpeg_video_h264_hierarchical_coding_type)(ctrl->value);
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
- p->codec.h264.hier_qp_layer = ctrl->value;
+ p->codec.h264.num_hier_layer = ctrl->value & 0x7;
+ p->codec.h264.hier_ref_type = (ctrl->value >> 16) & 0x1;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
- p->codec.h264.hier_qp_layer_qp[(ctrl->value >> 16) & 0x7]
+ p->codec.h264.hier_qp_layer[(ctrl->value >> 16) & 0x7]
= ctrl->value & 0xFF;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.h264.hier_qp_layer_bit[0] = ctrl->value;
+ p->codec.h264.hier_bit_layer[0] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.h264.hier_qp_layer_bit[1] = ctrl->value;
+ p->codec.h264.hier_bit_layer[1] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.h264.hier_qp_layer_bit[2] = ctrl->value;
+ p->codec.h264.hier_bit_layer[2] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3:
- p->codec.h264.hier_qp_layer_bit[3] = ctrl->value;
+ p->codec.h264.hier_bit_layer[3] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4:
- p->codec.h264.hier_qp_layer_bit[4] = ctrl->value;
+ p->codec.h264.hier_bit_layer[4] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5:
- p->codec.h264.hier_qp_layer_bit[5] = ctrl->value;
+ p->codec.h264.hier_bit_layer[5] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6:
- p->codec.h264.hier_qp_layer_bit[6] = ctrl->value;
+ p->codec.h264.hier_bit_layer[6] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
p->codec.h264.sei_gen_enable = ctrl->value;
@@ -3760,6 +4556,16 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR:
p->codec.h264.prepend_sps_pps_to_idr = ctrl->value ? 1 : 0;
break;
+ case V4L2_CID_MPEG_MFC_H264_ENABLE_LTR:
+ p->codec.h264.enable_ltr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR:
+ p->codec.h264.num_of_ltr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+ p->codec.h264.base_priority = ctrl->value;
+ p->codec.h264.set_priority = 1;
+ break;
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
switch ((enum v4l2_mpeg_video_mpeg4_profile)(ctrl->value)) {
case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
@@ -3787,6 +4593,18 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
p->codec.mpeg4.rc_max_qp = ctrl->value;
break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+ p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+ p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+ p->codec.mpeg4.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+ p->codec.mpeg4.rc_max_qp_b = ctrl->value;
+ break;
case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
p->codec.mpeg4.quarter_pixel = ctrl->value;
break;
@@ -3814,6 +4632,12 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
p->codec.mpeg4.rc_max_qp = ctrl->value;
break;
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+ p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+ p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+ break;
case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
break;
@@ -3829,6 +4653,12 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
p->codec.vp8.rc_max_qp = ctrl->value;
break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+ p->codec.vp8.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+ p->codec.vp8.rc_max_qp_p = ctrl->value;
+ break;
case V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP:
p->codec.vp8.rc_frame_qp = ctrl->value;
break;
@@ -3851,28 +4681,28 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
p->codec.vp8.vp8_gfrefreshperiod = ctrl->value;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE:
- p->codec.vp8.hierarchy_qp_enable = ctrl->value;
+ p->codec.vp8.hier_qp_enable = ctrl->value;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0:
- p->codec.vp8.hier_qp_layer_qp[(ctrl->value >> 16) & 0x3]
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
= ctrl->value & 0xFF;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1:
- p->codec.vp8.hier_qp_layer_qp[(ctrl->value >> 16) & 0x3]
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
= ctrl->value & 0xFF;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2:
- p->codec.vp8.hier_qp_layer_qp[(ctrl->value >> 16) & 0x3]
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
= ctrl->value & 0xFF;
break;
case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.vp8.hier_qp_layer_bit[0] = ctrl->value;
+ p->codec.vp8.hier_bit_layer[0] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.vp8.hier_qp_layer_bit[1] = ctrl->value;
+ p->codec.vp8.hier_bit_layer[1] = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.vp8.hier_qp_layer_bit[2] = ctrl->value;
+ p->codec.vp8.hier_bit_layer[2] = ctrl->value;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES:
p->codec.vp8.num_refs_for_p = ctrl->value;
@@ -3881,7 +4711,7 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
p->codec.vp8.intra_4x4mode_disable = ctrl->value;
break;
case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER:
- p->codec.vp8.num_temporal_layer = ctrl->value;
+ p->codec.vp8.num_hier_layer = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
p->codec.hevc.rc_frame_qp = ctrl->value;
@@ -3901,6 +4731,18 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
p->codec.hevc.rc_max_qp = ctrl->value;
break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+ p->codec.hevc.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+ p->codec.hevc.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+ p->codec.hevc.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+ p->codec.hevc.rc_max_qp_b = ctrl->value;
+ break;
case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
p->codec.hevc.level = ctrl->value;
break;
@@ -3943,25 +4785,46 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
p->codec.hevc.loopfilter_disable = ctrl->value;
break;
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY:
- p->codec.hevc.loopfilter_disable = ctrl->value;
+ p->codec.hevc.loopfilter_across = ctrl->value;
break;
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE:
- p->codec.hevc.longterm_ref_enable = ctrl->value;
+ p->codec.hevc.enable_ltr = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
- p->codec.hevc.hier_qp = ctrl->value;
+ p->codec.hevc.hier_qp_enable = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
- p->codec.hevc.hier_qp_type = ctrl->value;
+ p->codec.hevc.hier_qp_type =
+ (enum v4l2_mpeg_video_hevc_hierarchical_coding_type)(ctrl->value);
break;
case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
- p->codec.hevc.hier_qp_layer = ctrl->value;
+ p->codec.hevc.num_hier_layer = ctrl->value & 0x7;
+ p->codec.hevc.hier_ref_type = (ctrl->value >> 16) & 0x1;
break;
case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
- p->codec.hevc.hier_qp_layer_qp = ctrl->value & 0xFF;
+ p->codec.hevc.hier_qp_layer[(ctrl->value >> 16) & 0x7]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.hevc.hier_bit_layer[0] = ctrl->value;
break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT:
- p->codec.hevc.hier_qp_layer_bit = ctrl->value & 0xFF;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.hevc.hier_bit_layer[1] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.hevc.hier_bit_layer[2] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
+ p->codec.hevc.hier_bit_layer[3] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
+ p->codec.hevc.hier_bit_layer[4] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
+ p->codec.hevc.hier_bit_layer[5] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
+ p->codec.hevc.hier_bit_layer[6] = ctrl->value;
break;
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING:
p->codec.hevc.sign_data_hiding = ctrl->value;
@@ -3990,12 +4853,6 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD:
p->codec.hevc.refreshperiod = ctrl->value;
break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CR:
- p->codec.hevc.croma_qp_offset_cr = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CB:
- p->codec.hevc.croma_qp_offset_cb = ctrl->value;
- break;
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
p->codec.hevc.lf_beta_offset_div2 = ctrl->value;
break;
@@ -4011,6 +4868,21 @@ static int set_enc_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF:
p->codec.hevc.store_ref = ctrl->value;
break;
+ case V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE:
+ p->codec.h264.vui_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
+ p->codec.hevc.prepend_sps_pps_to_idr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE:
+ p->dynamic_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_CONFIG_QP:
+ p->config_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER:
+ p->num_hier_max_layer = ctrl->value;
+ break;
default:
v4l2_err(&dev->v4l2_dev, "Invalid control\n");
ret = -EINVAL;
@@ -4090,23 +4962,45 @@ static int set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
ctx->cacheable = 0;
break;
case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+ if (ctrl->value > 150)
+ ctrl->value = 1000;
+ if (ctrl->value == 0) {
+ ctrl->value = 100;
+ ctx->use_extra_qos = 1;
+ mfc_info_ctx("QOS_RATIO is 0, use extra qos!\n");
+ } else {
+ ctx->use_extra_qos = 0;
+ mfc_info_ctx("QOS_RATIO is %d, use extra qos!\n", ctrl->value);
+ }
ctx->qos_ratio = ctrl->value;
+ ctx->qos_changed = 1;
break;
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
- ctx->qp_max_change = ctrl->value;
- break;
case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
- ctx->qp_min_change = ctrl->value;
- ctrl->value = ((ctx->qp_max_change << 8)
- | (ctx->qp_min_change));
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
@@ -4114,6 +5008,13 @@ static int set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
+ case V4L2_CID_MPEG_MFC_H264_USE_LTR:
+ case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+ case V4L2_CID_MPEG_MFC_CONFIG_QP:
list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
continue;
@@ -4128,7 +5029,9 @@ static int set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
if (((ctx_ctrl->id == \
V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH) ||
(ctx_ctrl->id == \
- V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH)) &&
+ V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) ||
+ (ctx_ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH)) &&
(enc->sh_handle.fd == -1)) {
enc->sh_handle.fd = ctrl->value;
if (process_user_shared_handle_enc(ctx)) {
@@ -4136,6 +5039,10 @@ static int set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
return -EINVAL;
}
}
+ if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL)
+ ctx_ctrl->val = h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
+ if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE)
+ ctx_ctrl->val = h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
found = 1;
break;
}
@@ -4582,10 +5489,6 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
return 0;
}
-#define need_to_wait_frame_start(ctx) \
- (((ctx->state == MFCINST_FINISHING) || \
- (ctx->state == MFCINST_RUNNING)) && \
- test_bit(ctx->num, &ctx->dev->hw_lock))
static int s5p_mfc_stop_streaming(struct vb2_queue *q)
{
unsigned long flags;
@@ -4594,16 +5497,32 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
struct s5p_mfc_enc *enc = ctx->enc_priv;
int index = 0;
int aborted = 0;
+ int ret = 0;
+
+ mfc_info_ctx("enc stop_streaming is called, hw_lock : %d, type : %d\n",
+ test_bit(ctx->num, &dev->hw_lock), q->type);
+ MFC_TRACE_CTX("** ENC streamoff(type:%d)\n", q->type);
- if (need_to_wait_frame_start(ctx)) {
- ctx->state = MFCINST_ABORT;
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_stop_bits);
+ clear_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ /* If a H/W operation is in progress, wait for it complete */
+ if (need_to_wait_nal_abort(ctx)) {
if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_FRAME_DONE_RET))
+ S5P_FIMV_R2H_CMD_NAL_ABORT_RET))
s5p_mfc_cleanup_timeout(ctx);
aborted = 1;
+ } else if (test_bit(ctx->num, &dev->hw_lock)) {
+ ret = wait_event_timeout(ctx->queue,
+ (test_bit(ctx->num, &dev->hw_lock) == 0),
+ msecs_to_jiffies(MFC_INT_TIMEOUT));
+ if (ret == 0)
+ mfc_err_ctx("wait for event failed\n");
}
- if (enc->in_slice) {
+ if (enc->in_slice || enc->buf_full) {
ctx->state = MFCINST_ABORT_INST;
spin_lock_irq(&dev->condlock);
set_bit(ctx->num, &dev->ctx_work_bits);
@@ -4614,6 +5533,7 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
s5p_mfc_cleanup_timeout(ctx);
enc->in_slice = 0;
+ enc->buf_full = 0;
aborted = 1;
}
@@ -4649,9 +5569,25 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
spin_unlock_irqrestore(&dev->irqlock, flags);
- if (aborted)
+ if (aborted || ctx->state == MFCINST_FINISHING)
ctx->state = MFCINST_RUNNING;
+ spin_lock_irq(&dev->condlock);
+ clear_bit(ctx->num, &dev->ctx_stop_bits);
+ spin_unlock_irq(&dev->condlock);
+
+ mfc_debug(2, "buffer cleanup is done in stop_streaming, type : %d\n", q->type);
+
+ if (s5p_mfc_enc_ctx_ready(ctx)) {
+ spin_lock_irq(&dev->condlock);
+ set_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irq(&dev->condlock);
+ }
+ spin_lock_irq(&dev->condlock);
+ if (dev->ctx_work_bits)
+ queue_work(dev->sched_wq, &dev->sched_work);
+ spin_unlock_irq(&dev->condlock);
+
return 0;
}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
old mode 100644
new mode 100755
index 541a61de1158..9fb31c764da3
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
@@ -16,7 +16,7 @@
#define MFC_ENC_AVG_FPS_MODE
#define ENC_HIGH_FPS (70000)
-#define ENC_MAX_FPS (120000)
+#define ENC_MAX_FPS (240000)
#define ENC_AVG_FRAMES (10)
const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.h b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_intr.c b/drivers/media/platform/exynos/mfc/s5p_mfc_intr.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_intr.h b/drivers/media/platform/exynos/mfc/s5p_mfc_intr.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.c
old mode 100644
new mode 100755
index 1a3cf0b99e5d..fadfa7edd5b5
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.c
@@ -881,10 +881,10 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
/* multi-slice control */
/* multi-slice MB number or bit size */
- if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
WRITEL(((0x0 << 1) | 0x1), S5P_FIMV_ENC_MSLICE_CTRL);
WRITEL(p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
- } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
WRITEL(((0x1 << 1) | 0x1), S5P_FIMV_ENC_MSLICE_CTRL);
WRITEL(p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
} else {
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.h b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.h
old mode 100644
new mode 100755
index 8ad06de595f2..e851e179e17c
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v5.h
@@ -144,6 +144,7 @@ void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
#define ENC_MULTI_SLICE_MB_MAX ((1 << 16) - 1)
#define ENC_MULTI_SLICE_BIT_MIN 1900
#define ENC_MULTI_SLICE_BYTE_MIN 238
+#define ENC_MULTI_SLICE_MB_ROW_MAX 100
#define ENC_INTRA_REFRESH_MB_MAX ((1 << 16) - 1)
#define ENC_VBV_BUF_SIZE_MAX ((1 << 16) - 1)
#define ENC_H264_LOOP_FILTER_AB_MIN -6
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.c
old mode 100644
new mode 100755
index 04ced6aa052f..c9b11c116d65
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.c
@@ -333,6 +333,9 @@ int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
(ctx->dpb_count * (enc->luma_dpb_size +
enc->chroma_dpb_size + enc->me_buffer_size));
ctx->port_b_size = 0;
+
+ ctx->scratch_buf_size = max(ctx->scratch_buf_size, ctx->min_scratch_buf_size);
+ ctx->min_scratch_buf_size = 0;
break;
case S5P_FIMV_CODEC_MPEG4_ENC:
case S5P_FIMV_CODEC_H263_ENC:
@@ -399,6 +402,15 @@ int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
return -ENOMEM;
}
ctx->port_a_phys = s5p_mfc_mem_daddr_priv(ctx->port_a_buf);
+ ctx->port_a_virt = s5p_mfc_mem_vaddr_priv(ctx->port_a_buf);
+ if (!ctx->port_a_virt) {
+ s5p_mfc_mem_free_priv(ctx->port_a_buf);
+ ctx->port_a_buf = NULL;
+ ctx->port_a_phys = 0;
+
+ mfc_err_ctx("Get vaddr for codec buffer failed.\n");
+ return -ENOMEM;
+ }
}
mfc_debug_leave();
@@ -982,7 +994,7 @@ int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, dma_addr_t buf_addr,
if (cpb_buf_size < strm_size + 4)
mfc_info_ctx("cpb_buf_size(%zu) < strm_size(0x%08x) + 4 bytes\n",
cpb_buf_size, strm_size);
- if (ctx->state == MFCINST_GOT_INST && strm_size == 0)
+ if (strm_size == 0)
mfc_info_ctx("stream size is 0\n");
WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
@@ -1283,6 +1295,8 @@ int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
{
struct s5p_mfc_dev *dev = ctx->dev;
+ size = ALIGN(size, 512);
+
WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
@@ -1390,16 +1404,18 @@ static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
struct s5p_mfc_enc *enc = ctx->enc_priv;
/* multi-slice control */
- if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
+ if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
WRITEL((enc->slice_mode + 0x4), S5P_FIMV_E_MSLICE_MODE);
+ else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)
+ WRITEL((enc->slice_mode - 0x2), S5P_FIMV_E_MSLICE_MODE);
else
WRITEL(enc->slice_mode, S5P_FIMV_E_MSLICE_MODE);
/* multi-slice MB number or bit size */
- if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB || \
+ enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) {
WRITEL(enc->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
- } else if (enc->slice_mode == \
- V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ } else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
WRITEL(enc->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
} else {
WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
@@ -1410,6 +1426,77 @@ static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
}
+void s5p_mfc_set_default_params(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ /* Default setting for quality */
+ /* Common Registers */
+ WRITEL(0x0, S5P_FIMV_E_ENC_OPTIONS);
+ WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
+ WRITEL(0x80, S5P_FIMV_E_MV_HOR_RANGE);
+ WRITEL(0x80, S5P_FIMV_E_MV_VER_RANGE);
+ WRITEL(0x0, S5P_FIMV_E_IR_SIZE);
+ WRITEL(0x0, S5P_FIMV_E_AIR_THRESHOLD);
+ WRITEL(0x1E, S5P_FIMV_E_GOP_CONFIG); /* I frame period: 30 */
+ WRITEL(0x0, S5P_FIMV_E_GOP_CONFIG2);
+ WRITEL(0x0, S5P_FIMV_E_MSLICE_MODE);
+
+ /* Hierarchical Coding */
+ WRITEL(0x8, S5P_FIMV_E_NUM_T_LAYER);
+
+ /* Rate Control */
+ WRITEL(0x4000, S5P_FIMV_E_RC_CONFIG);
+ WRITEL(0x0, S5P_FIMV_E_RC_QP_BOUND);
+ WRITEL(0x0, S5P_FIMV_E_RC_QP_BOUND_PB);
+ WRITEL(0x2, S5P_FIMV_E_RC_MODE);
+ WRITEL(0xF, S5P_FIMV_E_MB_RC_CONFIG);
+ WRITEL(0x1E0001, S5P_FIMV_E_RC_FRAME_RATE); /* framerate: 30 fps */
+ WRITEL(0xF4240, S5P_FIMV_E_RC_BIT_RATE); /* bitrate: 1000000 */
+ WRITEL(0x3FD00, S5P_FIMV_E_RC_ROI_CTRL);
+ WRITEL(0x0, S5P_FIMV_E_VBV_BUFFER_SIZE);
+ WRITEL(0x0, S5P_FIMV_E_VBV_INIT_DELAY);
+ WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE);
+ WRITEL(0x2710, S5P_FIMV_E_MAX_BIT_COUNT); /* max bit count: 10000 */
+ WRITEL(0x3E8, S5P_FIMV_E_MIN_BIT_COUNT); /* min bit count: 1000 */
+
+ /* HEVC */
+ WRITEL(0x50F215, S5P_FIMV_E_HEVC_OPTIONS);
+ WRITEL(0x1E, S5P_FIMV_E_HEVC_REFRESH_PERIOD);
+ WRITEL(0x0, S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET);
+ WRITEL(0x0, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
+ WRITEL(0x0, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
+
+ /* H.264 */
+ WRITEL(0x3011, S5P_FIMV_E_H264_OPTIONS);
+ WRITEL(0x0, S5P_FIMV_E_H264_OPTIONS_2);
+ WRITEL(0x0, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
+ WRITEL(0x0, S5P_FIMV_E_H264_LF_BETA_OFFSET);
+ WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD);
+ WRITEL(0x0, S5P_FIMV_E_H264_CHROMA_QP_OFFSET);
+
+ /* VP8 */
+ WRITEL(0x0, S5P_FIMV_E_VP8_OPTION);
+ WRITEL(0x0, S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
+
+ /* MVC */
+ WRITEL(0x1D, S5P_FIMV_E_MVC_FRAME_QP_VIEW1); /* QP: 29 */
+ WRITEL(0xF4240, S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1); /* bitrate: 1000000 */
+ WRITEL(0x33003300, S5P_FIMV_E_MVC_RC_QBOUND_VIEW1); /* max I, P QP: 51 */
+ WRITEL(0x2, S5P_FIMV_E_MVC_RC_MODE_VIEW1);
+ WRITEL(0x1, S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON);
+
+ /* Additional initialization: NAL start only */
+ WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION);
+ WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR);
+ WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE);
+ WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
+ WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
+ WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
+
+ return;
+}
+
static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
@@ -1419,6 +1506,8 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
mfc_debug_enter();
+ s5p_mfc_set_default_params(ctx);
+
/* width */
WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH); /* 16 align */
/* height */
@@ -1432,12 +1521,14 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
/* pictype : IDR period */
- reg = 0;
+ reg = READL(S5P_FIMV_E_GOP_CONFIG);
+ reg &= ~(0xFFFF);
reg |= p->gop_size & 0xFFFF;
WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
if(FW_HAS_GOP2(dev)) {
- reg = 0;
+ reg = READL(S5P_FIMV_E_GOP_CONFIG2);
+ reg &= ~(0x3FFF);
reg |= (p->gop_size >> 16) & 0x3FFF;
WRITEL(reg, S5P_FIMV_E_GOP_CONFIG2);
}
@@ -1446,12 +1537,12 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
/* multi-slice MB number or bit size */
enc->slice_mode = p->slice_mode;
- WRITEL(0, S5P_FIMV_E_ENC_OPTIONS);
-
- if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
enc->slice_size.mb = p->slice_mb;
- } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
enc->slice_size.bits = p->slice_bit;
+ } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) {
+ enc->slice_size.mb = p->slice_mb_row * ((ctx->img_width + 15) / 16);
} else {
enc->slice_size.mb = 0;
enc->slice_size.bits = 0;
@@ -1461,31 +1552,22 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
/* cyclic intra refresh */
WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE);
+
reg = READL(S5P_FIMV_E_ENC_OPTIONS);
- if (p->intra_refresh_mb == 0)
- reg &= ~(0x1 << 4);
- else
+ /* frame skip mode */
+ reg &= ~(0x3);
+ reg |= (p->frame_skip_mode & 0x3);
+ /* seq header ctrl */
+ reg &= ~(0x1 << 2);
+ reg |= ((p->seq_hdr_mode & 0x1) << 2);
+ /* cyclic intra refresh */
+ reg &= ~(0x1 << 4);
+ if (p->intra_refresh_mb)
reg |= (0x1 << 4);
- WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
-
/* 'NON_REFERENCE_STORE_ENABLE' for debugging */
- reg = READL(S5P_FIMV_E_ENC_OPTIONS);
reg &= ~(0x1 << 9);
WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
- /* memory structure cur. frame */
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
- /* 0: Linear, 1: 2D tiled*/
- reg = READL(S5P_FIMV_E_ENC_OPTIONS);
- reg |= (0x1 << 7);
- WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
- } else {
- /* 0: Linear, 1: 2D tiled*/
- reg = READL(S5P_FIMV_E_ENC_OPTIONS);
- reg &= ~(0x1 << 7);
- WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
- }
-
switch (ctx->src_fmt->fourcc) {
case V4L2_PIX_FMT_NV12M:
case V4L2_PIX_FMT_NV12MT_16X16:
@@ -1521,12 +1603,6 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
}
WRITEL(pix_val, S5P_FIMV_PIXEL_FORMAT);
- /* memory structure recon. frame */
- /* 0: Linear, 1: 2D tiled */
- reg = READL(S5P_FIMV_E_ENC_OPTIONS);
- reg |= (0x1 << 8);
- WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
-
/* padding control & value */
WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL);
if (p->pad) {
@@ -1546,18 +1622,20 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
}
/* rate control config. */
- reg = 0;
- /** frame-level rate control */
+ reg = READL(S5P_FIMV_E_RC_CONFIG);
+ /* macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= ((p->rc_mb & 0x1) << 8);
+ /* framelevel rate control */
reg &= ~(0x1 << 9);
- reg |= (p->rc_frame << 9);
+ reg |= ((p->rc_frame & 0x1) << 9);
+ /* 'DROP_CONTROL_ENABLE', disable */
+ reg &= ~(0x1 << 10);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/* bit rate */
- if (p->rc_frame)
- WRITEL(p->rc_bitrate,
- S5P_FIMV_E_RC_BIT_RATE);
- else
- WRITEL(1, S5P_FIMV_E_RC_BIT_RATE);
+ if (p->rc_bitrate)
+ WRITEL(p->rc_bitrate, S5P_FIMV_E_RC_BIT_RATE);
if (p->rc_frame) {
if (FW_HAS_ADV_RC_MODE(dev)) {
@@ -1580,48 +1658,12 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
/* extended encoder ctrl */
/** vbv buffer size */
- if (p->frame_skip_mode == V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT)
- WRITEL(p->vbv_buf_size, S5P_FIMV_E_VBV_BUFFER_SIZE);
-
- /** seq header ctrl */
- reg = READL(S5P_FIMV_E_ENC_OPTIONS);
- reg &= ~(0x1 << 2);
- reg |= (p->seq_hdr_mode << 2);
- /** frame skip mode */
- reg &= ~(0x3);
- reg |= (p->frame_skip_mode);
- WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
-
- /* 'DROP_CONTROL_ENABLE', disable */
- reg = READL(S5P_FIMV_E_RC_CONFIG);
- reg &= ~(0x1 << 10);
- WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
- /* setting for MV range [16, 256] */
- if (mfc_version(dev) == 0x61)
- reg = ENC_V61_MV_RANGE;
- else if (mfc_version(dev) == 0x78)
- reg = ENC_V78_MV_RANGE;
- else
- reg = ENC_V65_MV_RANGE;
- WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE);
- WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE);
-
- WRITEL(0x0, S5P_FIMV_E_VBV_INIT_DELAY); /* SEQ_start Only */
-
- /* initialize for '0' only setting */
- WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG); /* NAL_start Only */
-
- WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT); /* NAL_start Only */
-
- WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR); /* NAL_start Only */
- WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE); /* NAL_start Only */
+ if (p->frame_skip_mode == V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ reg = READL(S5P_FIMV_E_VBV_BUFFER_SIZE);
+ reg &= ~(0xFF);
+ reg |= p->vbv_buf_size & 0xFF;
+ WRITEL(reg, S5P_FIMV_E_VBV_BUFFER_SIZE);
+ }
mfc_debug_leave();
@@ -1634,7 +1676,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
struct s5p_mfc_enc *enc = ctx->enc_priv;
struct s5p_mfc_enc_params *p = &enc->params;
struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
- unsigned int reg = 0;
+ unsigned int reg = 0, reg2 = 0;
int i;
mfc_debug_enter();
@@ -1682,10 +1724,52 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
reg |= p_264->profile;
WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+ reg = READL(S5P_FIMV_E_H264_OPTIONS);
+ /* entropy coding mode */
+ reg &= ~(0x1);
+ reg |= (p_264->entropy_mode & 0x1);
+ /* loop filter ctrl */
+ reg &= ~(0x3 << 1);
+ reg |= ((p_264->loop_filter_mode & 0x3) << 1);
/* interlace */
- reg = 0;
reg &= ~(0x1 << 3);
- reg |= (p_264->interlace << 3);
+ reg |= ((p_264->interlace & 0x1) << 3);
+ /* intra picture period for H.264 open GOP
+ * from 9.0 Version changed register meaning
+ */
+ reg &= ~(0x1 << 4);
+ p_264->open_gop ^= S5P_FIMV_E_IDR_H264_IDR;
+ reg |= ((p_264->open_gop & 0x1) << 4);
+ /* extended encoder ctrl */
+ reg &= ~(0x1 << 5);
+ reg |= ((p_264->ar_vui & 0x1) << 5);
+ /* ASO enable */
+ reg &= ~(0x1 << 6);
+ reg |= ((p_264->aso_enable & 0x1) << 6);
+ /* number of ref. picture */
+ reg &= ~(0x1 << 7);
+ reg |= (((p_264->num_ref_pic_4p - 1) & 0x1) << 7);
+ /* Temporal SVC - hier qp enable */
+ reg &= ~(0x1 << 8);
+ reg |= ((p_264->hier_qp_enable & 0x1) << 8);
+ /* 8x8 transform enable */
+ reg &= ~(0x1 << 12);
+ reg &= ~(0x1 << 13);
+ reg |= ((p_264->_8x8_transform & 0x1) << 12);
+ reg |= ((p_264->_8x8_transform & 0x1) << 13);
+ /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+ reg &= ~(0x1 << 14);
+ /*
+ * CONSTRAINT_SET0_FLAG: all constraints specified in
+ * Baseline Profile
+ */
+ reg |= (0x1 << 26);
+ /* sps pps control */
+ reg &= ~(0x1 << 29);
+ reg |= ((p_264->prepend_sps_pps_to_idr & 0x1) << 29);
+ /* VUI parameter disable */
+ reg &= ~(0x1 << 30);
+ reg |= ((p_264->vui_enable & 0x1) << 30);
WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
/** height */
@@ -1695,134 +1779,90 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
WRITEL(ctx->img_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
}
- /* loop filter ctrl */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x3 << 1);
- reg |= (p_264->loop_filter_mode << 1);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
/* loopfilter alpha offset */
- if (p_264->loop_filter_alpha < 0) {
- reg = 0x10;
- reg |= (0xFF - p_264->loop_filter_alpha) + 1;
- } else {
- reg = 0x00;
- reg |= (p_264->loop_filter_alpha & 0xF);
- }
+ reg = READL(S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
+ reg &= ~(0x1F);
+ reg |= (p_264->loop_filter_alpha & 0x1F);
WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
/* loopfilter beta offset */
- if (p_264->loop_filter_beta < 0) {
- reg = 0x10;
- reg |= (0xFF - p_264->loop_filter_beta) + 1;
- } else {
- reg = 0x00;
- reg |= (p_264->loop_filter_beta & 0xF);
- }
+ reg = READL(S5P_FIMV_E_H264_LF_BETA_OFFSET);
+ reg &= ~(0x1F);
+ reg |= (p_264->loop_filter_beta & 0x1F);
WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
- /* entropy coding mode */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1);
- reg |= (p_264->entropy_mode);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
- /* number of ref. picture */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 7);
- if (!IS_MFCv78(dev))
- reg |= ((p_264->num_ref_pic_4p-1) << 7);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
- /* 8x8 transform enable */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x3 << 12);
- reg |= (p_264->_8x8_transform << 12);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
/* rate control config. */
reg = READL(S5P_FIMV_E_RC_CONFIG);
- /** macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p->rc_mb << 8);
- WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/** frame QP */
- reg &= ~(0x3F);
- reg |= p_264->rc_frame_qp;
+ reg &= ~(0x7F);
+ reg |= (p_264->rc_frame_qp & 0x7F);
+ if (!p->rc_frame && !p->rc_mb && p->dynamic_qp)
+ reg |= (0x1 << 11);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/* frame rate */
/* Fix value for H.264, H.263 in the driver */
p->rc_frame_delta = FRAME_DELTA_DEFAULT;
if (p->rc_frame) {
- reg = 0;
- reg &= ~(0xffff << 16);
- reg |= ((p_264->rc_framerate * p->rc_frame_delta) << 16);
- reg &= ~(0xffff);
- reg |= p->rc_frame_delta;
+ reg = READL(S5P_FIMV_E_RC_FRAME_RATE);
+ reg &= ~(0xFFFF << 16);
+ reg |= (p_264->rc_framerate * p->rc_frame_delta) << 16;
+ reg &= ~(0xFFFF);
+ reg |= p->rc_frame_delta & 0xFFFF;
WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
}
-
- /* max & min value of QP */
- reg = 0;
- /** max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_264->rc_max_qp << 8);
- /** min QP */
- reg &= ~(0x3F);
- reg |= p_264->rc_min_qp;
+ /* max & min value of QP for I frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND);
+ /** max I frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_264->rc_max_qp & 0x7F) << 8);
+ /** min I frame QP */
+ reg &= ~(0x7F);
+ reg |= (p_264->rc_min_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
- /* macroblock adaptive scaling features */
- WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG);
- if (p->rc_mb) {
- reg = 0;
- /** dark region */
- reg &= ~(0x1 << 3);
- reg |= (p_264->rc_mb_dark << 3);
- /** smooth region */
- reg &= ~(0x1 << 2);
- reg |= (p_264->rc_mb_smooth << 2);
- /** static region */
- reg &= ~(0x1 << 1);
- reg |= (p_264->rc_mb_static << 1);
- /** high activity region */
- reg &= ~(0x1);
- reg |= p_264->rc_mb_activity;
- WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
- }
-
- WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
- if (!p->rc_frame && !p->rc_mb) {
- reg = 0;
- reg &= ~(0x3f << 16);
- reg |= (p_264->rc_b_frame_qp << 16);
- reg &= ~(0x3f << 8);
- reg |= (p_264->rc_p_frame_qp << 8);
- reg &= ~(0x3f);
- reg |= p_264->rc_frame_qp;
- WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
- }
-
- /* sps pps control */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 29);
- reg |= (p_264->prepend_sps_pps_to_idr << 29);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+ /* max & min value of QP for P/B frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+ /** max B frame QP */
+ reg &= ~(0x7F << 24);
+ reg |= ((p_264->rc_max_qp_b & 0x7F) << 24);
+ /** min B frame QP */
+ reg &= ~(0x7F << 16);
+ reg |= ((p_264->rc_min_qp_b & 0x7F) << 16);
+ /** max P frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_264->rc_max_qp_p & 0x7F) << 8);
+ /** min P frame QP */
+ reg &= ~(0x7F);
+ reg |= p_264->rc_min_qp_p & 0x7F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
- /*
- * CONSTRAINT_SET0_FLAG: all constraints specified in
- * Baseline Profile
- */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg |= (0x1 << 26);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+ /* macroblock adaptive scaling features */
+ reg = READL(S5P_FIMV_E_MB_RC_CONFIG);
+ /* dark region */
+ reg &= ~(0x1 << 3);
+ reg |= ((p_264->rc_mb_dark & 0x1) << 3);
+ /* smooth region */
+ reg &= ~(0x1 << 2);
+ reg |= ((p_264->rc_mb_smooth & 0x1) << 2);
+ /* static region */
+ reg &= ~(0x1 << 1);
+ reg |= ((p_264->rc_mb_static & 0x1) << 1);
+ /* high activity region */
+ reg &= ~(0x1);
+ reg |= (p_264->rc_mb_activity & 0x1);
+ WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
- /* extended encoder ctrl */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 5);
- reg |= (p_264->ar_vui << 5);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+ reg = READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+ reg &= ~(0x7F << 24);
+ reg |= ((p->config_qp & 0x7F) << 24);
+ reg &= ~(0x7F << 16);
+ reg |= ((p_264->rc_b_frame_qp & 0x7F) << 16);
+ reg &= ~(0x7F << 8);
+ reg |= ((p_264->rc_p_frame_qp & 0x7F) << 8);
+ reg &= ~(0x7F);
+ reg |= (p_264->rc_frame_qp & 0x7F);
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
@@ -1841,87 +1881,72 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
}
}
-
- /* intra picture period for H.264 open GOP */
- /** control */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- /* from 9.0 Version changed register meaning*/
- reg &= ~(0x1 << 4);
- p_264->open_gop ^= S5P_FIMV_E_IDR_H264_IDR;
- reg |= (p_264->open_gop << 4);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
- /** value */
- WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD);
+ /* intra picture period for H.264 open GOP, value */
if (p_264->open_gop) {
- reg = 0;
- reg &= ~(0xffff);
- reg |= p_264->open_gop_size;
+ reg = READL(S5P_FIMV_E_H264_I_PERIOD);
+ reg &= ~(0xFFFF);
+ reg |= (p_264->open_gop_size & 0xFFFF);
WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD);
}
- /* 'WEIGHTED_BI_PREDICTION' for B is disable */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x3 << 9);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
- /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 14);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
- /* ASO enable */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- if (p_264->aso_enable)
- reg |= (0x1 << 6);
- else
- reg &= ~(0x1 << 6);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_2);
+ /* pic_order_cnt_type = 0 for backward compatibilities */
+ if (FW_HAS_POC_TYPE_CTRL(dev))
+ reg &= ~(0x3);
+ /* Enable LTR */
+ reg &= ~(0x1 << 2);
+ if ((p_264->enable_ltr & 0x1) || (p_264->num_of_ltr > 0))
+ reg |= (0x1 << 2);
+ /* Number of LTR */
+ reg &= ~(0x3 << 7);
+ if (p_264->num_of_ltr > 2)
+ reg |= (((p_264->num_of_ltr - 2) & 0x3) << 7);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_2);
- /* VUI parameter disable */
- if (FW_HAS_VUI_PARAMS(dev)) {
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 30);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+ /* Temporal SVC - qp type, layer number */
+ reg = READL(S5P_FIMV_E_NUM_T_LAYER);
+ reg &= ~(0x1 << 3);
+ reg |= (p_264->hier_qp_type & 0x1) << 3;
+ reg &= ~(0x7);
+ reg |= p_264->num_hier_layer & 0x7;
+ reg &= ~(0x7 << 4);
+ if (p_264->hier_ref_type) {
+ reg |= 0x1 << 7;
+ reg |= (p->num_hier_max_layer & 0x7) << 4;
+ } else {
+ reg |= 0x7 << 4;
}
+ WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+ mfc_debug(3, "Temporal SVC: hier_qp_enable %d, enable_ltr %d, "
+ "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
+ p_264->hier_qp_enable, p_264->enable_ltr, p_264->num_hier_layer,
+ p->num_hier_max_layer, p_264->hier_ref_type, reg);
- /* pic_order_cnt_type = 0 for backward compatibilities */
- if (FW_HAS_POC_TYPE_CTRL(dev)) {
- reg = READL(S5P_FIMV_E_H264_OPTIONS_2);
- reg &= ~(0x3 << 0);
- reg |= (0x0 << 0); /* TODO: add new CID for this */
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_2);
+ /* QP & Bitrate for each layer */
+ for (i = 0; i < 7; i++) {
+ WRITEL(p_264->hier_qp_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+ WRITEL(p_264->hier_bit_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+ mfc_debug(3, "Temporal SVC: layer[%d] QP: %#x, bitrate: %#x\n",
+ i, p_264->hier_qp_layer[i],
+ p_264->hier_bit_layer[i]);
}
-#if defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS5433)
- reg = READL(S5P_FIMV_E_H264_OPTIONS_2);
- reg |= (0x1 << 3); /* Enable ECO MODE */
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_2);
-#endif
-
- /* hier qp enable */
- reg = READL(S5P_FIMV_E_H264_OPTIONS);
- reg &= ~(0x1 << 8);
- reg |= ((p_264->hier_qp & 0x1) << 8);
- WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
- reg = 0;
- if (p_264->hier_qp_layer) {
- reg |= 0x7 << 0x4;
- reg |= (p_264->hier_qp_type & 0x1) << 0x3;
- reg |= p_264->hier_qp_layer & 0x7;
- WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
- /* QP value for each layer */
- if (p_264->hier_qp) {
- for (i = 0; i < (p_264->hier_qp_layer & 0x7); i++)
- WRITEL(p_264->hier_qp_layer_qp[i],
- S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 + i * 4);
- } else {
- for (i = 0; i < (p_264->hier_qp_layer & 0x7); i++)
- WRITEL(p_264->hier_qp_layer_bit[i],
- S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+ if (p_264->set_priority) {
+ reg = 0;
+ reg2 = 0;
+ for (i = 0; i < (p_264->num_hier_layer & 0x7); i++) {
+ if (i <= 4)
+ reg |= ((p_264->base_priority & 0x3F) + i) << (6 * i);
+ else
+ reg2 |= ((p_264->base_priority & 0x3F) + i) << (6 * (i - 5));
}
+ WRITEL(reg, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+ WRITEL(reg2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+ mfc_debug(3, "Temporal SVC: priority EXTENSION0: %#x, EXTENSION1: %#x\n",
+ reg, reg2);
}
- /* number of coding layer should be zero when hierarchical is disable */
- WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
/* set frame pack sei generation */
if (p_264->sei_gen_enable) {
@@ -2015,26 +2040,25 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
/* WRITEL(p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL); */
/* qp */
- WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
- if (!p->rc_frame && !p->rc_mb) {
- reg = 0;
- reg &= ~(0x3f << 16);
- reg |= (p_mpeg4->rc_b_frame_qp << 16);
- reg &= ~(0x3f << 8);
- reg |= (p_mpeg4->rc_p_frame_qp << 8);
- reg &= ~(0x3f);
- reg |= p_mpeg4->rc_frame_qp;
- WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
- }
+ reg = READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+ reg &= ~(0x7F << 24);
+ reg |= ((p->config_qp & 0x7F) << 24);
+ reg &= ~(0x7F << 16);
+ reg |= ((p_mpeg4->rc_b_frame_qp & 0x7F) << 16);
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_p_frame_qp & 0x7F) << 8);
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_frame_qp & 0x7F);
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
/* frame rate */
if (p->rc_frame) {
p->rc_frame_delta = p_mpeg4->vop_frm_delta;
- reg = 0;
- reg &= ~(0xffff << 16);
+ reg = READL(S5P_FIMV_E_RC_FRAME_RATE);
+ reg &= ~(0xFFFF << 16);
reg |= (p_mpeg4->vop_time_res << 16);
- reg &= ~(0xffff);
- reg |= p_mpeg4->vop_frm_delta;
+ reg &= ~(0xFFFF);
+ reg |= (p_mpeg4->vop_frm_delta & 0xFFFF);
WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
} else {
p->rc_frame_delta = FRAME_DELTA_DEFAULT;
@@ -2042,25 +2066,37 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
/* rate control config. */
reg = READL(S5P_FIMV_E_RC_CONFIG);
- /** macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p->rc_mb << 8);
- WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/** frame QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_frame_qp;
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_frame_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
- /* max & min value of QP */
- reg = 0;
- /** max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_mpeg4->rc_max_qp << 8);
- /** min QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_min_qp;
+ /* max & min value of QP for I frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND);
+ /** max I frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_max_qp & 0x7F) << 8);
+ /** min I frame QP */
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_min_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+ /* max & min value of QP for P/B frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+ /** max B frame QP */
+ reg &= ~(0x7F << 24);
+ reg |= ((p_mpeg4->rc_max_qp_b & 0x7F) << 24);
+ /** min B frame QP */
+ reg &= ~(0x7F << 16);
+ reg |= ((p_mpeg4->rc_min_qp_b & 0x7F) << 16);
+ /** max P frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_max_qp_p & 0x7F) << 8);
+ /** min P frame QP */
+ reg &= ~(0x7F);
+ reg |= p_mpeg4->rc_min_qp_p & 0x7F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
/* initialize for '0' only setting*/
WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS); /* SEQ_start only */
WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD); /* SEQ_start only */
@@ -2089,49 +2125,54 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
/* qp */
- WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
- if (!p->rc_frame && !p->rc_mb) {
- reg = 0;
- reg &= ~(0x3f << 8);
- reg |= (p_mpeg4->rc_p_frame_qp << 8);
- reg &= ~(0x3f);
- reg |= p_mpeg4->rc_frame_qp;
- WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
- }
+ reg = READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+ reg &= ~(0x7F << 24);
+ reg |= ((p->config_qp & 0x7F) << 24);
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_p_frame_qp & 0x7F) << 8);
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_frame_qp & 0x7F);
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
/* frame rate */
/* Fix value for H.264, H.263 in the driver */
p->rc_frame_delta = FRAME_DELTA_DEFAULT;
if (p->rc_frame) {
- reg = 0;
- reg &= ~(0xffff << 16);
+ reg = READL(S5P_FIMV_E_RC_FRAME_RATE);
+ reg &= ~(0xFFFF << 16);
reg |= ((p_mpeg4->rc_framerate * p->rc_frame_delta) << 16);
- reg &= ~(0xffff);
- reg |= p->rc_frame_delta;
+ reg &= ~(0xFFFF);
+ reg |= (p->rc_frame_delta & 0xFFFF);
WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
}
/* rate control config. */
reg = READL(S5P_FIMV_E_RC_CONFIG);
- /** macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p->rc_mb << 8);
- WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/** frame QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_frame_qp;
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_frame_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
- /* max & min value of QP */
- reg = 0;
- /** max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_mpeg4->rc_max_qp << 8);
- /** min QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_min_qp;
+ /* max & min value of QP for I frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND);
+ /** max I frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_max_qp & 0x7F) << 8);
+ /** min I frame QP */
+ reg &= ~(0x7F);
+ reg |= (p_mpeg4->rc_min_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+ /* max & min value of QP for P/B frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+ /** max P frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_mpeg4->rc_max_qp_p & 0x7F) << 8);
+ /** min P frame QP */
+ reg &= ~(0x7F);
+ reg |= p_mpeg4->rc_min_qp_p & 0x7F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
mfc_debug_leave();
return 0;
@@ -2155,42 +2196,47 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
reg |= (p_vp8->vp8_version) ;
WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
- reg = 0;
+ reg = READL(S5P_FIMV_E_VP8_OPTION);
+ reg &= ~(0x1);
+ reg |= (p_vp8->num_refs_for_p - 1) & 0x1;
+ reg &= ~(0xF << 3);
+ reg |= (p_vp8->vp8_numberofpartitions & 0xF) << 3;
+ reg &= ~(0x1 << 10);
+ reg |= (p_vp8->intra_4x4mode_disable & 0x1) << 10;
+ /* Temporal SVC - hier qp enable */
+ reg &= ~(0x1 << 11);
+ reg |= (p_vp8->hier_qp_enable & 0x1) << 11;
/* Disable IVF header */
reg |= (0x1 << 12);
- reg |= (p_vp8->intra_4x4mode_disable & 0x1) << 10;
- reg |= (p_vp8->vp8_numberofpartitions & 0xF) << 3;
- reg |= (p_vp8->num_refs_for_p - 1) & 0x1;
WRITEL(reg, S5P_FIMV_E_VP8_OPTION);
- reg = 0;
+ reg = READL(S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
+ reg &= ~(0x1);
reg |= (p_vp8->vp8_goldenframesel & 0x1);
- reg |= (p_vp8->vp8_gfrefreshperiod & 0xffff) << 1;
+ reg &= ~(0xFFFF << 1);
+ reg |= (p_vp8->vp8_gfrefreshperiod & 0xFFFF) << 1;
WRITEL(reg, S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
- /* hier qp enable */
- reg = READL(S5P_FIMV_E_VP8_OPTION);
- reg &= ~(0x1 << 11);
- reg |= ((p_vp8->hierarchy_qp_enable & 0x1) << 11);
- WRITEL(reg, S5P_FIMV_E_VP8_OPTION);
- reg = 0;
- if (p_vp8->num_temporal_layer) {
- reg |= p_vp8->num_temporal_layer & 0x3;
- WRITEL(reg, S5P_FIMV_E_VP8_NUM_T_LAYER);
- /* QP value for each layer */
- if (p_vp8->hierarchy_qp_enable) {
- for (i = 0; i < (p_vp8->num_temporal_layer & 0x3); i++)
- WRITEL(p_vp8->hier_qp_layer_qp[i],
- S5P_FIMV_E_VP8_HIERARCHICAL_QP_LAYER0 + i * 4);
- } else {
- for (i = 0; i < (p_vp8->num_temporal_layer & 0x3); i++)
- WRITEL(p_vp8->hier_qp_layer_bit[i],
- S5P_FIMV_E_H264_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
- }
+ /* Temporal SVC - layer number */
+ reg = READL(S5P_FIMV_E_NUM_T_LAYER);
+ reg &= ~(0x7);
+ reg |= p_vp8->num_hier_layer & 0x3;
+ reg &= ~(0x7 << 4);
+ reg |= 0x3 << 4;
+ WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+ mfc_debug(3, "Temporal SVC: hier_qp_enable %d, num_hier_layer %d, NUM_T_LAYER 0x%x\n",
+ p_vp8->hier_qp_enable, p_vp8->num_hier_layer, reg);
+
+ /* QP & Bitrate for each layer */
+ for (i = 0; i < 3; i++) {
+ WRITEL(p_vp8->hier_qp_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+ WRITEL(p_vp8->hier_bit_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+ mfc_debug(3, "Temporal SVC: layer[%d] QP: %#x, bitrate: %#x\n",
+ i, p_vp8->hier_qp_layer[i],
+ p_vp8->hier_bit_layer[i]);
}
- /* number of coding layer should be zero when hierarchical is disable */
- reg |= p_vp8->num_temporal_layer;
- WRITEL(reg, S5P_FIMV_E_VP8_NUM_T_LAYER);
reg = 0;
reg |= (p_vp8->vp8_filtersharpness & 0x7);
@@ -2198,51 +2244,52 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
WRITEL(reg , S5P_FIMV_E_VP8_FILTER_OPTIONS);
/* qp */
- WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
- if (!p->rc_frame && !p->rc_mb) {
- reg = 0;
- reg &= ~(0x3f << 8);
- reg |= (p_vp8->rc_p_frame_qp << 8);
- reg &= ~(0x3f);
- reg |= p_vp8->rc_frame_qp;
- WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
- }
+ reg = READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+ reg &= ~(0x7F << 24);
+ reg |= ((p->config_qp & 0x7F) << 24);
+ reg &= ~(0x7F << 8);
+ reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8);
+ reg &= ~(0x7F);
+ reg |= (p_vp8->rc_frame_qp & 0x7F);
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
/* frame rate */
p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-
if (p->rc_frame) {
- reg = 0;
- reg &= ~(0xffff << 16);
+ reg = READL(S5P_FIMV_E_RC_FRAME_RATE);
+ reg &= ~(0xFFFF << 16);
reg |= ((p_vp8->rc_framerate * p->rc_frame_delta) << 16);
- reg &= ~(0xffff);
- reg |= p->rc_frame_delta;
+ reg &= ~(0xFFFF);
+ reg |= (p->rc_frame_delta & 0xFFFF);
WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
}
/* rate control config. */
reg = READL(S5P_FIMV_E_RC_CONFIG);
- /** macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p->rc_mb << 8);
/** frame QP */
- reg &= ~(0x3F);
- reg |= p_vp8->rc_frame_qp;
+ reg &= ~(0x7F);
+ reg |= (p_vp8->rc_frame_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
- /* max & min value of QP */
- reg = 0;
- /** max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_vp8->rc_max_qp << 8);
- /** min QP */
- reg &= ~(0x3F);
- reg |= p_vp8->rc_min_qp;
+ /* max & min value of QP for I frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND);
+ /** max I frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_vp8->rc_max_qp & 0x7F) << 8);
+ /** min I frame QP */
+ reg &= ~(0x7F);
+ reg |= (p_vp8->rc_min_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
- /* Disable all macroblock adaptive scaling features */
- reg = 0xF;
- WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
+ /* max & min value of QP for P/B frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+ /** max P frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_vp8->rc_max_qp_p & 0x7F) << 8);
+ /** min P frame QP */
+ reg &= ~(0x7F);
+ reg |= p_vp8->rc_min_qp_p & 0x7F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
mfc_debug_leave();
@@ -2286,129 +2333,165 @@ static int s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
/* max partition depth */
- reg = 0;
+ reg = READL(S5P_FIMV_E_HEVC_OPTIONS);
+ reg &= ~(0x3);
reg |= (p_hevc->max_partition_depth & 0x1);
- reg |= (p_hevc->num_refs_for_p-1) << 2;
- reg |= (2 << 3); /* always set IDR encoding */
+ reg &= ~(0x1 << 2);
+ reg |= (p_hevc->num_refs_for_p - 1) << 2;
+ reg &= ~(0x1 << 5);
reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
+ reg &= ~(0x1 << 6);
reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
+ reg &= ~(0x1 << 7);
reg |= (p_hevc->wavefront_enable & 0x1) << 7;
+ reg &= ~(0x1 << 8);
reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
- reg |= (p_hevc->longterm_ref_enable & 0x1) << 10;
- reg |= (p_hevc->hier_qp & 0x1) << 11;
+ reg &= ~(0x1 << 9);
+ reg |= (p_hevc->loopfilter_across & 0x1) << 9;
+ reg &= ~(0x1 << 10);
+ reg |= (p_hevc->enable_ltr & 0x1) << 10;
+ reg &= ~(0x1 << 11);
+ reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
+ reg &= ~(0x1 << 12);
reg |= (p_hevc->sign_data_hiding & 0x1) << 12;
+ reg &= ~(0x1 << 13);
reg |= (p_hevc->general_pb_enable & 0x1) << 13;
+ reg &= ~(0x1 << 14);
reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
+ reg &= ~(0x1 << 15);
reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
+ reg &= ~(0x1 << 16);
reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
+ reg &= ~(0x1 << 17);
reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
+ reg &= ~(0x7 << 18);
reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
- /* reg |= (1 << 21); always eco mode disable */
+ reg &= ~(0x1 << 22);
reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 22;
+ reg &= ~(0x1 << 26);
+ reg |= (p_hevc->prepend_sps_pps_to_idr & 0x1) << 26;
WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS);
/* refresh period */
- if (p_hevc->refreshtype) {
- reg = 0;
- reg |= (p_hevc->refreshperiod & 0x1);
- WRITEL(reg, S5P_FIMV_E_HEVC_REFRESH_PERIOD);
- }
+ reg = READL(S5P_FIMV_E_HEVC_REFRESH_PERIOD);
+ reg &= ~(0xFFFF);
+ reg |= (p_hevc->refreshperiod & 0xFFFF);
+ WRITEL(reg, S5P_FIMV_E_HEVC_REFRESH_PERIOD);
/* loop filter setting */
- reg |= (p_hevc->loopfilter_disable & 0x01) << 8;
if (!p_hevc->loopfilter_disable) {
- reg = 0;
- reg |= (p_hevc->lf_beta_offset_div2 & 0x1);
- WRITEL(reg, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
- reg = 0;
- reg |= (p_hevc->lf_tc_offset_div2 & 0x1);
- WRITEL(reg, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
- reg = READL(S5P_FIMV_E_HEVC_OPTIONS);
- reg &= ~(0x1 << 9);
- reg |= (p_hevc->loopfilter_across & 0x1) << 9;
+ WRITEL(p_hevc->lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
+ WRITEL(p_hevc->lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
}
/* long term reference */
- if (p_hevc->longterm_ref_enable) {
+ if (p_hevc->enable_ltr) {
reg = 0;
reg |= (p_hevc->store_ref & 0x3);
reg &= ~(0x3 << 2);
reg |= (p_hevc->user_ref & 0x3) << 2;
WRITEL(reg, S5P_FIMV_E_HEVC_NAL_CONTROL);
}
- /* hier qp enable */
- if (p_hevc->hier_qp && p_hevc->hier_qp_layer) {
- reg |= (p_hevc->hier_qp_type & 0x1) << 0x3;
- reg |= p_hevc->hier_qp_layer & 0x7;
- /* number of coding layer should be zero when hierarchical is disable */
- WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
- /* QP value for each layer */
- for (i = 0; i < (p_hevc->hier_qp_layer & 0x7); i++)
- WRITEL(p_hevc->hier_qp_layer_qp,
- S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
- WRITEL(p_hevc->hier_qp_layer_bit,
- S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+
+ /* Temporal SVC - qp type, layer number */
+ reg = READL(S5P_FIMV_E_NUM_T_LAYER);
+ reg &= ~(0x1 << 3);
+ reg |= (p_hevc->hier_qp_type & 0x1) << 3;
+ reg &= ~(0x7);
+ reg |= p_hevc->num_hier_layer & 0x7;
+ reg &= ~(0x7 << 4);
+ if (p_hevc->hier_ref_type) {
+ reg |= 0x1 << 7;
+ reg |= (p->num_hier_max_layer & 0x7) << 4;
+ } else {
+ reg |= 0x7 << 4;
+ }
+ WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+ mfc_debug(2, "Temporal SVC: hier_qp_enable %d, enable_ltr %d, "
+ "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
+ p_hevc->hier_qp_enable, p_hevc->enable_ltr, p_hevc->num_hier_layer,
+ p->num_hier_max_layer, p_hevc->hier_ref_type, reg);
+
+ /* QP & Bitrate for each layer */
+ for (i = 0; i < 7; i++) {
+ WRITEL(p_hevc->hier_qp_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+ WRITEL(p_hevc->hier_bit_layer[i],
+ S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+ mfc_debug(3, "Temporal SVC: layer[%d] QP: %#x, bitrate: %#x\n",
+ i, p_hevc->hier_qp_layer[i],
+ p_hevc->hier_bit_layer[i]);
}
+
/* rate control config. */
reg = READL(S5P_FIMV_E_RC_CONFIG);
- /** macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p->rc_mb << 8);
- WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/** frame QP */
- reg &= ~(0x3F);
- reg |= p_hevc->rc_frame_qp;
+ reg &= ~(0x7F);
+ reg |= (p_hevc->rc_frame_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
/* frame rate */
-
p->rc_frame_delta = FRAME_DELTA_DEFAULT;
if (p->rc_frame) {
- reg = 0;
- reg &= ~(0xffff << 16);
+ reg = READL(S5P_FIMV_E_RC_FRAME_RATE);
+ reg &= ~(0xFFFF << 16);
reg |= ((p_hevc->rc_framerate * p->rc_frame_delta) << 16);
- reg &= ~(0xffff);
- reg |= p->rc_frame_delta;
+ reg &= ~(0xFFFF);
+ reg |= (p->rc_frame_delta & 0xFFFF);
WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
}
- /* max & min value of QP */
- reg = 0;
- /** max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_hevc->rc_max_qp << 8);
- /** min QP */
- reg &= ~(0x3F);
- reg |= p_hevc->rc_min_qp;
+ /* max & min value of QP for I frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND);
+ /** max I frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_hevc->rc_max_qp & 0x7F) << 8);
+ /** min I frame QP */
+ reg &= ~(0x7F);
+ reg |= (p_hevc->rc_min_qp & 0x7F);
WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+ /* max & min value of QP for P/B frame */
+ reg = READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+ /** max B frame QP */
+ reg &= ~(0x7F << 24);
+ reg |= ((p_hevc->rc_max_qp_b & 0x7F) << 24);
+ /** min B frame QP */
+ reg &= ~(0x7F << 16);
+ reg |= ((p_hevc->rc_min_qp_b & 0x7F) << 16);
+ /** max P frame QP */
+ reg &= ~(0x7F << 8);
+ reg |= ((p_hevc->rc_max_qp_p & 0x7F) << 8);
+ /** min P frame QP */
+ reg &= ~(0x7F);
+ reg |= p_hevc->rc_min_qp_p & 0x7F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
/* macroblock adaptive scaling features */
- WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG);
- if (p->rc_mb) {
- reg = 0;
- /** dark region */
- reg &= ~(0x1 << 3);
- reg |= (p_hevc->rc_lcu_dark << 3);
- /** smooth region */
- reg &= ~(0x1 << 2);
- reg |= (p_hevc->rc_lcu_smooth << 2);
- /** static region */
- reg &= ~(0x1 << 1);
- reg |= (p_hevc->rc_lcu_static << 1);
- /** high activity region */
- reg &= ~(0x1);
- reg |= p_hevc->rc_lcu_activity;
- WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
- }
- WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
- if (!p->rc_frame && !p->rc_mb) {
- reg = 0;
- reg &= ~(0x3f << 16);
- reg |= (p_hevc->rc_b_frame_qp << 16);
- reg &= ~(0x3f << 8);
- reg |= (p_hevc->rc_p_frame_qp << 8);
- reg &= ~(0x3f);
- reg |= p_hevc->rc_frame_qp;
- WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
- }
- mfc_debug_leave();
+ reg = READL(S5P_FIMV_E_MB_RC_CONFIG);
+ /* dark region */
+ reg &= ~(0x1 << 3);
+ reg |= ((p_hevc->rc_lcu_dark & 0x1) << 3);
+ /* smooth region */
+ reg &= ~(0x1 << 2);
+ reg |= ((p_hevc->rc_lcu_smooth & 0x1) << 2);
+ /* static region */
+ reg &= ~(0x1 << 1);
+ reg |= ((p_hevc->rc_lcu_static & 0x1) << 1);
+ /* high activity region */
+ reg &= ~(0x1);
+ reg |= (p_hevc->rc_lcu_activity & 0x1);
+ WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
+
+ reg = READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+ reg &= ~(0x7F << 24);
+ reg |= ((p->config_qp & 0x7F) << 24);
+ reg &= ~(0x7F << 16);
+ reg |= ((p_hevc->rc_b_frame_qp & 0x7F) << 16);
+ reg &= ~(0x7F << 8);
+ reg |= ((p_hevc->rc_p_frame_qp & 0x7F) << 8);
+ reg &= ~(0x7F);
+ reg |= (p_hevc->rc_frame_qp & 0x7F);
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+ mfc_debug_leave();
return 0;
}
@@ -2471,6 +2554,9 @@ static int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
if (dec->is_dual_dpb)
reg |= (0x1 << S5P_FIMV_D_OPT_DISPLAY_LINEAR_EN);
+ /* Parsing all including PPS */
+ reg |= (0x1 << S5P_FIMV_D_OPT_SPECIAL_PARSING_SHIFT);
+
WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
if (ctx->codec_mode == S5P_FIMV_CODEC_FIMV1_DEC) {
@@ -2515,6 +2601,10 @@ static int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
/* Enable realloc interface if SEI is enabled */
if (dec->sei_parse && FW_HAS_SEI_S3D_REALLOC(dev))
reg |= (0x1 << S5P_FIMV_D_SEI_NEED_INIT_BUFFER_SHIFT);
+
+ /* Enable recovery SEI parsing */
+ reg |= (0x1 << S5P_FIMV_D_SEI_RECOVERY_PARSING_ENABLE);
+
WRITEL(reg, S5P_FIMV_D_SEI_ENABLE);
WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
@@ -2632,6 +2722,109 @@ static int s5p_mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
return 0;
}
+static inline void s5p_mfc_set_stride_enc(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int i;
+
+ if (IS_MFCv7X(dev) || IS_MFCV8(dev)) {
+ for (i = 0; i < ctx->raw_buf.num_planes; i++) {
+ WRITEL(ctx->raw_buf.stride[i],
+ S5P_FIMV_E_SOURCE_FIRST_STRIDE + (i * 4));
+ mfc_debug(2, "enc src[%d] stride: 0x%08lx",
+ i, (unsigned long)ctx->raw_buf.stride[i]);
+ }
+ }
+}
+
+/*
+ When the resolution is changed,
+ s5p_mfc_start_change_resol_enc() should be called right before NAL_START.
+ return value
+ 0: no resolution change
+ 1: resolution swap
+ 2: resolution change
+*/
+int s5p_mfc_start_change_resol_enc(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc *enc = ctx->enc_priv;
+ struct s5p_mfc_enc_params *p = &enc->params;
+ unsigned int reg = 0;
+ int old_img_width;
+ int old_img_height;
+ int new_img_width;
+ int new_img_height;
+ int ret = 0;
+
+ if ((ctx->img_width == 0) || (ctx->img_height == 0)) {
+ mfc_err("new_img_width = %d, new_img_height = %d\n",
+ ctx->img_width, ctx->img_height);
+ return 0;
+ }
+
+ old_img_width = ctx->old_img_width;
+ old_img_height = ctx->old_img_height;
+
+ new_img_width = ctx->img_width;
+ new_img_height = ctx->img_height;
+
+ if ((old_img_width == new_img_width) && (old_img_height == new_img_height)) {
+ mfc_err("Resolution is not changed. new_img_width = %d, new_img_height = %d\n",
+ new_img_width, new_img_height);
+ return 0;
+ }
+
+ mfc_info_ctx("Resolution Change : (%d x %d) -> (%d x %d)\n",
+ old_img_width, old_img_height, new_img_width, new_img_height);
+
+ if (ctx->img_width) {
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+ }
+
+ if ((old_img_width == new_img_height) && (old_img_height == new_img_width)) {
+ reg = READL(S5P_FIMV_E_PARAM_CHANGE);
+ reg &= ~(0x1 << 6);
+ reg |= (0x1 << 6); /* resolution swap */
+ WRITEL(reg, S5P_FIMV_E_PARAM_CHANGE);
+ ret = 1;
+ } else {
+ reg = READL(S5P_FIMV_E_PARAM_CHANGE);
+ reg &= ~(0x3 << 7);
+ /* For now, FW does not care S5P_FIMV_E_PARAM_CHANGE is 1 or 2.
+ * It cares S5P_FIMV_E_PARAM_CHANGE is NOT zero.
+ */
+ if ((old_img_width*old_img_height) < (new_img_width*new_img_height)) {
+ reg |= (0x1 << 7); /* resolution increased */
+ mfc_info_ctx("Resolution Increased\n");
+ } else {
+ reg |= (0x2 << 7); /* resolution decreased */
+ mfc_info_ctx("Resolution Decreased\n");
+ }
+ WRITEL(reg, S5P_FIMV_E_PARAM_CHANGE);
+
+ /** set cropped width */
+ WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
+ /** set cropped height */
+ WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+
+ /* bit rate */
+ if (p->rc_frame)
+ WRITEL(p->rc_bitrate, S5P_FIMV_E_RC_BIT_RATE);
+ else
+ WRITEL(1000000, S5P_FIMV_E_RC_BIT_RATE);
+ ret = 2;
+ }
+
+ /** set new stride */
+ s5p_mfc_set_stride_enc(ctx);
+
+ /** set cropped offset */
+ WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
+
+ return ret;
+}
+
/* Encode a single frame */
int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
{
@@ -2644,6 +2837,11 @@ int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
s5p_mfc_set_slice_mode(ctx);
+ if (ctx->enc_drc_flag) {
+ ctx->enc_res_change = s5p_mfc_start_change_resol_enc(ctx);
+ ctx->enc_drc_flag = 0;
+ }
+
WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
/* Issue different commands to instance basing on whether it
* is the last frame or not. */
@@ -2768,8 +2966,13 @@ static inline int s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
temp_vb = list_entry(ctx->src_queue.next,
struct s5p_mfc_buf, list);
temp_vb->used = 1;
- s5p_mfc_set_dec_stream_buffer(ctx,
- s5p_mfc_mem_plane_addr(ctx, &temp_vb->vb, 0), 0, 0);
+ if (dec->consumed)
+ s5p_mfc_set_dec_stream_buffer(ctx,
+ s5p_mfc_mem_plane_addr(ctx, &temp_vb->vb, 0),
+ dec->consumed, dec->remained_size);
+ else
+ s5p_mfc_set_dec_stream_buffer(ctx,
+ s5p_mfc_mem_plane_addr(ctx, &temp_vb->vb, 0), 0, 0);
}
if (dec->is_dynamic_dpb) {
@@ -3130,21 +3333,6 @@ static inline int s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
return 0;
}
-static inline void s5p_mfc_set_stride_enc(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- int i;
-
- if (IS_MFCv7X(dev) || IS_MFCV8(dev)) {
- for (i = 0; i < ctx->raw_buf.num_planes; i++) {
- WRITEL(ctx->raw_buf.stride[i],
- S5P_FIMV_E_SOURCE_FIRST_STRIDE + (i * 4));
- mfc_debug(2, "enc src[%d] stride: 0x%08lx",
- i, (unsigned long)ctx->raw_buf.stride[i]);
- }
- }
-}
-
static inline int s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
@@ -3156,6 +3344,12 @@ static inline int s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
+ if (list_empty(&ctx->dst_queue)) {
+ mfc_debug(2, "no dst buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_addr = s5p_mfc_mem_plane_addr(ctx, &dst_mb->vb, 0);
dst_size = (unsigned int)vb2_plane_size(&dst_mb->vb, 0);
@@ -3386,6 +3580,7 @@ void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
ret = s5p_mfc_run_dec_last_frames(ctx);
break;
case MFCINST_RUNNING:
+ case MFCINST_SPECIAL_PARSING_NAL:
ret = s5p_mfc_run_dec_frame(ctx);
break;
case MFCINST_INIT:
@@ -3395,6 +3590,7 @@ void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
ret = s5p_mfc_close_inst(ctx);
break;
case MFCINST_GOT_INST:
+ case MFCINST_SPECIAL_PARSING:
ret = s5p_mfc_run_init_dec(ctx);
break;
case MFCINST_HEAD_PARSED:
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.h
old mode 100644
new mode 100755
index b20f72fe2647..6a94096d89e4
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v6.h
@@ -152,6 +152,7 @@ void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
#define ENC_MULTI_SLICE_BIT_MIN 2800
#define ENC_MULTI_SLICE_BYTE_MIN 350
+#define ENC_MULTI_SLICE_MB_ROW_MAX 255
#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
#define ENC_H264_LOOP_FILTER_AB_MIN -12
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v8.h b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v8.h
old mode 100644
new mode 100755
index ac0ac5b78663..1933c1bbef58
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v8.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v8.h
@@ -151,6 +151,7 @@ void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
#define ENC_MULTI_SLICE_BIT_MIN 2800
#define ENC_MULTI_SLICE_BYTE_MIN 350
+#define ENC_MULTI_SLICE_MB_ROW_MAX 255
#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
#define ENC_H264_LOOP_FILTER_AB_MIN -12
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v9.h b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v9.h
old mode 100644
new mode 100755
index 7644451748d1..9c47ba8fcc3c
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v9.h
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr_v9.h
@@ -148,28 +148,9 @@ void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
} while (0)
/* Definition */
-#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
-#define ENC_MULTI_SLICE_BIT_MIN 2800
-#define ENC_MULTI_SLICE_BYTE_MIN 350
-#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
-#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
-#define ENC_H264_LOOP_FILTER_AB_MIN -12
-#define ENC_H264_LOOP_FILTER_AB_MAX 12
-#define ENC_H264_RC_FRAME_RATE_MAX ((1 << 16) - 1)
-#define ENC_H263_RC_FRAME_RATE_MAX ((1 << 16) - 1)
-#define ENC_H264_PROFILE_MAX 3
-#define ENC_H264_LEVEL_MAX 42
-#define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1)
#define FRAME_DELTA_DEFAULT 1
#define TIGHT_CBR_MAX 10
#define I_LIMIT_CBR_MAX 5
-#define ENC_HEVC_RC_FRAME_RATE_MAX ((1 << 16) - 1)
-#define ENC_HEVC_QP_INDEX_MIN -12
-#define ENC_HEVC_QP_INDEX_MAX 12
-#define ENC_HEVC_LOOP_FILTER_MIN -12
-#define ENC_HEVC_LOOP_FILTER_MAX 12
-#define ENC_HEVC_RC_FRAME_RATE_MAX ((1 << 16) - 1)
-#define ENC_HEVC_LEVEL_MAX 62
/* Definitions for shared memory compatibility */
#define PIC_TIME_TOP S5P_FIMV_D_RET_PICTURE_TAG_TOP
@@ -233,12 +214,6 @@ void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
#define ENC_HEVC_ME_SIZE(x, y) \
((((x * 32 / 8 + 63) / 64 * 64) * ((y * 8) + 64)) + (x * y * 32))
-/* MV range is [16,256] for v6.1, [16,128] for v6.5 */
-#define ENC_V61_MV_RANGE 256
-#define ENC_V65_MV_RANGE 128
-/* MV range is [16,32] for v7.8 */
-#define ENC_V78_MV_RANGE 32
-
#define NUM_MPEG4_LF_BUF 2
/* Scratch buffer size for MFC v8.0 */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_pm.c b/drivers/media/platform/exynos/mfc/s5p_mfc_pm.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_pm.h b/drivers/media/platform/exynos/mfc/s5p_mfc_pm.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c b/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
old mode 100644
new mode 100755
index cce9e2f0d831..7ad9a83a7e8e
--- a/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
+++ b/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
@@ -36,7 +36,9 @@ static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
struct s5p_mfc_platdata *pdata = dev->pdata;
struct s5p_mfc_qos *qos_table = pdata->qos_table;
- if (ctx->buf_process_type & MFCBUFPROC_COPY) {
+ if (ctx->qos_changed)
+ ctx->qos_changed = 0;
+ if (ctx->use_extra_qos) {
if (pdata->qos_extra[idx].thrd_mb != MFC_QOS_FLAG_NODATA) {
qos_table = pdata->qos_extra;
#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
@@ -85,7 +87,7 @@ static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
qos_table[idx].freq_kfc);
#endif
atomic_set(&dev->qos_req_cur, idx + 1);
- mfc_dbg_ctx("QoS request: %d\n", idx + 1);
+ mfc_info_ctx("QoS request: %d\n", idx + 1);
break;
case MFC_QOS_UPDATE:
if (dev->curr_rate < qos_table[idx].freq_mfc) {
@@ -131,7 +133,7 @@ static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
qos_table[idx].freq_kfc);
#endif
atomic_set(&dev->qos_req_cur, idx + 1);
- mfc_dbg_ctx("QoS update: %d\n", idx + 1);
+ mfc_info_ctx("QoS update: %d\n", idx + 1);
break;
case MFC_QOS_REMOVE:
MFC_TRACE_CTX("++ QOS remove(prev mfc:%d)\n",
@@ -154,7 +156,7 @@ static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
pm_qos_remove_request(&dev->qos_req_cluster0);
#endif
atomic_set(&dev->qos_req_cur, 0);
- mfc_dbg_ctx("QoS remove\n");
+ mfc_info_ctx("QoS remove\n");
break;
default:
mfc_err_ctx("Unknown request for opr [%d]\n", opr_type);
@@ -173,7 +175,7 @@ static void mfc_qos_print(struct s5p_mfc_ctx *ctx,
qos_table[index].freq_cpu);
#endif
#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
- mfc_dbg_ctx("\tint: %d(%d), mif: %d, cpu: %d, kfc: %d\n",
+ mfc_info_ctx("\tint: %d(%d), mif: %d, cpu: %d, kfc: %d\n",
qos_table[index].freq_int,
qos_table[index].freq_mfc,
qos_table[index].freq_mif,
@@ -211,6 +213,9 @@ static void mfc_qos_add_or_update(struct s5p_mfc_ctx *ctx, int total_mb)
} else if (atomic_read(&dev->qos_req_cur) != (i + 1)) {
mfc_qos_print(ctx, qos_table, i);
mfc_qos_operate(ctx, MFC_QOS_UPDATE, i);
+ } else if (atomic_read(&dev->qos_req_cur) == (i + 1) &&
+ ctx->qos_changed) {
+ mfc_qos_operate(ctx, MFC_QOS_UPDATE, i);
}
break;
}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.h b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.h
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_shm.c b/drivers/media/platform/exynos/mfc/s5p_mfc_shm.c
old mode 100644
new mode 100755
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_shm.h b/drivers/media/platform/exynos/mfc/s5p_mfc_shm.h
old mode 100644
new mode 100755
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
old mode 100644
new mode 100755
index 69bd5bb0d5af..90c6ccfd97d6
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -358,8 +358,9 @@ enum v4l2_mpeg_video_header_mode {
#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE (V4L2_CID_MPEG_BASE+221)
enum v4l2_mpeg_video_multi_slice_mode {
V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE = 0,
- V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB = 1,
- V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2,
+ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB = 1,
+ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES = 2,
+ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW = 3,
};
#define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222)
#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_MPEG_BASE+223)
@@ -431,6 +432,7 @@ enum v4l2_mpeg_video_h264_profile {
V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA = 14,
V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH = 15,
V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH = 16,
+ V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH = 17,
};
#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT (V4L2_CID_MPEG_BASE+364)
#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH (V4L2_CID_MPEG_BASE+365)
diff --git a/include/uapi/linux/videodev2_exynos_media.h b/include/uapi/linux/videodev2_exynos_media.h
old mode 100644
new mode 100755
index abb64fdc078f..21927206676a
--- a/include/uapi/linux/videodev2_exynos_media.h
+++ b/include/uapi/linux/videodev2_exynos_media.h
@@ -322,6 +322,26 @@ enum v4l2_mpeg_mfc51_video_frame_type {
(V4L2_CID_MPEG_MFC_BASE + 97)
#define V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE \
(V4L2_CID_MPEG_MFC_BASE + 98)
+#define V4L2_CID_MPEG_MFC_GET_10BIT_INFO \
+ (V4L2_CID_MPEG_MFC_BASE + 99)
+#define V4L2_CID_MPEG_MFC_H264_ENABLE_LTR \
+ (V4L2_CID_MPEG_MFC_BASE + 100)
+#define V4L2_CID_MPEG_MFC_H264_MARK_LTR \
+ (V4L2_CID_MPEG_MFC_BASE + 101)
+#define V4L2_CID_MPEG_MFC_H264_USE_LTR \
+ (V4L2_CID_MPEG_MFC_BASE + 102)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW \
+ (V4L2_CID_MPEG_MFC_BASE + 103)
+#define V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY \
+ (V4L2_CID_MPEG_MFC_BASE + 104)
+#define V4L2_CID_MPEG_MFC_CONFIG_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 105)
+#define V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE \
+ (V4L2_CID_MPEG_MFC_BASE + 106)
+#define V4L2_CID_MPEG_MFC_GET_DRIVER_INFO \
+ (V4L2_CID_MPEG_MFC_BASE + 107)
+#define V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE \
+ (V4L2_CID_MPEG_MFC_BASE + 108)
/* CIDs for HEVC encoding. Number gaps are for compatibility */
@@ -339,12 +359,14 @@ enum v4l2_mpeg_mfc51_video_frame_type {
(V4L2_CID_MPEG_MFC_BASE + 115)
#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE \
(V4L2_CID_MPEG_MFC_BASE + 116)
+enum v4l2_mpeg_video_hevc_hierarchical_coding_type {
+ V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B = 0,
+ V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P = 1,
+};
#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER \
(V4L2_CID_MPEG_MFC_BASE + 117)
#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP \
(V4L2_CID_MPEG_MFC_BASE + 118)
-#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT \
- (V4L2_CID_MPEG_MFC_BASE + 119)
#define V4L2_CID_MPEG_VIDEO_HEVC_PROFILE \
(V4L2_CID_MPEG_MFC_BASE + 120)
#define V4L2_CID_MPEG_VIDEO_HEVC_LEVEL \
@@ -411,4 +433,106 @@ enum v4l2_mpeg_mfc51_video_frame_type {
(V4L2_CID_MPEG_MFC_BASE + 151)
#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD \
(V4L2_CID_MPEG_MFC_BASE + 152)
+#define V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR \
+ (V4L2_CID_MPEG_MFC_BASE + 153)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH \
+ (V4L2_CID_MPEG_MFC_BASE + 154)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0 \
+ (V4L2_CID_MPEG_MFC_BASE + 155)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1 \
+ (V4L2_CID_MPEG_MFC_BASE + 156)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2 \
+ (V4L2_CID_MPEG_MFC_BASE + 157)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3 \
+ (V4L2_CID_MPEG_MFC_BASE + 158)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4 \
+ (V4L2_CID_MPEG_MFC_BASE + 159)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5 \
+ (V4L2_CID_MPEG_MFC_BASE + 160)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6 \
+ (V4L2_CID_MPEG_MFC_BASE + 161)
+#define V4L2_CID_MPEG_VIDEO_VP9_VERSION \
+ (V4L2_CID_MPEG_MFC_BASE + 163)
+#define V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE \
+ (V4L2_CID_MPEG_MFC_BASE + 164)
+#define V4L2_CID_MPEG_VIDEO_VP9_MIN_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 165)
+#define V4L2_CID_MPEG_VIDEO_VP9_MAX_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 166)
+#define V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 167)
+#define V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 168)
+#define V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL \
+ (V4L2_CID_MPEG_MFC_BASE + 169)
+#define V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD \
+ (V4L2_CID_MPEG_MFC_BASE + 170)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE \
+ (V4L2_CID_MPEG_MFC_BASE + 171)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP \
+ (V4L2_CID_MPEG_MFC_BASE + 172)
+#define V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES \
+ (V4L2_CID_MPEG_MFC_BASE + 173)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER \
+ (V4L2_CID_MPEG_MFC_BASE + 174)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH \
+ (V4L2_CID_MPEG_MFC_BASE + 175)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0 \
+ (V4L2_CID_MPEG_MFC_BASE + 176)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1 \
+ (V4L2_CID_MPEG_MFC_BASE + 177)
+#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2 \
+ (V4L2_CID_MPEG_MFC_BASE + 178)
+#define V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH \
+ (V4L2_CID_MPEG_MFC_BASE + 179)
+#define V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT \
+ (V4L2_CID_MPEG_MFC_BASE + 180)
+#define V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER \
+ (V4L2_CID_MPEG_MFC_BASE + 181)
+
+/* CIDs for new common interface */
+#define V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER \
+ (V4L2_CID_MPEG_MFC_BASE + 193)
+#define V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT \
+ (V4L2_CID_MPEG_MFC_BASE + 194)
+#define V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR \
+ (V4L2_CID_MPEG_MFC_BASE + 195)
+
+/* QP BOUND interface */
+#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 201)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 202)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 203)
+#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 204)
+#define V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 205)
+#define V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 206)
+#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 207)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 208)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 209)
+#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 210)
+#define V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 211)
+#define V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P \
+ (V4L2_CID_MPEG_MFC_BASE + 212)
+#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 213)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 214)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 215)
+#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 216)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 217)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B \
+ (V4L2_CID_MPEG_MFC_BASE + 218)
#endif /* __LINUX_VIDEODEV2_EXYNOS_MEDIA_H */
--
2.20.1