From e9eb0f878b6c2173654d6d7780fd1babc427ccea Mon Sep 17 00:00:00 2001 From: "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 #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