Re: [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x

Kyungmin Park
2012-07-06T14:21:26Z

Hi,

On Fri, Jul 6, 2012 at 11:00 PM, Arun Kumar K <arun.kk@samsung.com> wrote:
> From: Jeongtae Park <jtp.park@samsung.com>
>
> Multi Format Codec 6.x is a hardware video coding acceleration
> module fount in new Exynos5 SoC series.
> It is capable of handling a range of video codecs and this driver
> provides a V4L2 interface for video decoding and encoding.
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Singed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
> Singed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/media/video/Kconfig | 16 +-
> drivers/media/video/s5p-mfc/Makefile | 7 +-
> drivers/media/video/s5p-mfc/regs-mfc-v6.h | 676 ++++++++++
> drivers/media/video/s5p-mfc/regs-mfc.h | 29 +
> drivers/media/video/s5p-mfc/s5p_mfc.c | 163 ++-
> drivers/media/video/s5p-mfc/s5p_mfc_cmd.c | 6 +-
> drivers/media/video/s5p-mfc/s5p_mfc_cmd.h | 3 +
> drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c | 96 ++
> drivers/media/video/s5p-mfc/s5p_mfc_common.h | 123 ++-
> drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c | 160 ++-
> drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h | 1 +
> drivers/media/video/s5p-mfc/s5p_mfc_dec.c | 210 +++-
> drivers/media/video/s5p-mfc/s5p_mfc_dec.h | 1 +
> drivers/media/video/s5p-mfc/s5p_mfc_enc.c | 191 ++--
> drivers/media/video/s5p-mfc/s5p_mfc_enc.h | 1 +
> drivers/media/video/s5p-mfc/s5p_mfc_intr.c | 1 -
> drivers/media/video/s5p-mfc/s5p_mfc_opr.c | 278 +++--
> drivers/media/video/s5p-mfc/s5p_mfc_opr.h | 25 +-
> drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c | 1697 ++++++++++++++++++++++++++
> drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h | 140 +++
> drivers/media/video/s5p-mfc/s5p_mfc_pm.c | 6 +-
> drivers/media/video/s5p-mfc/s5p_mfc_shm.c | 28 +-
> drivers/media/video/s5p-mfc/s5p_mfc_shm.h | 13 +-
> drivers/media/video/v4l2-ctrls.c | 1 -
> 24 files changed, 3476 insertions(+), 396 deletions(-)

Doesn't it too big for one patch? Can you split it into several patches?

> create mode 100644 drivers/media/video/s5p-mfc/regs-mfc-v6.h
> create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
>
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 99937c9..0d7fe77 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -1198,13 +1198,27 @@ config VIDEO_SAMSUNG_S5P_JPEG
> This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
>
> config VIDEO_SAMSUNG_S5P_MFC
> + bool
> +
> +config VIDEO_SAMSUNG_S5P_MFC_V5
> tristate "Samsung S5P MFC 5.1 Video Codec"
> - depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
> + depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS4
> + select VIDEO_SAMSUNG_S5P_MFC
> select VIDEOBUF2_DMA_CONTIG
> default n
> help
> MFC 5.1 driver for V4L2.
>
> +config VIDEO_SAMSUNG_S5P_MFC_V6

Yes, I know it's exynos5 series features. however, it's not good idea
to add new config.
It already handled platform device with proper name.
e.g., s5p-mfc-v5, s5p-mfc-v6 and handle it with platform data.

> + tristate "Samsung S5P MFC 6.x Video Codec"
> + depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS5
> + select VIDEO_SAMSUNG_S5P_MFC
> + select VIDEOBUF2_DMA_CONTIG
> + select DMA_SHARED_BUFFER
> + default n
> + help
> + MFC 6.x driver for V4L2.
> +
> config VIDEO_MX2_EMMAPRP
> tristate "MX2 eMMa-PrP support"
> depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27
> diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/video/s5p-mfc/Makefile
> index d066340..0308d74 100644
> --- a/drivers/media/video/s5p-mfc/Makefile
> +++ b/drivers/media/video/s5p-mfc/Makefile
> @@ -1,5 +1,6 @@
> obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> -s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> +s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
> s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> -s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> -s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
> +s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5) += s5p_mfc_opr.o s5p_mfc_cmd.o s5p_mfc_shm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6) += s5p_mfc_opr_v6.o s5p_mfc_cmd_v6.o
> diff --git a/drivers/media/video/s5p-mfc/regs-mfc-v6.h b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> new file mode 100644
> index 0000000..f22a159
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> @@ -0,0 +1,676 @@
> +/*
> + * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _REGS_FIMV_V6_H
> +#define _REGS_FIMV_V6_H
> +
> +#define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
> +#define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
> +
> +/* Number of bits that the buffer address should be shifted for particular
> + * MFC buffers. */
> +#define S5P_FIMV_MEM_OFFSET 0
> +
> +#define S5P_FIMV_START_ADDR 0x0000
> +#define S5P_FIMV_END_ADDR 0xfd80
> +
> +#define S5P_FIMV_REG_CLEAR_BEGIN 0xf000
> +#define S5P_FIMV_REG_CLEAR_COUNT 1024
> +
> +/* Codec Common Registers */
> +#define S5P_FIMV_RISC_ON 0x0000
> +#define S5P_FIMV_RISC2HOST_INT 0x003C
> +#define S5P_FIMV_HOST2RISC_INT 0x0044
> +#define S5P_FIMV_RISC_BASE_ADDRESS 0x0054
> +
> +#define S5P_FIMV_MFC_RESET 0x1070
> +
> +#define S5P_FIMV_HOST2RISC_CMD 0x1100
> +#define S5P_FIMV_H2R_CMD_EMPTY 0
> +#define S5P_FIMV_H2R_CMD_SYS_INIT 1
> +#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE 2
> +#define S5P_FIMV_CH_SEQ_HEADER 3
> +#define S5P_FIMV_CH_INIT_BUFS 4
> +#define S5P_FIMV_CH_FRAME_START 5
> +#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE 6
> +#define S5P_FIMV_H2R_CMD_SLEEP 7
> +#define S5P_FIMV_H2R_CMD_WAKEUP 8
> +#define S5P_FIMV_CH_LAST_FRAME 9
> +#define S5P_FIMV_H2R_CMD_FLUSH 10
> +/* RMVME: REALLOC used? */
> +#define S5P_FIMV_CH_FRAME_START_REALLOC 5
> +
> +#define S5P_FIMV_RISC2HOST_CMD 0x1104
> +#define S5P_FIMV_R2H_CMD_EMPTY 0
> +#define S5P_FIMV_R2H_CMD_SYS_INIT_RET 1
> +#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET 2
> +#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET 3
> +#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET 4
> +
> +#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET 6
> +#define S5P_FIMV_R2H_CMD_SLEEP_RET 7
> +#define S5P_FIMV_R2H_CMD_WAKEUP_RET 8
> +#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET 9
> +#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET 10
> +#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET 11
> +#define S5P_FIMV_R2H_CMD_FW_STATUS_RET 12
> +#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_FUL_RET 16
> +#define S5P_FIMV_R2H_CMD_ERR_RET 32
> +
> +#define S5P_FIMV_FW_VERSION 0xF000
> +
> +#define S5P_FIMV_INSTANCE_ID 0xF008
> +#define S5P_FIMV_CODEC_TYPE 0xF00C
> +#define S5P_FIMV_CONTEXT_MEM_ADDR 0xF014
> +#define S5P_FIMV_CONTEXT_MEM_SIZE 0xF018
> +#define S5P_FIMV_PIXEL_FORMAT 0xF020
> +
> +#define S5P_FIMV_METADATA_ENABLE 0xF024
> +#define S5P_FIMV_DBG_BUFFER_ADDR 0xF030
> +#define S5P_FIMV_DBG_BUFFER_SIZE 0xF034
> +#define S5P_FIMV_RET_INSTANCE_ID 0xF070
> +
> +#define S5P_FIMV_ERROR_CODE 0xF074
> +#define S5P_FIMV_ERR_WARNINGS_START 160
> +#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
> +#define S5P_FIMV_ERR_DEC_SHIFT 0
> +#define S5P_FIMV_ERR_DSPL_MASK 0xFFFF0000
> +#define S5P_FIMV_ERR_DSPL_SHIFT 16
> +
> +#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE 0xF078
> +#define S5P_FIMV_METADATA_STATUS 0xF07C
> +#define S5P_FIMV_METADATA_ADDR_MB_INFO 0xF080
> +#define S5P_FIMV_METADATA_SIZE_MB_INFO 0xF084
> +
> +/* Decoder Registers */
> +#define S5P_FIMV_D_CRC_CTRL 0xF0B0
> +#define S5P_FIMV_D_DEC_OPTIONS 0xF0B4
> +#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK 4
> +#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT 3
> +#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT 1
> +#define S5P_FIMV_D_OPT_LF_CTRL_MASK 0x3
> +#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT 0
> +
> +#define S5P_FIMV_D_DISPLAY_DELAY 0xF0B8
> +
> +#define S5P_FIMV_D_SET_FRAME_WIDTH 0xF0BC
> +#define S5P_FIMV_D_SET_FRAME_HEIGHT 0xF0C0
> +
> +#define S5P_FIMV_D_SEI_ENABLE 0xF0C4
> +
> +/* Buffer setting registers */
> +#define S5P_FIMV_D_MIN_NUM_DPB 0xF0F0
> +#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE 0xF0F4
> +#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE 0xF0F8
> +#define S5P_FIMV_D_MVC_NUM_VIEWS 0xF0FC
> +#define S5P_FIMV_D_NUM_DPB 0xF130
> +#define S5P_FIMV_D_LUMA_DPB_SIZE 0xF134
> +#define S5P_FIMV_D_CHROMA_DPB_SIZE 0xF138
> +#define S5P_FIMV_D_MV_BUFFER_SIZE 0xF13C
> +
> +#define S5P_FIMV_D_LUMA_DPB 0xF140
> +#define S5P_FIMV_D_CHROMA_DPB 0xF240
> +#define S5P_FIMV_D_MV_BUFFER 0xF340
> +
> +#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR 0xF440
> +#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE 0xF444
> +#define S5P_FIMV_D_METADATA_BUFFER_ADDR 0xF448
> +#define S5P_FIMV_D_METADATA_BUFFER_SIZE 0xF44C
> +#define S5P_FIMV_D_CPB_BUFFER_ADDR 0xF4B0
> +#define S5P_FIMV_D_CPB_BUFFER_SIZE 0xF4B4
> +
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER 0xF4B8
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER 0xF4BC
> +#define S5P_FIMV_D_CPB_BUFFER_OFFSET 0xF4C0
> +#define S5P_FIMV_D_SLICE_IF_ENABLE 0xF4C4
> +#define S5P_FIMV_D_PICTURE_TAG 0xF4C8
> +#define S5P_FIMV_D_STREAM_DATA_SIZE 0xF4D0
> +
> +/* Display information register */
> +#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH 0xF500
> +#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT 0xF504
> +
> +/* Display status */
> +#define S5P_FIMV_D_DISPLAY_STATUS 0xF508
> +#define S5P_FIMV_DEC_STATUS_DECODING_ONLY 0
> +#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY 1
> +#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY 2
> +#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY 3
> +#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK 7
> +#define S5P_FIMV_DEC_STATUS_PROGRESSIVE (0<<3)
> +#define S5P_FIMV_DEC_STATUS_INTERLACE (1<<3)
> +#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK (1<<3)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4
> +#define S5P_FIMV_DEC_STATUS_CRC_GENERATED (1<<5)
> +#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED (0<<5)
> +#define S5P_FIMV_DEC_STATUS_CRC_MASK (1<<5)
> +
> +#define S5P_FIMV_D_DISPLAY_LUMA_ADDR 0xF50C
> +#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR 0xF510
> +
> +#define S5P_FIMV_D_DISPLAY_FRAME_TYPE 0xF514
> +#define S5P_FIMV_DECODE_FRAME_SKIPPED 0
> +#define S5P_FIMV_DECODE_FRAME_I_FRAME 1
> +#define S5P_FIMV_DECODE_FRAME_P_FRAME 2
> +#define S5P_FIMV_DECODE_FRAME_B_FRAME 3
> +#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME 4
> +#define S5P_FIMV_SHARED_CROP_INFO_H 0x0020
> +#define S5P_FIMV_SHARED_CROP_LEFT_MASK 0xFFFF
> +#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT 0
> +#define S5P_FIMV_SHARED_CROP_RIGHT_MASK 0xFFFF0000
> +#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT 16
> +#define S5P_FIMV_SHARED_CROP_INFO_V 0x0024
> +#define S5P_FIMV_SHARED_CROP_TOP_MASK 0xFFFF
> +#define S5P_FIMV_SHARED_CROP_TOP_SHIFT 0
> +#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK 0xFFFF0000
> +#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT 16
> +
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO1 0xF518
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO2 0xF51C
> +#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE 0xF520
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP 0xF524
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP 0xF528
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT 0xF52C
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT 0xF530
> +#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO 0xF534
> +#define S5P_FIMV_D_DISPLAY_EXTENDED_AR 0xF538
> +
> +/* Decoded picture information register */
> +#define S5P_FIMV_D_DECODED_FRAME_WIDTH 0xF53C
> +#define S5P_FIMV_D_DECODED_FRAME_HEIGHT 0xF540
> +#define S5P_FIMV_D_DECODED_STATUS 0xF544
> +#define S5P_FIMV_DEC_CRC_GEN_MASK 0x1
> +#define S5P_FIMV_DEC_CRC_GEN_SHIFT 6
> +
> +#define S5P_FIMV_D_DECODED_LUMA_ADDR 0xF548
> +#define S5P_FIMV_D_DECODED_CHROMA_ADDR 0xF54C
> +
> +#define S5P_FIMV_D_DECODED_FRAME_TYPE 0xF550
> +#define S5P_FIMV_DECODE_FRAME_MASK 7
> +
> +#define S5P_FIMV_D_DECODED_CROP_INFO1 0xF554
> +#define S5P_FIMV_D_DECODED_CROP_INFO2 0xF558
> +#define S5P_FIMV_D_DECODED_PICTURE_PROFILE 0xF55C
> +#define S5P_FIMV_D_DECODED_NAL_SIZE 0xF560
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP 0xF564
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP 0xF568
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT 0xF56C
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT 0xF570
> +
> +/* Returned value register for specific setting */
> +#define S5P_FIMV_D_RET_PICTURE_TAG_TOP 0xF574
> +#define S5P_FIMV_D_RET_PICTURE_TAG_BOT 0xF578
> +#define S5P_FIMV_D_RET_PICTURE_TIME_TOP 0xF57C
> +#define S5P_FIMV_D_RET_PICTURE_TIME_BOT 0xF580
> +#define S5P_FIMV_D_CHROMA_FORMAT 0xF588
> +#define S5P_FIMV_D_MPEG4_INFO 0xF58C
> +#define S5P_FIMV_D_H264_INFO 0xF590
> +
> +#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB 0xF594
> +#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB 0xF598
> +#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM 0xF59C
> +#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM 0xF5A0
> +#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL 0xF5A4
> +#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL 0xF5A8
> +#define S5P_FIMV_D_METADATA_ADDR_VUI 0xF5AC
> +#define S5P_FIMV_D_METADATA_SIZE_VUI 0xF5B0
> +
> +#define S5P_FIMV_D_MVC_VIEW_ID 0xF5B4
> +
> +/* SEI related information */
> +#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL 0xF5F0
> +#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID 0xF5F4
> +#define S5P_FIMV_D_FRAME_PACK_SEI_INFO 0xF5F8
> +#define S5P_FIMV_D_FRAME_PACK_GRID_POS 0xF5FC
> +
> +/* Encoder Registers */
> +#define S5P_FIMV_E_FRAME_WIDTH 0xF770
> +#define S5P_FIMV_E_FRAME_HEIGHT 0xF774
> +#define S5P_FIMV_E_CROPPED_FRAME_WIDTH 0xF778
> +#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT 0xF77C
> +#define S5P_FIMV_E_FRAME_CROP_OFFSET 0xF780
> +#define S5P_FIMV_E_ENC_OPTIONS 0xF784
> +#define S5P_FIMV_E_PICTURE_PROFILE 0xF788
> +#define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
> +#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_MPEG4_SIMPLE 0
> +#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
> +#define S5P_FIMV_E_FIXED_PICTURE_QP 0xF790
> +
> +#define S5P_FIMV_E_RC_CONFIG 0xF794
> +#define S5P_FIMV_E_RC_QP_BOUND 0xF798
> +#define S5P_FIMV_E_RC_RPARAM 0xF79C
> +#define S5P_FIMV_E_MB_RC_CONFIG 0xF7A0
> +#define S5P_FIMV_E_PADDING_CTRL 0xF7A4
> +#define S5P_FIMV_E_MV_HOR_RANGE 0xF7AC
> +#define S5P_FIMV_E_MV_VER_RANGE 0xF7B0
> +
> +#define S5P_FIMV_E_VBV_BUFFER_SIZE 0xF84C
> +#define S5P_FIMV_E_VBV_INIT_DELAY 0xF850
> +#define S5P_FIMV_E_NUM_DPB 0xF890
> +#define S5P_FIMV_E_LUMA_DPB 0xF8C0
> +#define S5P_FIMV_E_CHROMA_DPB 0xF904
> +#define S5P_FIMV_E_ME_BUFFER 0xF948
> +
> +#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR 0xF98C
> +#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE 0xF990
> +#define S5P_FIMV_E_TMV_BUFFER0 0xF994
> +#define S5P_FIMV_E_TMV_BUFFER1 0xF998
> +#define S5P_FIMV_E_SOURCE_LUMA_ADDR 0xF9F0
> +#define S5P_FIMV_E_SOURCE_CHROMA_ADDR 0xF9F4
> +#define S5P_FIMV_E_STREAM_BUFFER_ADDR 0xF9F8
> +#define S5P_FIMV_E_STREAM_BUFFER_SIZE 0xF9FC
> +#define S5P_FIMV_E_ROI_BUFFER_ADDR 0xFA00
> +
> +#define S5P_FIMV_E_PARAM_CHANGE 0xFA04
> +#define S5P_FIMV_E_IR_SIZE 0xFA08
> +#define S5P_FIMV_E_GOP_CONFIG 0xFA0C
> +#define S5P_FIMV_E_MSLICE_MODE 0xFA10
> +#define S5P_FIMV_E_MSLICE_SIZE_MB 0xFA14
> +#define S5P_FIMV_E_MSLICE_SIZE_BITS 0xFA18
> +#define S5P_FIMV_E_FRAME_INSERTION 0xFA1C
> +
> +#define S5P_FIMV_E_RC_FRAME_RATE 0xFA20
> +#define S5P_FIMV_E_RC_BIT_RATE 0xFA24
> +#define S5P_FIMV_E_RC_QP_OFFSET 0xFA28
> +#define S5P_FIMV_E_RC_ROI_CTRL 0xFA2C
> +#define S5P_FIMV_E_PICTURE_TAG 0xFA30
> +#define S5P_FIMV_E_BIT_COUNT_ENABLE 0xFA34
> +#define S5P_FIMV_E_MAX_BIT_COUNT 0xFA38
> +#define S5P_FIMV_E_MIN_BIT_COUNT 0xFA3C
> +
> +#define S5P_FIMV_E_METADATA_BUFFER_ADDR 0xFA40
> +#define S5P_FIMV_E_METADATA_BUFFER_SIZE 0xFA44
> +#define S5P_FIMV_E_STREAM_SIZE 0xFA80
> +#define S5P_FIMV_E_SLICE_TYPE 0xFA84
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED 0
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_I 1
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_P 2
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_B 3
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED 4
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS 5
> +#define S5P_FIMV_E_PICTURE_COUNT 0xFA88
> +#define S5P_FIMV_E_RET_PICTURE_TAG 0xFA8C
> +#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER 0xFA90
> +
> +#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR 0xFA94
> +#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR 0xFA98
> +#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR 0xFA9C
> +#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR 0xFAA0
> +#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE 0xFAA4
> +#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE 0xFAA8
> +
> +#define S5P_FIMV_E_MPEG4_OPTIONS 0xFB10
> +#define S5P_FIMV_E_MPEG4_HEC_PERIOD 0xFB14
> +#define S5P_FIMV_E_ASPECT_RATIO 0xFB50
> +#define S5P_FIMV_E_EXTENDED_SAR 0xFB54
> +
> +#define S5P_FIMV_E_H264_OPTIONS 0xFB58
> +#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
> +
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE 0xFB68
> +#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1 0xFB6C
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR 0xFB70
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1 0xFB74
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 0xFB78
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1 0xFB7C
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2 0xFB80
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3 0xFB84
> +
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 0xFB88
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1 0xFB8C
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2 0xFB90
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3 0xFB94
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4 0xFB98
> +#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_H264_NUM_T_LAYER 0xFBAC
> +
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 0xFBB0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1 0xFBB4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2 0xFBB8
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3 0xFBBC
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4 0xFBC0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5 0xFBC4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6 0xFBC8
> +
> +#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE 0
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM 1
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL 2
> +
> +#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1 0xFD40
> +#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1 0xFD44
> +#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1 0xFD48
> +#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1 0xFD4C
> +#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1 0xFD50
> +#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON 0xFD80
> +
> +/* Codec numbers */
> +#define S5P_FIMV_CODEC_NONE -1
> +
> +
> +#define S5P_FIMV_CODEC_H264_DEC 0
> +#define S5P_FIMV_CODEC_H264_MVC_DEC 1
> +
> +#define S5P_FIMV_CODEC_MPEG4_DEC 3
> +#define S5P_FIMV_CODEC_FIMV1_DEC 4
> +#define S5P_FIMV_CODEC_FIMV2_DEC 5
> +#define S5P_FIMV_CODEC_FIMV3_DEC 6
> +#define S5P_FIMV_CODEC_FIMV4_DEC 7
> +#define S5P_FIMV_CODEC_H263_DEC 8
> +#define S5P_FIMV_CODEC_VC1RCV_DEC 9
> +#define S5P_FIMV_CODEC_VC1_DEC 10
> +/* FIXME: Add 11~12 */
> +#define S5P_FIMV_CODEC_MPEG2_DEC 13
> +#define S5P_FIMV_CODEC_VP8_DEC 14
> +/* FIXME: Add 15~16 */
> +#define S5P_FIMV_CODEC_H264_ENC 20
> +#define S5P_FIMV_CODEC_H264_MVC_ENC 21
> +
> +#define S5P_FIMV_CODEC_MPEG4_ENC 23
> +#define S5P_FIMV_CODEC_H263_ENC 24
> +/*** Definitions for MFCv5 compatibility ***/
> +#define S5P_FIMV_SI_DISPLAY_Y_ADR S5P_FIMV_D_DISPLAY_LUMA_ADDR
> +#define S5P_FIMV_SI_DISPLAY_C_ADR S5P_FIMV_D_DISPLAY_CHROMA_ADDR
> +
> +#define S5P_FIMV_CRC_LUMA0 S5P_FIMV_D_DECODED_LUMA_CRC_TOP
> +#define S5P_FIMV_CRC_CHROMA0 S5P_FIMV_D_DECODED_CHROMA_CRC_TOP
> +#define S5P_FIMV_CRC_LUMA1 S5P_FIMV_D_DECODED_LUMA_CRC_BOT
> +#define S5P_FIMV_CRC_CHROMA1 S5P_FIMV_D_DECODED_CHROMA_CRC_BOT
> +#define S5P_FIMV_CRC_DISP_LUMA0 S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP
> +#define S5P_FIMV_CRC_DISP_CHROMA0 S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP
> +
> +#define S5P_FIMV_SI_DECODED_STATUS S5P_FIMV_D_DECODED_STATUS
> +#define S5P_FIMV_SI_DISPLAY_STATUS S5P_FIMV_D_DISPLAY_STATUS
> +#define S5P_FIMV_SHARED_SET_FRAME_TAG S5P_FIMV_D_PICTURE_TAG
> +#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP S5P_FIMV_D_RET_PICTURE_TAG_TOP
> +#define S5P_FIMV_CRC_DISP_STATUS S5P_FIMV_D_DISPLAY_STATUS
> +
> +/* SEI related information */
> +#define S5P_FIMV_FRAME_PACK_SEI_AVAIL S5P_FIMV_D_FRAME_PACK_SEI_AVAIL
> +#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID
> +#define S5P_FIMV_FRAME_PACK_SEI_INFO S5P_FIMV_D_FRAME_PACK_SEI_INFO
> +#define S5P_FIMV_FRAME_PACK_GRID_POS S5P_FIMV_D_FRAME_PACK_GRID_POS
> +
> +#define S5P_FIMV_SHARED_SET_E_FRAME_TAG S5P_FIMV_E_PICTURE_TAG
> +#define S5P_FIMV_SHARED_GET_E_FRAME_TAG S5P_FIMV_E_RET_PICTURE_TAG
> +#define S5P_FIMV_ENCODED_LUMA_ADDR S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR
> +#define S5P_FIMV_ENCODED_CHROMA_ADDR S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR
> +#define S5P_FIMV_FRAME_INSERTION S5P_FIMV_E_FRAME_INSERTION
> +
> +#define S5P_FIMV_PARAM_CHANGE_FLAG S5P_FIMV_E_PARAM_CHANGE /* flag */
> +#define S5P_FIMV_NEW_I_PERIOD S5P_FIMV_E_GOP_CONFIG
> +#define S5P_FIMV_NEW_RC_FRAME_RATE S5P_FIMV_E_RC_FRAME_RATE
> +#define S5P_FIMV_NEW_RC_BIT_RATE S5P_FIMV_E_RC_BIT_RATE
> +/*** End of MFCv5 compatibility definitions ***/
> +
> +/*** old definitions ***/
> +#define S5P_FIMV_SW_RESET 0x0000
> +#define S5P_FIMV_RISC_HOST_INT 0x0008
> +
> +/* Command from HOST to RISC */
> +#define S5P_FIMV_HOST2RISC_ARG1 0x0034
> +#define S5P_FIMV_HOST2RISC_ARG2 0x0038
> +#define S5P_FIMV_HOST2RISC_ARG3 0x003c
> +#define S5P_FIMV_HOST2RISC_ARG4 0x0040
> +
> +/* Command from RISC to HOST */
> +#define S5P_FIMV_RISC2HOST_CMD_MASK 0x1FFFF
> +#define S5P_FIMV_RISC2HOST_ARG1 0x0048
> +#define S5P_FIMV_RISC2HOST_ARG2 0x004c
> +#define S5P_FIMV_RISC2HOST_ARG3 0x0050
> +#define S5P_FIMV_RISC2HOST_ARG4 0x0054
> +
> +#define S5P_FIMV_SYS_MEM_SZ 0x005c
> +#define S5P_FIMV_FW_STATUS 0x0080
> +
> +/* Memory controller register */
> +#define S5P_FIMV_MC_DRAMBASE_ADR_A 0x0508
> +#define S5P_FIMV_MC_DRAMBASE_ADR_B 0x050c
> +#define S5P_FIMV_MC_STATUS 0x0510
> +
> +/* Common register */
> +#define S5P_FIMV_COMMON_BASE_A 0x0600
> +#define S5P_FIMV_COMMON_BASE_B 0x0700
> +
> +/* Decoder */
> +#define S5P_FIMV_DEC_CHROMA_ADR (S5P_FIMV_COMMON_BASE_A)
> +#define S5P_FIMV_DEC_LUMA_ADR (S5P_FIMV_COMMON_BASE_B)
> +
> +/* H.264 decoding */
> +#define S5P_FIMV_H264_VERT_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c) /* vertical neighbor motion vector */
> +#define S5P_FIMV_H264_NB_IP_ADR (S5P_FIMV_COMMON_BASE_A + 0x90) /* neighbor pixels for intra pred */
> +#define S5P_FIMV_H264_MV_ADR (S5P_FIMV_COMMON_BASE_B + 0x80) /* H264 motion vector */
> +
> +/* MPEG4 decoding */
> +#define S5P_FIMV_MPEG4_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c) /* neighbor AC/DC coeff. */
> +#define S5P_FIMV_MPEG4_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90) /* upper neighbor motion vector */
> +#define S5P_FIMV_MPEG4_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94) /* subseq. anchor motion vector */
> +#define S5P_FIMV_MPEG4_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98) /* overlap transform line */
> +#define S5P_FIMV_MPEG4_SP_ADR (S5P_FIMV_COMMON_BASE_A + 0xa8) /* syntax parser */
> +
> +/* H.263 decoding */
> +#define S5P_FIMV_H263_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
> +#define S5P_FIMV_H263_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
> +#define S5P_FIMV_H263_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94)
> +#define S5P_FIMV_H263_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98)
> +
> +/* VC-1 decoding */
> +#define S5P_FIMV_VC1_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
> +#define S5P_FIMV_VC1_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
> +#define S5P_FIMV_VC1_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94)
> +#define S5P_FIMV_VC1_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98)
> +#define S5P_FIMV_VC1_BITPLANE3_ADR (S5P_FIMV_COMMON_BASE_A + 0x9c) /* bitplane3 */
> +#define S5P_FIMV_VC1_BITPLANE2_ADR (S5P_FIMV_COMMON_BASE_A + 0xa0) /* bitplane2 */
> +#define S5P_FIMV_VC1_BITPLANE1_ADR (S5P_FIMV_COMMON_BASE_A + 0xa4) /* bitplane1 */
> +
> +/* Encoder */
> +#define S5P_FIMV_ENC_REF0_LUMA_ADR (S5P_FIMV_COMMON_BASE_A + 0x1c) /* reconstructed luma */
> +#define S5P_FIMV_ENC_REF1_LUMA_ADR (S5P_FIMV_COMMON_BASE_A + 0x20)
> +#define S5P_FIMV_ENC_REF0_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B) /* reconstructed chroma */
> +#define S5P_FIMV_ENC_REF1_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x04)
> +#define S5P_FIMV_ENC_REF2_LUMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x10)
> +#define S5P_FIMV_ENC_REF2_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x08)
> +#define S5P_FIMV_ENC_REF3_LUMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x14)
> +#define S5P_FIMV_ENC_REF3_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x0c)
> +
> +/* H.264 encoding */
> +#define S5P_FIMV_H264_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A) /* upper motion vector */
> +#define S5P_FIMV_H264_NBOR_INFO_ADR (S5P_FIMV_COMMON_BASE_A + 0x04) /* entropy engine's neighbor info. */
> +#define S5P_FIMV_H264_UP_INTRA_MD_ADR (S5P_FIMV_COMMON_BASE_A + 0x08) /* upper intra MD */
> +#define S5P_FIMV_H264_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10) /* direct cozero flag */
> +#define S5P_FIMV_H264_UP_INTRA_PRED_ADR (S5P_FIMV_COMMON_BASE_B + 0x40) /* upper intra PRED */
> +
> +/* H.263 encoding */
> +#define S5P_FIMV_H263_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A) /* upper motion vector */
> +#define S5P_FIMV_H263_ACDC_COEF_ADR (S5P_FIMV_COMMON_BASE_A + 0x04) /* upper Q coeff. */
> +
> +/* MPEG4 encoding */
> +#define S5P_FIMV_MPEG4_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A) /* upper motion vector */
> +#define S5P_FIMV_MPEG4_ACDC_COEF_ADR (S5P_FIMV_COMMON_BASE_A + 0x04) /* upper Q coeff. */
> +#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10) /* direct cozero flag */
> +
> +#define S5P_FIMV_ENC_REF_B_LUMA_ADR 0x062c /* ref B Luma addr */
> +#define S5P_FIMV_ENC_REF_B_CHROMA_ADR 0x0630 /* ref B Chroma addr */
> +
> +#define S5P_FIMV_ENC_CUR_LUMA_ADR 0x0718 /* current Luma addr */
> +#define S5P_FIMV_ENC_CUR_CHROMA_ADR 0x071C /* current Chroma addr */
> +
> +/* Codec common register */
> +#define S5P_FIMV_ENC_HSIZE_PX 0x0818 /* frame width at encoder */
> +#define S5P_FIMV_ENC_VSIZE_PX 0x081c /* frame height at encoder */
> +#define S5P_FIMV_ENC_PROFILE 0x0830 /* profile register */
> +#define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
> +#define S5P_FIMV_ENC_LF_CTRL 0x0848 /* loop filter control */
> +#define S5P_FIMV_ENC_ALPHA_OFF 0x084c /* loop filter alpha offset */
> +#define S5P_FIMV_ENC_BETA_OFF 0x0850 /* loop filter beta offset */
> +#define S5P_FIMV_MR_BUSIF_CTRL 0x0854 /* hidden, bus interface ctrl */
> +#define S5P_FIMV_ENC_PXL_CACHE_CTRL 0x0a00 /* pixel cache control */
> +
> +/* Channel & stream interface register */
> +#define S5P_FIMV_SI_RTN_CHID 0x2000 /* Return CH instance ID register */
> +#define S5P_FIMV_SI_CH0_INST_ID 0x2040 /* codec instance ID */
> +#define S5P_FIMV_SI_CH1_INST_ID 0x2080 /* codec instance ID */
> +/* Decoder */
> +#define S5P_FIMV_SI_VRESOL 0x2004 /* vertical resolution of decoder */
> +#define S5P_FIMV_SI_HRESOL 0x2008 /* horizontal resolution of decoder */
> +#define S5P_FIMV_SI_BUF_NUMBER 0x200c /* number of frames in the decoded pic */
> +#define S5P_FIMV_SI_CONSUMED_BYTES 0x2018 /* Consumed number of bytes to decode
> + a frame */
> +#define S5P_FIMV_SI_FRAME_TYPE 0x2020 /* frame type such as skip/I/P/B */
> +
> +#define S5P_FIMV_SI_CH0_SB_ST_ADR 0x2044 /* start addr of stream buf */
> +#define S5P_FIMV_SI_CH0_SB_FRM_SIZE 0x2048 /* size of stream buf */
> +#define S5P_FIMV_SI_CH0_DESC_ADR 0x204c /* addr of descriptor buf */
> +#define S5P_FIMV_SI_CH0_CPB_SIZE 0x2058 /* max size of coded pic. buf */
> +#define S5P_FIMV_SI_CH0_DESC_SIZE 0x205c /* max size of descriptor buf */
> +
> +#define S5P_FIMV_SI_CH1_SB_ST_ADR 0x2084 /* start addr of stream buf */
> +#define S5P_FIMV_SI_CH1_SB_FRM_SIZE 0x2088 /* size of stream buf */
> +#define S5P_FIMV_SI_CH1_DESC_ADR 0x208c /* addr of descriptor buf */
> +#define S5P_FIMV_SI_CH1_CPB_SIZE 0x2098 /* max size of coded pic. buf */
> +#define S5P_FIMV_SI_CH1_DESC_SIZE 0x209c /* max size of descriptor buf */
> +
> +#define S5P_FIMV_SI_FIMV1_HRESOL 0x2054 /* horizontal resolution */
> +#define S5P_FIMV_SI_FIMV1_VRESOL 0x2050 /* vertical resolution */
> +
> +/* Decode frame address */
> +#define S5P_FIMV_DECODE_Y_ADR 0x2024
> +#define S5P_FIMV_DECODE_C_ADR 0x2028
> +
> +/* Decoded frame type */
> +#define S5P_FIMV_DECODE_FRAME_TYPE 0x2020
> +
> +/* Sizes of buffers required for decoding */
> +#define S5P_FIMV_DEC_NB_IP_SIZE (32 * 1024)
> +#define S5P_FIMV_DEC_VERT_NB_MV_SIZE (16 * 1024)
> +#define S5P_FIMV_DEC_NB_DCAC_SIZE (16 * 1024)
> +#define S5P_FIMV_DEC_UPNB_MV_SIZE (68 * 1024)
> +#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE (136 * 1024)
> +#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE (32 * 1024)
> +#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE (2 * 1024)
> +#define S5P_FIMV_DEC_STX_PARSER_SIZE (68 * 1024)
> +
> +#define S5P_FIMV_NV12M_HALIGN 16
> +#define S5P_FIMV_NV12MT_HALIGN 16
> +#define S5P_FIMV_NV12MT_VALIGN 16
> +
> +/* Sizes of buffers required for encoding */
> +#define S5P_FIMV_ENC_UPMV_SIZE (0x10000)
> +#define S5P_FIMV_ENC_COLFLG_SIZE (0x10000)
> +#define S5P_FIMV_ENC_INTRAMD_SIZE (0x10000)
> +#define S5P_FIMV_ENC_INTRAPRED_SIZE (0x4000)
> +#define S5P_FIMV_ENC_NBORINFO_SIZE (0x10000)
> +#define S5P_FIMV_ENC_ACDCCOEF_SIZE (0x10000)
> +
> +/* Encoder */
> +#define S5P_FIMV_ENC_SI_STRM_SIZE 0x2004 /* stream size */
> +#define S5P_FIMV_ENC_SI_PIC_CNT 0x2008 /* picture count */
> +#define S5P_FIMV_ENC_SI_WRITE_PTR 0x200c /* write pointer */
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE 0x2010 /* slice type(I/P/B/IDR) */
> +
> +#define S5P_FIMV_ENCODED_Y_ADDR 0x2014 /* the addr of the encoded luma pic */
> +#define S5P_FIMV_ENCODED_C_ADDR 0x2018 /* the addr of the encoded chroma pic */
> +
> +#define S5P_FIMV_ENC_SI_CH0_SB_ADR 0x2044 /* addr of stream buf */
> +#define S5P_FIMV_ENC_SI_CH0_SB_SIZE 0x204c /* size of stream buf */
> +#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR 0x2050 /* current Luma addr */
> +#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR 0x2054 /* current Chroma addr */
> +#define S5P_FIMV_ENC_SI_CH0_FRAME_INS 0x2058 /* frame insertion */
> +
> +#define S5P_FIMV_ENC_SI_CH1_SB_ADR 0x2084 /* addr of stream buf */
> +#define S5P_FIMV_ENC_SI_CH1_SB_SIZE 0x208c /* size of stream buf */
> +#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR 0x2090 /* current Luma addr */
> +#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR 0x2094 /* current Chroma addr */
> +#define S5P_FIMV_ENC_SI_CH1_FRAME_INS 0x2098 /* frame insertion */
> +
> +#define S5P_FIMV_ENC_PIC_TYPE_CTRL 0xc504 /* pic type level control */
> +#define S5P_FIMV_ENC_B_RECON_WRITE_ON 0xc508 /* B frame recon write ctrl */
> +#define S5P_FIMV_ENC_MSLICE_CTRL 0xc50c /* multi slice control */
> +#define S5P_FIMV_ENC_MSLICE_MB 0xc510 /* MB number in the one slice */
> +#define S5P_FIMV_ENC_MSLICE_BIT 0xc514 /* bit count for one slice */
> +#define S5P_FIMV_ENC_CIR_CTRL 0xc518 /* number of intra refresh MB */
> +#define S5P_FIMV_ENC_MAP_FOR_CUR 0xc51c /* linear or 64x32 tiled mode */
> +#define S5P_FIMV_ENC_PADDING_CTRL 0xc520 /* padding control */
> +
> +#define S5P_FIMV_ENC_RC_CONFIG 0xc5a0 /* RC config */
> +#define S5P_FIMV_ENC_RC_BIT_RATE 0xc5a8 /* bit rate */
> +#define S5P_FIMV_ENC_RC_QBOUND 0xc5ac /* max/min QP */
> +#define S5P_FIMV_ENC_RC_RPARA 0xc5b0 /* rate control reaction coeff */
> +#define S5P_FIMV_ENC_RC_MB_CTRL 0xc5b4 /* MB adaptive scaling */
> +
> +/* Encoder for H264 only */
> +#define S5P_FIMV_ENC_H264_ENTRP_MODE 0xd004 /* CAVLC or CABAC */
> +#define S5P_FIMV_ENC_H264_ALPHA_OFF 0xd008 /* loop filter alpha offset */
> +#define S5P_FIMV_ENC_H264_BETA_OFF 0xd00c /* loop filter beta offset */
> +#define S5P_FIMV_ENC_H264_NUM_OF_REF 0xd010 /* number of reference for P/B */
> +#define S5P_FIMV_ENC_H264_TRANS_FLAG 0xd034 /* 8x8 transform flag in PPS & high profile */
> +
> +#define S5P_FIMV_ENC_RC_FRAME_RATE 0xd0d0 /* frame rate */
> +
> +/* Encoder for MPEG4 only */
> +#define S5P_FIMV_ENC_MPEG4_QUART_PXL 0xe008 /* qpel interpolation ctrl */
> +
> +/* Additional */
> +#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL 0x2068 /* DPB Config Control Register */
> +#define S5P_FIMV_DPB_COUNT_MASK 0xffff
> +
> +#define S5P_FIMV_SI_CH0_RELEASE_BUF 0x2060 /* DPB release buffer register */
> +#define S5P_FIMV_SI_CH0_HOST_WR_ADR 0x2064 /* address of shared memory */
> +
> +/* Channel Control Register */
> +#define S5P_FIMV_CH_FRAME_START_REALLOC 5
> +
> +#define S5P_FIMV_CH_MASK 7
> +#define S5P_FIMV_CH_SHIFT 16
> +
> +/* Host to RISC command */
> +#define S5P_FIMV_R2H_CMD_RSV_RET 3
> +#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET 7
> +#define S5P_FIMV_R2H_CMD_FLUSH_RET 12
> +#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
> +
> +/* Shared memory registers' offsets */
> +
> +/* An offset of the start position in the stream when
> + * the start position is not aligned */
> +#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT 0x000C
> +#define S5P_FIMV_SHARED_START_BYTE_NUM 0x0018
> +#define S5P_FIMV_SHARED_RC_VOP_TIMING 0x0030
> +#define S5P_FIMV_SHARED_LUMA_DPB_SIZE 0x0064
> +#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE 0x0068
> +#define S5P_FIMV_SHARED_MV_SIZE 0x006C
> +#define S5P_FIMV_SHARED_PIC_TIME_TOP 0x0010
> +#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM 0x0014
> +#define S5P_FIMV_SHARED_EXT_ENC_CONTROL 0x0028
> +#define S5P_FIMV_SHARED_P_B_FRAME_QP 0x0070
> +#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC 0x0074
> +#define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
> +#define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
> +#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
> +
> +/* End of old definitions */
> +
> +#endif /* _REGS_FIMV_V6_H */
> diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/video/s5p-mfc/regs-mfc.h
> index a19bece..d2dfb06 100644
> --- a/drivers/media/video/s5p-mfc/regs-mfc.h
> +++ b/drivers/media/video/s5p-mfc/regs-mfc.h
> @@ -144,6 +144,7 @@
> #define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
> #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_MPEG4_SIMPLE 0
> #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
> #define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
> @@ -213,6 +214,7 @@
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4
>
> /* Decode frame address */
> #define S5P_FIMV_DECODE_Y_ADR 0x2024
> @@ -377,6 +379,16 @@
> #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
> #define S5P_FIMV_R2H_CMD_ERR_RET 32
>
> +/* Dummy definition for MFCv6 compatibilty */
> +#define S5P_FIMV_CODEC_H264_MVC_DEC -1
> +#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1
> +#define S5P_FIMV_MFC_RESET -1
> +#define S5P_FIMV_RISC_ON -1
> +#define S5P_FIMV_RISC_BASE_ADDRESS -1
> +#define S5P_FIMV_CODEC_VP8_DEC -1
> +#define S5P_FIMV_REG_CLEAR_BEGIN 0
> +#define S5P_FIMV_REG_CLEAR_COUNT 0
> +
> /* Error handling defines */
> #define S5P_FIMV_ERR_WARNINGS_START 145
> #define S5P_FIMV_ERR_DEC_MASK 0xFFFF
> @@ -414,5 +426,22 @@
> #define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
> #define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
> #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
> +#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT 2
> +
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL 0x16C
> +#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID 0x170
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO 0x174
> +#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS 0x178
> +
> +/* SEI related information */
> +#define S5P_FIMV_FRAME_PACK_SEI_AVAIL S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL
> +#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID
> +#define S5P_FIMV_FRAME_PACK_SEI_INFO S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO
> +#define S5P_FIMV_FRAME_PACK_GRID_POS S5P_FIMV_SHARED_FRAME_PACK_GRID_POS
> +
> +#define S5P_FIMV_SHARED_SET_E_FRAME_TAG S5P_FIMV_SHARED_SET_FRAME_TAG
> +#define S5P_FIMV_SHARED_GET_E_FRAME_TAG S5P_FIMV_SHARED_GET_FRAME_TAG_TOP
> +#define S5P_FIMV_ENCODED_LUMA_ADDR S5P_FIMV_ENCODED_Y_ADDR
> +#define S5P_FIMV_ENCODED_CHROMA_ADDR S5P_FIMV_ENCODED_C_ADDR
>
> #endif /* _REGS_FIMV_H */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
> index 9bb68e7..bec94bc 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
> @@ -21,15 +21,13 @@
> #include <linux/videodev2.h>
> #include <linux/workqueue.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> +#include "s5p_mfc_common.h"
> #include "s5p_mfc_ctrl.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_dec.h"
> #include "s5p_mfc_enc.h"
> #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
>
> #define S5P_MFC_NAME "s5p-mfc"
> #define S5P_MFC_DEC_NAME "s5p-mfc-dec"
> @@ -155,13 +153,6 @@ static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
> return MFCNODE_INVALID;
> }
>
> -static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> -{
> - mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> - mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> -}
> -
> static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_buf *dst_buf;
> @@ -179,8 +170,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
> ctx->dst_queue_cnt--;
> dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
>
> - if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> - s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> + if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
> + s5p_mfc_read_info(ctx, PIC_TIME_BOT))
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
> else
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
> @@ -195,7 +186,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
> struct s5p_mfc_dev *dev = ctx->dev;
> struct s5p_mfc_buf *dst_buf, *src_buf;
> size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
> - unsigned int frame_type = s5p_mfc_get_frame_type();
> + unsigned int frame_type = s5p_mfc_get_dec_frame_type();
>
> /* Copy timestamp / timecode from decoded src to dst and set
> appropraite flags */
> @@ -232,7 +223,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
> struct s5p_mfc_dev *dev = ctx->dev;
> struct s5p_mfc_buf *dst_buf;
> size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
> - unsigned int frame_type = s5p_mfc_get_frame_type();
> + unsigned int frame_type = s5p_mfc_get_dec_frame_type();
> unsigned int index;
>
> /* If frame is same as previous then skip and do not dequeue */
> @@ -251,8 +242,8 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
> list_del(&dst_buf->list);
> ctx->dst_queue_cnt--;
> dst_buf->b->v4l2_buf.sequence = ctx->sequence;
> - if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> - s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> + if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
> + s5p_mfc_read_info(ctx, PIC_TIME_BOT))
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
> else
> dst_buf->b->v4l2_buf.field =
> @@ -285,12 +276,13 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
>
> dst_frame_status = s5p_mfc_get_dspl_status()
> & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> - res_change = s5p_mfc_get_dspl_status()
> - & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> + res_change = (s5p_mfc_get_dspl_status()
> + & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
> + >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
> mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
> if (ctx->state == MFCINST_RES_CHANGE_INIT)
> ctx->state = MFCINST_RES_CHANGE_FLUSH;
> - if (res_change) {
> + if (res_change && res_change != 3) {
> ctx->state = MFCINST_RES_CHANGE_INIT;
> s5p_mfc_clear_int_flags(dev);
> wake_up_ctx(ctx, reason, err);
> @@ -333,7 +325,8 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
> list);
> ctx->consumed_stream += s5p_mfc_get_consumed_stream();
> if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
> - s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
> + s5p_mfc_get_dec_frame_type() ==
> + S5P_FIMV_DECODE_FRAME_P_FRAME
> && ctx->consumed_stream + STUFF_BYTE <
> src_buf->b->v4l2_planes[0].bytesused) {
> /* Run MFC again on the same buffer */
> @@ -427,7 +420,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
> unsigned int reason, unsigned int err)
> {
> struct s5p_mfc_dev *dev;
> - unsigned int guard_width, guard_height;
>
> if (ctx == NULL)
> return;
> @@ -439,45 +431,28 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
> ctx->img_width = s5p_mfc_get_img_width();
> ctx->img_height = s5p_mfc_get_img_height();
>
> - ctx->buf_width = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN);
> - ctx->buf_height = ALIGN(ctx->img_height,
> - S5P_FIMV_NV12MT_VALIGN);
> - mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
> - "buffer dimensions: %dx%d\n", ctx->img_width,
> - ctx->img_height, ctx->buf_width,
> - ctx->buf_height);
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> - ctx->luma_size = ALIGN(ctx->buf_width *
> - ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->chroma_size = ALIGN(ctx->buf_width *
> - ALIGN((ctx->img_height >> 1),
> - S5P_FIMV_NV12MT_VALIGN),
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->mv_size = ALIGN(ctx->buf_width *
> - ALIGN((ctx->buf_height >> 2),
> - S5P_FIMV_NV12MT_VALIGN),
> - S5P_FIMV_DEC_BUF_ALIGN);
> - } else {
> - guard_width = ALIGN(ctx->img_width + 24,
> - S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN(ctx->img_height + 16,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->luma_size = ALIGN(guard_width *
> - guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> - guard_width = ALIGN(ctx->img_width + 16,
> - S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN((ctx->img_height >> 1) + 4,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->chroma_size = ALIGN(guard_width *
> - guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->mv_size = 0;
> - }
> + s5p_mfc_dec_calc_dpb_size(ctx);
> +
> ctx->dpb_count = s5p_mfc_get_dpb_count();
> if (ctx->img_width == 0 || ctx->img_height == 0)
> ctx->state = MFCINST_ERROR;
> else
> ctx->state = MFCINST_HEAD_PARSED;
> +
> + if ((ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) &&
> + !list_empty(&ctx->src_queue)) {
> + struct s5p_mfc_buf *src_buf;
> + src_buf = list_entry(ctx->src_queue.next,
> + struct s5p_mfc_buf, list);
> + mfc_debug(2, "Check consumed size of header. ");
> + mfc_debug(2, "source : %d, consumed : %d\n",
> + s5p_mfc_get_consumed_stream(),
> + src_buf->b->v4l2_planes[0].bytesused);
> + if (s5p_mfc_get_consumed_stream() <
> + src_buf->b->v4l2_planes[0].bytesused)
> + ctx->remained = 1;
> + }
> }
> s5p_mfc_clear_int_flags(dev);
> clear_work_bit(ctx);
> @@ -508,7 +483,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
> spin_unlock(&dev->condlock);
> if (err == 0) {
> ctx->state = MFCINST_RUNNING;
> - if (!ctx->dpb_flush_flag) {
> + if (!ctx->dpb_flush_flag && !ctx->remained) {
> spin_lock_irqsave(&dev->irqlock, flags);
> if (!list_empty(&ctx->src_queue)) {
> src_buf = list_entry(ctx->src_queue.next,
> @@ -567,6 +542,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
> break;
>
> case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
> + case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
> case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
> if (ctx->c_ops->post_frame_start) {
> if (ctx->c_ops->post_frame_start(ctx))
> @@ -679,6 +655,7 @@ static int s5p_mfc_open(struct file *file)
> if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
> ctx->type = MFCINST_DECODER;
> ctx->c_ops = get_dec_codec_ops();
> + s5p_mfc_dec_init(ctx);
> /* Setup ctrl handler */
> ret = s5p_mfc_dec_ctrls_setup(ctx);
> if (ret) {
> @@ -691,6 +668,7 @@ static int s5p_mfc_open(struct file *file)
> /* only for encoder */
> INIT_LIST_HEAD(&ctx->ref_queue);
> ctx->ref_queue_cnt = 0;
> + s5p_mfc_enc_init(ctx);
> /* Setup ctrl handler */
> ret = s5p_mfc_enc_ctrls_setup(ctx);
> if (ret) {
> @@ -842,6 +820,7 @@ static int s5p_mfc_release(struct file *file)
> mfc_debug(2, "Last instance - release firmware\n");
> /* reset <-> F/W release */
> s5p_mfc_reset(dev);
> + s5p_mfc_deinit_hw(dev);
> s5p_mfc_release_firmware(dev);
> del_timer_sync(&dev->watchdog_timer);
> if (s5p_mfc_power_off() < 0)
> @@ -1086,6 +1065,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
> dev->watchdog_timer.data = (unsigned long)dev;
> dev->watchdog_timer.function = s5p_mfc_watchdog;
>
> + dev->variant = (struct s5p_mfc_variant *)
> + platform_get_device_id(pdev)->driver_data;
> +
> pr_debug("%s--\n", __func__);
> return 0;
>
> @@ -1205,9 +1187,74 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
> NULL)
> };
>
> +struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
> + .h264_ctx = 0x96000,
> + .non_h264_ctx = 0x2800,
> + .dsc = 0x20000,
> + .shm = 0x1000,
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v5 = {
> + .fw = 0x60000,
> + .cpb = 0x400000, /* 4MB */
> + .priv = &mfc_buf_size_v5,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v5 = {
> + .base = 17,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v5 = {
> + .version = 0x51,
> + .port_num = 2,
> + .buf_size = &buf_size_v5,
> + .buf_align = &mfc_buf_align_v5,
> +};
> +
> +struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
> + .dev_ctx = 0x7000, /* 28KB */
> + .h264_dec_ctx = 0x200000, /* 1.6MB */
> + .other_dec_ctx = 0x5000, /* 20KB */
> + .h264_enc_ctx = 0x19000, /* 100KB */
> + .other_enc_ctx = 0x3000, /* 12KB */
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v6 = {
> + .fw = 0x100000, /* 1MB */
> + .cpb = 0x300000, /* 3MB */
> + .priv = &mfc_buf_size_v6,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v6 = {
> + .base = 0,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v6 = {
> + .version = 0x61,
> + .port_num = 1,
> + .buf_size = &buf_size_v6,
> + .buf_align = &mfc_buf_align_v6,
> +};
> +
> +static struct platform_device_id mfc_driver_ids[] = {
> + {
> + .name = "s5p-mfc",
> + .driver_data = (unsigned long)&mfc_drvdata_v5,
> + }, {
> + .name = "s5p-mfc-v5",
> + .driver_data = (unsigned long)&mfc_drvdata_v5,
> + }, {
> + .name = "s5p-mfc-v6",
> + .driver_data = (unsigned long)&mfc_drvdata_v6,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
> +
> static struct platform_driver s5p_mfc_driver = {
> - .probe = s5p_mfc_probe,
> - .remove = __devexit_p(s5p_mfc_remove),
> + .probe = s5p_mfc_probe,
> + .remove = __devexit_p(s5p_mfc_remove),
> + .id_table = mfc_driver_ids,
> .driver = {
> .name = S5P_MFC_NAME,
> .owner = THIS_MODULE,
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> index f0665ed..e3c64db 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> @@ -16,8 +16,8 @@
> #include "s5p_mfc_debug.h"
>
> /* This function is used to send a command to the MFC */
> -static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> - struct s5p_mfc_cmd_args *args)
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args)
> {
> int cur_cmd;
> unsigned long timeout;
> @@ -81,7 +81,7 @@ int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
> memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> h2r_args.arg[0] = ctx->codec_mode;
> h2r_args.arg[1] = 0; /* no crc & no pixelcache */
> - h2r_args.arg[2] = ctx->ctx_ofs;
> + h2r_args.arg[2] = ctx->ctx.ofs;
> h2r_args.arg[3] = ctx->ctx_size;
> ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> &h2r_args);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> index 5ceebfe..5c9e662 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> @@ -21,6 +21,9 @@ struct s5p_mfc_cmd_args {
> unsigned int arg[MAX_H2R_ARG];
> };
>
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args);
> +
> int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
> int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
> int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> new file mode 100644
> index 0000000..6a631e0
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> @@ -0,0 +1,96 @@
> +/*
> + * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include "s5p_mfc_common.h"
> +
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_debug.h"
> +#include "s5p_mfc_intr.h"
> +
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args)
> +{
> + mfc_debug(2, "Issue the command: %d\n", cmd);
> +
> + /* Reset RISC2HOST command */
> + mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD);
> +
> + /* Issue the command */
> + mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
> + mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT);
> +
> + return 0;
> +}
> +
> +int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + s5p_mfc_alloc_dev_context_buffer(dev);
> + mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
> + mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE);
> + return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
> +}
> +
> +int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
> +}
> +
> +int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
> +}
> +
> +/* Open a new instance and get its number */
> +int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
> + dev->curr_ctx = ctx->num;
> + mfc_write(dev, ctx->codec_mode, S5P_FIMV_CODEC_TYPE);
> + mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
> + mfc_write(dev, ctx->ctx_size, S5P_FIMV_CONTEXT_MEM_SIZE);
> + mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL); /* no crc */
> +
> + return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> + &h2r_args);
> +}
> +
> +/* Close instance */
> +int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> + int ret = 0;
> +
> + dev->curr_ctx = ctx->num;
> + if (ctx->state != MFCINST_FREE) {
> + mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + ret = s5p_mfc_cmd_host2risc(dev,
> + S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
> + &h2r_args);
> + } else {
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> index bd5706a..8c646f4 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> @@ -16,7 +16,6 @@
> #ifndef S5P_MFC_COMMON_H_
> #define S5P_MFC_COMMON_H_
>
> -#include "regs-mfc.h"
> #include <linux/platform_device.h>
> #include <linux/videodev2.h>
> #include <media/v4l2-ctrls.h>
> @@ -34,10 +33,6 @@
> #define MFC_OFFSET_SHIFT 11
>
> #define FIRMWARE_ALIGN 0x20000 /* 128KB */
> -#define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264 instance */
> -#define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */
> -#define DESC_BUF_SIZE 0x20000 /* 128KB for DESC buffer */
> -#define SHARED_BUF_SIZE 0x2000 /* 8KB for shared buffer */
>
> #define DEF_CPB_SIZE 0x40000 /* 512KB */
>
> @@ -174,6 +169,54 @@ struct s5p_mfc_pm {
> struct device *device;
> };
>
> +struct s5p_mfc_buf_size_v5 {
> + unsigned int h264_ctx;
> + unsigned int non_h264_ctx;
> + unsigned int dsc;
> + unsigned int shm;
> +};
> +
> +struct s5p_mfc_buf_size_v6 {
> + unsigned int dev_ctx;
> + unsigned int h264_dec_ctx;
> + unsigned int other_dec_ctx;
> + unsigned int h264_enc_ctx;
> + unsigned int other_enc_ctx;
> +};
> +
> +struct s5p_mfc_buf_size {
> + unsigned int fw;
> + unsigned int cpb;
> + void *priv;
> +};
> +
> +struct s5p_mfc_buf_align {
> + unsigned int base;
> +};
> +
> +struct s5p_mfc_variant {
> + unsigned int version;
> + unsigned int port_num;
> + struct s5p_mfc_buf_size *buf_size;
> + struct s5p_mfc_buf_align *buf_align;
> +};
> +
> +/**
> + * struct s5p_mfc_priv_buf - represents internal used buffer
> + * @alloc: allocation-specific context for each buffer
> + * (videobuf2 allocator)
> + * @ofs: offset of each buffer, will be used for MFC
> + * @virt: kernel virtual address, only valid when the
> + * buffer accessed by driver
> + * @dma: DMA address, only valid when kernel DMA API used
> + */
> +struct s5p_mfc_priv_buf {
> + void *alloc;
> + unsigned long ofs;
> + void *virt;
> + dma_addr_t dma;
> +};
> +
> /**
> * struct s5p_mfc_dev - The struct containing driver internal parameters.
> *
> @@ -209,6 +252,7 @@ struct s5p_mfc_pm {
> * @watchdog_work: worker for the watchdog
> * @alloc_ctx: videobuf2 allocator contexts for two memory banks
> * @enter_suspend: flag set when entering suspend
> + * @ctx_buf: common context memory (MFCv6)
> *
> */
> struct s5p_mfc_dev {
> @@ -223,6 +267,7 @@ struct s5p_mfc_dev {
> struct v4l2_ctrl_handler dec_ctrl_handler;
> struct v4l2_ctrl_handler enc_ctrl_handler;
> struct s5p_mfc_pm pm;
> + struct s5p_mfc_variant *variant;
> int num_inst;
> spinlock_t irqlock; /* lock when operating on videobuf2 queues */
> spinlock_t condlock; /* lock when changing/checking if a context is
> @@ -245,6 +290,8 @@ struct s5p_mfc_dev {
> struct work_struct watchdog_work;
> void *alloc_ctx[2];
> unsigned long enter_suspend;
> +
> + struct s5p_mfc_priv_buf ctx_buf;
> };
>
> /**
> @@ -278,6 +325,23 @@ struct s5p_mfc_h264_enc_params {
> enum v4l2_mpeg_video_h264_level level_v4l2;
> int level;
> u16 cpb_size;
> + int interlace;
> + u8 hier_qp;
> + u8 hier_qp_type;
> + u8 hier_qp_layer;
> + u8 hier_qp_layer_qp[7];
> + u8 sei_frame_packing;
> + u8 sei_fp_curr_frame_0;
> + u8 sei_fp_arrangement_type;
> +
> + u8 fmo;
> + u8 fmo_map_type;
> + u8 fmo_slice_grp;
> + u8 fmo_chg_dir;
> + u32 fmo_chg_rate;
> + u32 fmo_run_len[4];
> + u8 aso;
> + u32 aso_slice_order[8];
> };
>
> /**
> @@ -288,8 +352,6 @@ struct s5p_mfc_mpeg4_enc_params {
> enum v4l2_mpeg_video_mpeg4_profile profile;
> int quarter_pixel;
> /* Common for MPEG4, H263 */
> - u16 vop_time_res;
> - u16 vop_frm_delta;
> u8 rc_frame_qp;
> u8 rc_min_qp;
> u8 rc_max_qp;
> @@ -316,9 +378,11 @@ struct s5p_mfc_enc_params {
> u8 pad_cb;
> u8 pad_cr;
> int rc_frame;
> + int rc_mb;
> u32 rc_bitrate;
> u16 rc_reaction_coeff;
> u16 vbv_size;
> + u32 vbv_delay;
>
> enum v4l2_mpeg_video_header_mode seq_hdr_mode;
> enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
> @@ -327,7 +391,6 @@ struct s5p_mfc_enc_params {
> u8 num_b_frame;
> u32 rc_framerate_num;
> u32 rc_framerate_denom;
> - int interlace;
>
> union {
> struct s5p_mfc_h264_enc_params h264;
> @@ -470,6 +533,7 @@ struct s5p_mfc_ctx {
> unsigned long consumed_stream;
>
> unsigned int dpb_flush_flag;
> + unsigned int remained;
>
> /* Buffers */
> void *bank1_buf;
> @@ -499,37 +563,42 @@ struct s5p_mfc_ctx {
> int display_delay;
> int display_delay_enable;
> int after_packed_pb;
> + int sei_fp_parse;
>
> int dpb_count;
> int total_dpb_count;
>
> /* Buffers */
> - void *ctx_buf;
> - size_t ctx_phys;
> - size_t ctx_ofs;
> - size_t ctx_size;
> -
> - void *desc_buf;
> - size_t desc_phys;
> -
> -
> - void *shm_alloc;
> - void *shm;
> - size_t shm_ofs;
> + unsigned int ctx_size;
> + struct s5p_mfc_priv_buf ctx;
> + struct s5p_mfc_priv_buf dsc;
> + struct s5p_mfc_priv_buf shm;
>
> struct s5p_mfc_enc_params enc_params;
>
> size_t enc_dst_buf_size;
> + size_t luma_dpb_size;
> + size_t chroma_dpb_size;
> + size_t me_buffer_size;
> + size_t tmv_buffer_size;
>
> enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
>
> struct list_head ref_queue;
> unsigned int ref_queue_cnt;
>
> + enum v4l2_mpeg_video_multi_slice_mode slice_mode;
> + union {
> + unsigned int mb;
> + unsigned int bits;
> + } slice_size;
> +
> struct s5p_mfc_codec_ops *c_ops;
>
> struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
> struct v4l2_ctrl_handler ctrl_handler;
> + unsigned int frame_tag;
> + size_t scratch_buf_size;
> };
>
> /*
> @@ -567,4 +636,18 @@ struct mfc_control {
> #define ctrl_to_ctx(__ctrl) \
> container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
>
> +#define HAS_PORTNUM(dev) (dev ? (dev->variant ? \
> + (dev->variant->port_num ? 1 : 0) : 0) : 0)
> +#define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0)
> +#define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0)
> +
> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> +#include "regs-mfc.h"
> +#include "s5p_mfc_opr.h"
> +#include "s5p_mfc_shm.h"
> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> +#include "regs-mfc-v6.h"
> +#include "s5p_mfc_opr_v6.h"
> +#endif
> +
> #endif /* S5P_MFC_COMMON_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> index 08a5cfe..65ff15d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> @@ -15,7 +15,6 @@
> #include <linux/firmware.h>
> #include <linux/jiffies.h>
> #include <linux/sched.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_cmd.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> @@ -38,12 +37,12 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
> * into kernel. */
> mfc_debug_enter();
> err = request_firmware((const struct firmware **)&fw_blob,
> - "s5p-mfc.fw", dev->v4l2_dev.dev);
> + "mfc_fw.bin", dev->v4l2_dev.dev);
> if (err != 0) {
> mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
> return -EINVAL;
> }
> - dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
> + dev->fw_size = dev->variant->buf_size->fw;
> if (s5p_mfc_bitproc_buf) {
> mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
> release_firmware(fw_blob);
> @@ -77,28 +76,33 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
> return -EIO;
> }
> dev->bank1 = s5p_mfc_bitproc_phys;
> - b_base = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
> - if (IS_ERR(b_base)) {
> - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> - s5p_mfc_bitproc_phys = 0;
> - s5p_mfc_bitproc_buf = NULL;
> - mfc_err("Allocating bank2 base failed\n");
> - release_firmware(fw_blob);
> - return -ENOMEM;
> - }
> - bank2_base_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> - vb2_dma_contig_memops.put(b_base);
> - if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> - mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
> - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> - s5p_mfc_bitproc_phys = 0;
> - s5p_mfc_bitproc_buf = NULL;
> - release_firmware(fw_blob);
> - return -EIO;
> + if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
> + b_base = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
> + 1 << MFC_BANK2_ALIGN_ORDER);
> + if (IS_ERR(b_base)) {
> + vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> + s5p_mfc_bitproc_phys = 0;
> + s5p_mfc_bitproc_buf = 0;
> + mfc_err("Allocating bank2 base failed\n");
> + release_firmware(fw_blob);
> + return -ENOMEM;
> + }
> + bank2_base_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> + vb2_dma_contig_memops.put(b_base);
> + if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> + mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
> + vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> + s5p_mfc_bitproc_phys = 0;
> + s5p_mfc_bitproc_buf = 0;
> + release_firmware(fw_blob);
> + return -EIO;
> + }
> + dev->bank2 = bank2_base_phys;
> + } else {
> + dev->bank2 = dev->bank1;
> }
> - dev->bank2 = bank2_base_phys;
> memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
> wmb();
> release_firmware(fw_blob);
> @@ -116,7 +120,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
> * into kernel. */
> mfc_debug_enter();
> err = request_firmware((const struct firmware **)&fw_blob,
> - "s5p-mfc.fw", dev->v4l2_dev.dev);
> + "mfc_fw.bin", dev->v4l2_dev.dev);
> if (err != 0) {
> mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
> return -EINVAL;
> @@ -157,46 +161,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
> {
> unsigned int mc_status;
> unsigned long timeout;
> + int i;
>
> mfc_debug_enter();
> - /* Stop procedure */
> - /* reset RISC */
> - mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> - /* All reset except for MC */
> - mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> - mdelay(10);
> -
> - timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> - /* Check MC status */
> - do {
> - if (time_after(jiffies, timeout)) {
> - mfc_err("Timeout while resetting MFC\n");
> - return -EIO;
> - }
>
> - mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> + if (IS_MFCV6(dev)) {
> + /* Reset IP */
> + /* except RISC, reset */
> + mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET);
> + /* reset release */
> + mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET);
>
> - } while (mc_status & 0x3);
> + /* Zero Initialization of MFC registers */
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> + mfc_write(dev, 0, S5P_FIMV_FW_VERSION);
> +
> + for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
> + mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));
> +
> + /* Reset */
> + mfc_write(dev, 0, S5P_FIMV_RISC_ON);
> + mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET);
> + mfc_write(dev, 0, S5P_FIMV_MFC_RESET);
> + } else {
> + /* Stop procedure */
> + /* reset RISC */
> + mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> + /* All reset except for MC */
> + mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> + mdelay(10);
> +
> + timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> + /* Check MC status */
> + do {
> + if (time_after(jiffies, timeout)) {
> + mfc_err("Timeout while resetting MFC\n");
> + return -EIO;
> + }
> +
> + mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> +
> + } while (mc_status & 0x3);
> +
> + mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> + mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
> + }
>
> - mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> - mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
> mfc_debug_leave();
> return 0;
> }
>
> static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
> {
> - mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> - mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> - mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
> + if (IS_MFCV6(dev)) {
> + mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS);
> + mfc_debug(2, "Base Address : %08x\n", dev->bank1);
> + } else {
> + mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> + mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> + mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
> + dev->bank1, dev->bank2);
> + }
> }
>
> static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
> {
> - mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> - mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> - mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> + if (IS_MFCV6(dev)) {
> + /* Zero initialization should be done before RESET.
> + * Nothing to do here. */
> + } else {
> + mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> + mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> + }
> }
>
> /* Initialize hardware */
> @@ -224,7 +263,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> s5p_mfc_clear_cmds(dev);
> /* 3. Release reset signal to the RISC */
> s5p_mfc_clean_dev_int_flags(dev);
> - mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> + if (IS_MFCV6(dev))
> + mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
> + else
> + mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Will now wait for completion of firmware transfer\n");
> if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
> mfc_err("Failed to load firmware\n");
> @@ -267,6 +309,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> }
>
>
> +/* Deinitialize hardware */
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
> +{
> + s5p_mfc_clock_on();
> +
> + s5p_mfc_reset(dev);
> + s5p_mfc_release_dev_context_buffer(dev);
> +
> + s5p_mfc_clock_off();
> +}
> +
> int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
> {
> int ret;
> @@ -322,7 +375,10 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
> return ret;
> }
> /* 4. Release reset signal to the RISC */
> - mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> + if (IS_MFCV6(dev))
> + mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
> + else
> + mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
> if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
> mfc_err("Failed to load firmware\n");
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> index 61dc23b..b72c8c6 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> @@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
> int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
>
> int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
>
> int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
> int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> index 4dd32fc..d4c6cf2 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> @@ -23,85 +23,113 @@
> #include <linux/workqueue.h>
> #include <media/v4l2-ctrls.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_dec.h"
> #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
> +
> +#define DEF_SRC_FMT 4
> +#define DEF_DST_FMT 0
>
> static struct s5p_mfc_fmt formats[] = {
> {
> + .name = "4:2:0 2 Planes 16x16 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> .name = "4:2:0 2 Planes 64x32 Tiles",
> .fourcc = V4L2_PIX_FMT_NV12MT,
> .codec_mode = S5P_FIMV_CODEC_NONE,
> .type = MFC_FMT_RAW,
> .num_planes = 2,
> - },
> + },
> + {
> + .name = "4:2:0 2 Planes Y/CbCr",
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> + .name = "4:2:0 2 Planes Y/CrCb",
> + .fourcc = V4L2_PIX_FMT_NV21M,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> {
> - .name = "4:2:0 2 Planes",
> - .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "H264 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264,
> + .codec_mode = S5P_FIMV_CODEC_H264_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "H264 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_FIMV_CODEC_H264_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "H264/MVC Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264_MVC,
> + .codec_mode = S5P_FIMV_CODEC_H264_MVC_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "H263 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_FIMV_CODEC_H263_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "H263 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H263,
> + .codec_mode = S5P_FIMV_CODEC_H263_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG1 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG1,
> - .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG1 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG1,
> + .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG2 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG2,
> - .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG2 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG2,
> + .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG4 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG4 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG4,
> + .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "XviD Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_XVID,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "XviD Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_XVID,
> + .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "VC1 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> - .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "VC1 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> + .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "VC1 RCV Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> - .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "VC1 RCV Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> + .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> + },
> + {
> + .name = "VC8 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VP8,
> + .codec_mode = S5P_FIMV_CODEC_VP8_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> };
>
> @@ -336,21 +364,35 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
> /* Try format */
> static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> {
> + struct s5p_mfc_dev *dev = video_drvdata(file);
> struct s5p_mfc_fmt *fmt;
>
> - if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> - mfc_err("This node supports decoding only\n");
> - return -EINVAL;
> - }
> - fmt = find_format(f, MFC_FMT_DEC);
> - if (!fmt) {
> - mfc_err("Unsupported format\n");
> - return -EINVAL;
> - }
> - if (fmt->type != MFC_FMT_DEC) {
> - mfc_err("\n");
> - return -EINVAL;
> + mfc_debug(2, "Type is %d\n", f->type);
> + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + fmt = find_format(f, MFC_FMT_DEC);
> + if (!fmt) {
> + mfc_err("Unsupported format for source.\n");
> + return -EINVAL;
> + }
> + if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> + fmt = find_format(f, MFC_FMT_RAW);
> + if (!fmt) {
> + mfc_err("Unsupported format for destination.\n");
> + return -EINVAL;
> + }
> + if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (fmt->fourcc != V4L2_PIX_FMT_NV12MT) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> }
> +
> return 0;
> }
>
> @@ -373,6 +415,26 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> ret = -EBUSY;
> goto out;
> }
> + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> + fmt = find_format(f, MFC_FMT_RAW);
> + if (!fmt) {
> + mfc_err("Unsupported format for source.\n");
> + return -EINVAL;
> + }
> + if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> + ctx->dst_fmt = fmt;
> + mfc_debug_leave();
> + return ret;
> + } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + mfc_err("Wrong type error for S_FMT : %d", f->type);
> + return -EINVAL;
> + }
> fmt = find_format(f, MFC_FMT_DEC);
> if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
> mfc_err("Unknown codec\n");
> @@ -385,6 +447,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> ret = -EINVAL;
> goto out;
> }
> + if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> ctx->src_fmt = fmt;
> ctx->codec_mode = fmt->codec_mode;
> mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
> @@ -498,7 +564,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
> }
> s5p_mfc_try_run(dev);
> s5p_mfc_wait_for_done_ctx(ctx,
> - S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
> + S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
> }
> return ret;
> }
> @@ -696,10 +762,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
> return -EINVAL;
> }
> if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
> - left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
> + left = s5p_mfc_read_info(ctx, CROP_INFO_H);
> right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
> left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
> - top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
> + top = s5p_mfc_read_info(ctx, CROP_INFO_V);
> bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
> top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
> cr->c.left = left;
> @@ -750,6 +816,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> void *allocators[])
> {
> struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> + struct s5p_mfc_dev *dev = ctx->dev;
>
> /* Video output for decoding (source)
> * this can be set after getting an instance */
> @@ -785,7 +852,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> psize[0] = ctx->luma_size;
> psize[1] = ctx->chroma_size;
> - allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +
> + if (IS_MFCV6(dev))
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + else
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
> ctx->state == MFCINST_INIT) {
> @@ -1035,3 +1108,10 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
> ctx->ctrls[i] = NULL;
> }
>
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
> +{
> + ctx->src_fmt = &formats[DEF_SRC_FMT];
> + ctx->dst_fmt = &formats[DEF_DST_FMT];
> + mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
> + (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> index fb8b215..c53baf8 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
> struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
> int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
> void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
>
> #endif /* S5P_MFC_DEC_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> index 03d8334..645a8ef 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> @@ -24,48 +24,63 @@
> #include <linux/workqueue.h>
> #include <media/v4l2-ctrls.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_enc.h"
> #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> +
> +#define DEF_SRC_FMT 2
> +#define DEF_DST_FMT 4
>
> static struct s5p_mfc_fmt formats[] = {
> {
> - .name = "4:2:0 2 Planes 64x32 Tiles",
> - .fourcc = V4L2_PIX_FMT_NV12MT,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "4:2:0 2 Planes 16x16 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> + .name = "4:2:0 2 Planes 64x32 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> + .name = "4:2:0 2 Planes Y/CbCr",
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "4:2:0 2 Planes",
> - .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "4:2:0 2 Planes Y/CrCb",
> + .fourcc = V4L2_PIX_FMT_NV21M,
> + .codec_mode = S5P_FIMV_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "H264 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_FIMV_CODEC_H264_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "H264 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264,
> + .codec_mode = S5P_FIMV_CODEC_H264_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG4 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "MPEG4 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG4,
> + .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> },
> {
> - .name = "H263 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_FIMV_CODEC_H263_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "H263 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H263,
> + .codec_mode = S5P_FIMV_CODEC_H263_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> },
> };
>
> @@ -641,13 +656,22 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
> vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> }
> - ctx->state = MFCINST_RUNNING;
> - if (s5p_mfc_ctx_ready(ctx)) {
> - spin_lock_irqsave(&dev->condlock, flags);
> - set_bit(ctx->num, &dev->ctx_work_bits);
> - spin_unlock_irqrestore(&dev->condlock, flags);
> +
> + if (IS_MFCV6(dev)) {
> + ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
> + } else {
> + ctx->state = MFCINST_RUNNING;
> + if (s5p_mfc_ctx_ready(ctx)) {
> + spin_lock_irqsave(&dev->condlock, flags);
> + set_bit(ctx->num, &dev->ctx_work_bits);
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + }
> + s5p_mfc_try_run(dev);
> }
> - s5p_mfc_try_run(dev);
> +
> + if (IS_MFCV6(dev))
> + ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
> +
> return 0;
> }
>
> @@ -961,6 +985,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> mfc_err("failed to set output format\n");
> return -EINVAL;
> }
> +
> + if (!IS_MFCV6(dev) &&
> + (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (IS_MFCV6(dev) &&
> + (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> +
> if (fmt->num_planes != pix_fmt_mp->num_planes) {
> mfc_err("failed to set output format\n");
> ret = -EINVAL;
> @@ -973,45 +1008,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
> pix_fmt_mp->width, pix_fmt_mp->height,
> ctx->img_width, ctx->img_height);
> - if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> - ctx->buf_width = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12M_HALIGN);
> - ctx->luma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
> - S5P_FIMV_NV12M_LVALIGN);
> - ctx->chroma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
> - >> 1), S5P_FIMV_NV12M_CVALIGN);
> -
> - ctx->luma_size = ALIGN(ctx->luma_size,
> - S5P_FIMV_NV12M_SALIGN);
> - ctx->chroma_size = ALIGN(ctx->chroma_size,
> - S5P_FIMV_NV12M_SALIGN);
> -
> - pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> - pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> - pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> - pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> -
> - } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> - ctx->buf_width = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN);
> - ctx->luma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->chroma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
> - >> 1), S5P_FIMV_NV12MT_VALIGN);
> - ctx->luma_size = ALIGN(ctx->luma_size,
> - S5P_FIMV_NV12MT_SALIGN);
> - ctx->chroma_size = ALIGN(ctx->chroma_size,
> - S5P_FIMV_NV12MT_SALIGN);
> -
> - pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> - pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> - pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> - pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> - }
> +
> + s5p_mfc_enc_calc_src_size(ctx);
> + pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> + pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> + pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> + pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> +
> ctx->src_bufs_cnt = 0;
> ctx->output_state = QUEUE_FREE;
> } else {
> @@ -1026,6 +1029,7 @@ out:
> static int vidioc_reqbufs(struct file *file, void *priv,
> struct v4l2_requestbuffers *reqbufs)
> {
> + struct s5p_mfc_dev *dev = video_drvdata(file);
> struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
> int ret = 0;
>
> @@ -1045,12 +1049,15 @@ static int vidioc_reqbufs(struct file *file, void *priv,
> return ret;
> }
> ctx->capture_state = QUEUE_BUFS_REQUESTED;
> - ret = s5p_mfc_alloc_codec_buffers(ctx);
> - if (ret) {
> - mfc_err("Failed to allocate encoding buffers\n");
> - reqbufs->count = 0;
> - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> - return -ENOMEM;
> +
> + if (!IS_MFCV6(dev)) {
> + ret = s5p_mfc_alloc_codec_buffers(ctx);
> + if (ret) {
> + mfc_err("Failed to allocate encoding buffers\n");
> + reqbufs->count = 0;
> + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> + return -ENOMEM;
> + }
> }
> } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> if (ctx->output_state != QUEUE_FREE) {
> @@ -1297,6 +1304,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
> 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;
> }
> @@ -1516,6 +1530,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> unsigned int psize[], void *allocators[])
> {
> struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> + struct s5p_mfc_dev *dev = ctx->dev;
>
> if (ctx->state != MFCINST_GOT_INST) {
> mfc_err("inavlid state: %d\n", ctx->state);
> @@ -1544,8 +1559,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> *buf_count = MFC_MAX_BUFFERS;
> psize[0] = ctx->luma_size;
> psize[1] = ctx->chroma_size;
> - allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> - allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + if (IS_MFCV6(dev)) {
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + allocators[1] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + } else {
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + allocators[1] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + }
> } else {
> mfc_err("inavlid queue type: %d\n", vq->type);
> return -EINVAL;
> @@ -1826,3 +1850,10 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
> for (i = 0; i < NUM_CTRLS; i++)
> ctx->ctrls[i] = NULL;
> }
> +
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
> +{
> + ctx->src_fmt = &formats[DEF_SRC_FMT];
> + ctx->dst_fmt = &formats[DEF_DST_FMT];
> +}
> +
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> index 405bdd3..413f22f 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
> struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
> int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
> void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
>
> #endif /* S5P_MFC_ENC_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> index 8f2f8bf..dfdc558 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> @@ -17,7 +17,6 @@
> #include <linux/io.h>
> #include <linux/sched.h>
> #include <linux/wait.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_intr.h"
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> index e6217cb..1fd9c92 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> @@ -12,15 +12,12 @@
> * published by the Free Software Foundation.
> */
>
> -#include "regs-mfc.h"
> -#include "s5p_mfc_cmd.h"
> #include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
> #include "s5p_mfc_ctrl.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
> #include <asm/cacheflush.h>
> #include <linux/delay.h>
> #include <linux/dma-mapping.h>
> @@ -37,39 +34,31 @@
> /* Allocate temporary buffers for decoding */
> int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
> {
> - void *desc_virt;
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - ctx->desc_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> - if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> - ctx->desc_buf = NULL;
> + ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> + buf_size->dsc);
> + if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
> + ctx->dsc.alloc = NULL;
> mfc_err("Allocating DESC buffer failed\n");
> return -ENOMEM;
> }
> - ctx->desc_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> - BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> - if (desc_virt == NULL) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> - mfc_err("Remapping DESC buffer failed\n");
> - return -ENOMEM;
> - }
> - memset(desc_virt, 0, DESC_BUF_SIZE);
> - wmb();
> + ctx->dsc.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
> + BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
> return 0;
> }
>
> /* Release temporary buffers for decoding */
> void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> {
> - if (ctx->desc_phys) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> + if (ctx->dsc.dma) {
> + vb2_dma_contig_memops.put(ctx->dsc.alloc);
> + ctx->dsc.alloc = NULL;
> + ctx->dsc.dma = 0;
> }
> }
>
> @@ -231,41 +220,43 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
> /* Allocate memory for instance data buffer */
> int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
> {
> - void *context_virt;
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> - ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
> + ctx->ctx_size = buf_size->h264_ctx;
> else
> - ctx->ctx_size = MFC_CTX_BUF_SIZE;
> - ctx->ctx_buf = vb2_dma_contig_memops.alloc(
> + ctx->ctx_size = buf_size->non_h264_ctx;
> + ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
> dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> - if (IS_ERR(ctx->ctx_buf)) {
> + if (IS_ERR(ctx->ctx.alloc)) {
> mfc_err("Allocating context buffer failed\n");
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + ctx->ctx.alloc = NULL;
> return -ENOMEM;
> }
> - ctx->ctx_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
> - BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
> - context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
> - if (context_virt == NULL) {
> + ctx->ctx.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> + BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
> + ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> + if (!ctx->ctx.virt) {
> mfc_err("Remapping instance buffer failed\n");
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.ofs = 0;
> + ctx->ctx.dma = 0;
> return -ENOMEM;
> }
> /* Zero content of the allocated memory */
> - memset(context_virt, 0, ctx->ctx_size);
> + memset(ctx->ctx.virt, 0, ctx->ctx_size);
> wmb();
> if (s5p_mfc_init_shm(ctx) < 0) {
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.ofs = 0;
> + ctx->ctx.virt = NULL;
> + ctx->ctx.dma = 0;
> return -ENOMEM;
> }
> return 0;
> @@ -274,15 +265,100 @@ int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
> /* Release instance buffer */
> void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
> {
> - if (ctx->ctx_buf) {
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + if (ctx->ctx.alloc) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.ofs = 0;
> + ctx->ctx.virt = NULL;
> + ctx->ctx.dma = 0;
> }
> - if (ctx->shm_alloc) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_alloc = NULL;
> - ctx->shm = NULL;
> + if (ctx->shm.alloc) {
> + vb2_dma_contig_memops.put(ctx->shm.alloc);
> + ctx->shm.alloc = NULL;
> + ctx->shm.ofs = 0;
> + ctx->shm.virt = NULL;
> + }
> +}
> +
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> +
> + return 0;
> +}
> +
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int guard_width, guard_height;
> +
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> + ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + mfc_debug(2,
> + "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
> + ctx->img_width, ctx->img_height, ctx->buf_width,
> + ctx->buf_height);
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> + ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->chroma_size = ALIGN(ctx->buf_width *
> + ALIGN((ctx->img_height >> 1),
> + S5P_FIMV_NV12MT_VALIGN),
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->mv_size = ALIGN(ctx->buf_width *
> + ALIGN((ctx->buf_height >> 2),
> + S5P_FIMV_NV12MT_VALIGN),
> + S5P_FIMV_DEC_BUF_ALIGN);
> + } else {
> + guard_width =
> + ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
> + guard_height =
> + ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
> + ctx->luma_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> +
> + guard_width =
> + ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
> + guard_height =
> + ALIGN((ctx->img_height >> 1) + 4,
> + S5P_FIMV_NV12MT_VALIGN);
> + ctx->chroma_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> +
> + ctx->mv_size = 0;
> + }
> +}
> +
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
> + ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
> + * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
> + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
> }
> }
>
> @@ -290,16 +366,17 @@ void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
> void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
> - mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
> + mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
> + mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
> }
>
> /* Set registers for shared buffer */
> static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> - mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> + mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> }
>
> /* Set registers for decoding stream buffer */
> @@ -311,7 +388,7 @@ int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
> mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
> mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
> - s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
> + s5p_mfc_write_info(ctx, start_num_byte, START_BYTE_NUM);
> return 0;
> }
>
> @@ -438,10 +515,10 @@ int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
> mfc_debug(2, "Not enough memory has been allocated\n");
> return -ENOMEM;
> }
> - s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> - s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
> + s5p_mfc_write_info(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> + s5p_mfc_write_info(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
> if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
> - s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
> + s5p_mfc_write_info(ctx, frame_size_mv, ALLOC_MV_SIZE);
> mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
> << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
> S5P_FIMV_SI_CH0_INST_ID);
> @@ -685,16 +762,16 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> /* reaction coefficient */
> if (p->rc_frame)
> mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> + shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
> /* seq header ctrl */
> shm &= ~(0x1 << 3);
> shm |= (p->seq_hdr_mode << 3);
> /* frame skip mode */
> shm &= ~(0x3 << 1);
> shm |= (p->frame_skip_mode << 1);
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> + s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
> /* fixed target bit */
> - s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
> + s5p_mfc_write_info(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
> return 0;
> }
>
> @@ -723,9 +800,9 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> reg |= p_264->profile;
> mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> /* interlace */
> - mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> + mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> /* height */
> - if (p->interlace)
> + if (p_264->interlace)
> mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
> /* loopfilter ctrl */
> mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
> @@ -767,7 +844,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> /* macroblock level rate control */
> reg &= ~(0x1 << 8);
> - reg |= (p_264->rc_mb << 8);
> + reg |= (p->rc_mb << 8);
> /* frame QP */
> reg &= ~(0x3F);
> reg |= p_264->rc_frame_qp;
> @@ -788,7 +865,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> reg |= p_264->rc_min_qp;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> /* macroblock adaptive scaling features */
> - if (p_264->rc_mb) {
> + if (p->rc_mb) {
> reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
> /* dark region */
> reg &= ~(0x1 << 3);
> @@ -804,37 +881,36 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> reg |= p_264->rc_mb_activity;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
> }
> - if (!p->rc_frame &&
> - !p_264->rc_mb) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> + if (!p->rc_frame && !p->rc_mb) {
> + shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
> shm &= ~(0xFFF);
> shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
> shm |= (p_264->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> + s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
> }
> /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> + shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
> /* AR VUI control */
> shm &= ~(0x1 << 15);
> shm |= (p_264->vui_sar << 1);
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> + s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
> if (p_264->vui_sar) {
> /* aspect ration IDC */
> - shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
> + shm = s5p_mfc_read_info(ctx, SAMPLE_ASPECT_RATIO_IDC);
> shm &= ~(0xFF);
> shm |= p_264->vui_sar_idc;
> - s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
> + s5p_mfc_write_info(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
> if (p_264->vui_sar_idc == 0xFF) {
> /* sample AR info */
> - shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
> + shm = s5p_mfc_read_info(ctx, EXTENDED_SAR);
> shm &= ~(0xFFFFFFFF);
> shm |= p_264->vui_ext_sar_width << 16;
> shm |= p_264->vui_ext_sar_height;
> - s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
> + s5p_mfc_write_info(ctx, shm, EXTENDED_SAR);
> }
> }
> /* intra picture period for H.264 */
> - shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
> + shm = s5p_mfc_read_info(ctx, H264_I_PERIOD);
> /* control */
> shm &= ~(0x1 << 16);
> shm |= (p_264->open_gop << 16);
> @@ -843,16 +919,16 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> shm &= ~(0xFFFF);
> shm |= p_264->open_gop_size;
> }
> - s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
> + s5p_mfc_write_info(ctx, shm, H264_I_PERIOD);
> /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> + shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
> /* vbv buffer size */
> if (p->frame_skip_mode ==
> V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> shm &= ~(0xFFFF << 16);
> shm |= (p_264->cpb_size << 16);
> }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> + s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
> return 0;
> }
>
> @@ -885,11 +961,11 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
> /* qp */
> if (!p->rc_frame) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> + shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
> shm &= ~(0xFFF);
> shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
> shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> + s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
> }
> /* frame rate */
> if (p->rc_frame) {
> @@ -898,12 +974,12 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> p->rc_framerate_denom;
> mfc_write(dev, framerate,
> S5P_FIMV_ENC_RC_FRAME_RATE);
> - shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
> + shm = s5p_mfc_read_info(ctx, RC_VOP_TIMING);
> shm &= ~(0xFFFFFFFF);
> shm |= (1 << 31);
> shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
> shm |= (p->rc_framerate_denom & 0xFFFF);
> - s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
> + s5p_mfc_write_info(ctx, shm, RC_VOP_TIMING);
> }
> } else {
> mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> @@ -924,14 +1000,14 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> reg |= p_mpeg4->rc_min_qp;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> + shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
> /* vbv buffer size */
> if (p->frame_skip_mode ==
> V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> shm &= ~(0xFFFF << 16);
> shm |= (p->vbv_size << 16);
> }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> + s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
> return 0;
> }
>
> @@ -946,10 +1022,10 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> s5p_mfc_set_enc_params(ctx);
> /* qp */
> if (!p->rc_frame) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> + shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
> shm &= ~(0xFFF);
> shm |= (p_h263->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> + s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
> }
> /* frame rate */
> if (p->rc_frame && p->rc_framerate_denom)
> @@ -973,14 +1049,14 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> reg |= p_h263->rc_min_qp;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> + shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
> /* vbv buffer size */
> if (p->frame_skip_mode ==
> V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> shm &= ~(0xFFFF << 16);
> shm |= (p->vbv_size << 16);
> }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> + s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
> return 0;
> }
>
> @@ -1395,3 +1471,21 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
> }
> }
>
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> +{
> + mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> +}
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs)
> +{
> + s5p_mfc_write_shm(ctx, data, ofs);
> +}
> +
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> + unsigned int ofs)
> +{
> + return s5p_mfc_read_shm(ctx, ofs);
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> index 5932d1c..6b49a7c 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> @@ -50,8 +50,20 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
> int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
> void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
>
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
> +
> void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
> void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs);
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> + unsigned int ofs);
>
> #define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
> S5P_FIMV_SI_DISPLAY_Y_ADR) << \
> @@ -63,9 +75,13 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> S5P_FIMV_SI_DISPLAY_STATUS)
> #define s5p_mfc_get_dec_status() readl(dev->regs_base + \
> S5P_FIMV_SI_DECODE_STATUS)
> -#define s5p_mfc_get_frame_type() (readl(dev->regs_base + \
> +#define s5p_mfc_get_dec_frame_type() (readl(dev->regs_base + \
> S5P_FIMV_DECODE_FRAME_TYPE) \
> & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_disp_frame_type() ((s5p_mfc_read_shm(ctx, \
> + DISP_PIC_FRAME_TYPE) \
> + >> S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) \
> + & S5P_FIMV_DECODE_FRAME_MASK)
> #define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
> S5P_FIMV_SI_CONSUMED_BYTES)
> #define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
> @@ -89,5 +105,12 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> S5P_FIMV_ENC_SI_STRM_SIZE)
> #define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
> S5P_FIMV_ENC_SI_SLICE_TYPE)
> +#define s5p_mfc_get_enc_dpb_count() -1
> +#define s5p_mfc_get_enc_pic_count() readl(dev->regs_base + \
> + S5P_FIMV_ENC_SI_PIC_CNT)
> +#define s5p_mfc_get_sei_avail_status() s5p_mfc_read_shm(ctx, \
> + FRAME_PACK_SEI_AVAIL)
> +#define s5p_mfc_get_mvc_num_views() -1
> +#define s5p_mfc_get_mvc_view_id() -1
>
> #endif /* S5P_MFC_OPR_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> new file mode 100644
> index 0000000..8e68ecc
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> @@ -0,0 +1,1697 @@
> +/*
> + * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> + *
> + * Samsung MFC (Multi Function Codec - FIMV) driver
> + * This file contains hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#undef DEBUG
> +
> +#include <linux/delay.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/jiffies.h>
> +#include <linux/firmware.h>
> +#include <linux/err.h>
> +#include <linux/sched.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_intr.h"
> +#include "s5p_mfc_pm.h"
> +#include "s5p_mfc_debug.h"
> +
> +/* #define S5P_MFC_DEBUG_REGWRITE */
> +#ifdef S5P_MFC_DEBUG_REGWRITE
> +#undef writel
> +#define writel(v, r) \
> + do { \
> + pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v); \
> + __raw_writel(v, r); \
> + } while (0)
> +#endif /* S5P_MFC_DEBUG_REGWRITE */
> +
> +#define READL(offset) readl(dev->regs_base + (offset))
> +#define WRITEL(data, offset) writel((data), dev->regs_base + (offset))
> +#define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
> +#define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
> +
> +/* Allocate temporary buffers for decoding */
> +int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +
> + return 0;
> +}
> +
> +/* Release temproary buffers for decoding */
> +void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +}
> +
> +/* Allocate codec buffers */
> +int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int mb_width, mb_height;
> +
> + mb_width = mb_width(ctx->img_width);
> + mb_height = mb_height(ctx->img_height);
> +
> + if (ctx->type == MFCINST_DECODER) {
> + mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
> + ctx->luma_size, ctx->chroma_size, ctx->mv_size);
> + mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
> + } else if (ctx->type == MFCINST_ENCODER) {
> + ctx->tmv_buffer_size = 2 * ALIGN((mb_width + 1) *
> + (mb_height + 1) * 8, 16);
> + ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * 256, 256);
> + ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * 128, 256);
> + ctx->me_buffer_size = ALIGN(((((ctx->img_width+63)/64) * 16) *
> + (((ctx->img_height+63)/64) * 16)) +
> + ((((mb_width*mb_height)+31)/32) * 16), 256);
> +
> + mfc_debug(2, "recon luma size: %d chroma size: %d\n",
> + ctx->luma_dpb_size, ctx->chroma_dpb_size);
> + } else {
> + return -EINVAL;
> + }
> +
> + /* Codecs have different memory requirements */
> + switch (ctx->codec_mode) {
> + case S5P_FIMV_CODEC_H264_DEC:
> + case S5P_FIMV_CODEC_H264_MVC_DEC:
> + ctx->scratch_buf_size = (mb_width * 128) + 65536;
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size =
> + ctx->scratch_buf_size +
> + (ctx->total_dpb_count * ctx->mv_size);
> + break;
> + case S5P_FIMV_CODEC_MPEG4_DEC:
> + /* mb_width * (mb_height * 64 + 144) + 8192 * mb_height +
> + * 41088 */
> + ctx->scratch_buf_size = mb_width * (mb_height * 64 + 144) +
> + ((2048 + 15)/16 * mb_height * 64) +
> + ((2048 + 15)/16 * 256 + 8320);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_FIMV_CODEC_VC1RCV_DEC:
> + case S5P_FIMV_CODEC_VC1_DEC:
> + ctx->scratch_buf_size = 2096 * (mb_width + mb_height + 1);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_FIMV_CODEC_MPEG2_DEC:
> + ctx->bank1_size = 0;
> + ctx->bank2_size = 0;
> + break;
> + case S5P_FIMV_CODEC_H263_DEC:
> + ctx->scratch_buf_size = mb_width * 400;
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_FIMV_CODEC_VP8_DEC:
> + ctx->scratch_buf_size = mb_width * 32 + mb_height * 128 + 34816;
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_FIMV_CODEC_H264_ENC:
> + ctx->scratch_buf_size = (mb_width * 64) +
> + ((mb_width + 1) * 16) + (4096 * 16);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size =
> + ctx->scratch_buf_size + ctx->tmv_buffer_size +
> + (ctx->dpb_count * (ctx->luma_dpb_size +
> + ctx->chroma_dpb_size + ctx->me_buffer_size));
> + ctx->bank2_size = 0;
> + break;
> + case S5P_FIMV_CODEC_MPEG4_ENC:
> + case S5P_FIMV_CODEC_H263_ENC:
> + ctx->scratch_buf_size = (mb_width * 16) + ((mb_width + 1) * 16);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> + ctx->bank1_size =
> + ctx->scratch_buf_size + ctx->tmv_buffer_size +
> + (ctx->dpb_count * (ctx->luma_dpb_size +
> + ctx->chroma_dpb_size + ctx->me_buffer_size));
> + ctx->bank2_size = 0;
> + break;
> + default:
> + break;
> + }
> +
> + /* Allocate only if memory from bank 1 is necessary */
> + if (ctx->bank1_size > 0) {
> + ctx->bank1_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
> + if (IS_ERR(ctx->bank1_buf)) {
> + ctx->bank1_buf = 0;
> + pr_err("Buf alloc for decoding failed (port A)\n");
> + return -ENOMEM;
> + }
> + ctx->bank1_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
> + BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + }
> +
> + return 0;
> +}
> +
> +/* Release buffers allocated for codec */
> +void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->bank1_buf) {
> + vb2_dma_contig_memops.put(ctx->bank1_buf);
> + ctx->bank1_buf = 0;
> + ctx->bank1_phys = 0;
> + ctx->bank1_size = 0;
> + }
> +}
> +
> +/* Allocate memory for instance data buffer */
> +int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + mfc_debug_enter();
> +
> + switch (ctx->codec_mode) {
> + case S5P_FIMV_CODEC_H264_DEC:
> + case S5P_FIMV_CODEC_H264_MVC_DEC:
> + ctx->ctx_size = buf_size->h264_dec_ctx;
> + break;
> + case S5P_FIMV_CODEC_MPEG4_DEC:
> + case S5P_FIMV_CODEC_H263_DEC:
> + case S5P_FIMV_CODEC_VC1RCV_DEC:
> + case S5P_FIMV_CODEC_VC1_DEC:
> + case S5P_FIMV_CODEC_MPEG2_DEC:
> + case S5P_FIMV_CODEC_VP8_DEC:
> + ctx->ctx_size = buf_size->other_dec_ctx;
> + break;
> + case S5P_FIMV_CODEC_H264_ENC:
> + ctx->ctx_size = buf_size->h264_enc_ctx;
> + break;
> + case S5P_FIMV_CODEC_MPEG4_ENC:
> + case S5P_FIMV_CODEC_H263_ENC:
> + ctx->ctx_size = buf_size->other_enc_ctx;
> + break;
> + default:
> + ctx->ctx_size = 0;
> + mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
> + break;
> + }
> +
> + ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> + if (IS_ERR(ctx->ctx.alloc)) {
> + mfc_err("Allocating context buffer failed.\n");
> + return PTR_ERR(ctx->ctx.alloc);
> + }
> +
> + ctx->ctx.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> +
> + ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> + if (!ctx->ctx.virt) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.dma = 0;
> + ctx->ctx.virt = NULL;
> +
> + mfc_err("Remapping context buffer failed.\n");
> + return -ENOMEM;
> + }
> +
> + memset(ctx->ctx.virt, 0, ctx->ctx_size);
> + wmb();
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Release instance buffer */
> +void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + mfc_debug_enter();
> +
> + if (ctx->ctx.alloc) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.dma = 0;
> + ctx->ctx.virt = NULL;
> + }
> +
> + mfc_debug_leave();
> +}
> +
> +/* Allocate context buffers for SYS_INIT */
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + mfc_debug_enter();
> +
> + dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
> + if (IS_ERR(dev->ctx_buf.alloc)) {
> + mfc_err("Allocating DESC buffer failed.\n");
> + return PTR_ERR(dev->ctx_buf.alloc);
> + }
> +
> + dev->ctx_buf.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> + dev->ctx_buf.alloc);
> +
> + dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
> + if (!dev->ctx_buf.virt) {
> + vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> + dev->ctx_buf.alloc = NULL;
> + dev->ctx_buf.dma = 0;
> +
> + mfc_err("Remapping DESC buffer failed.\n");
> + return -ENOMEM;
> + }
> +
> + memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
> + wmb();
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Release context buffers for SYS_INIT */
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> + if (dev->ctx_buf.alloc) {
> + vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> + dev->ctx_buf.alloc = NULL;
> + dev->ctx_buf.dma = 0;
> + dev->ctx_buf.virt = NULL;
> + }
> +}
> +
> +static int calc_plane(int width, int height)
> +{
> + int mbX, mbY;
> +
> + mbX = (width + 15)/16;
> + mbY = (height + 15)/16;
> +
> + if (width * height < 2048 * 1024)
> + mbY = (mbY + 1) / 2 * 2;
> +
> + return (mbX * 16) * (mbY * 16);
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
> +{
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> + ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
> + "buffer dimensions: %dx%d\n", ctx->img_width,
> + ctx->img_height, ctx->buf_width, ctx->buf_height);
> +
> + ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
> + ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) {
> + ctx->mv_size = s5p_mfc_dec_mv_size(ctx->img_width,
> + ctx->img_height);
> + ctx->mv_size = ALIGN(ctx->mv_size, 16);
> + } else {
> + ctx->mv_size = 0;
> + }
> +}
> +
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int mb_width, mb_height;
> +
> + mb_width = mb_width(ctx->img_width);
> + mb_height = mb_height(ctx->img_height);
> +
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
> + ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
> + ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
> +}
> +
> +/* Set registers for decoding stream buffer */
> +int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> + unsigned int start_num_byte, unsigned int strm_size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
> +
> + mfc_debug_enter();
> + mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
> + "buf_size: 0x%08x (%d)\n",
> + ctx->inst_no, buf_addr, strm_size, strm_size);
> + WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
> + WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR);
> + WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE);
> + WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET);
> +
> + mfc_debug_leave();
> + return 0;
> +}
> +
> +/* Set decoding frame buffer */
> +int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int frame_size, i;
> + unsigned int frame_size_ch, frame_size_mv;
> + struct s5p_mfc_dev *dev = ctx->dev;
> + size_t buf_addr1;
> + int buf_size1;
> + int align_gap;
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> +
> + mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> + mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
> + mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
> +
> + WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB);
> + WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE);
> + WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE);
> +
> + WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR);
> + WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE);
> + buf_addr1 += ctx->scratch_buf_size;
> + buf_size1 -= ctx->scratch_buf_size;
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC)
> + WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE);
> +
> + frame_size = ctx->luma_size;
> + frame_size_ch = ctx->chroma_size;
> + frame_size_mv = ctx->mv_size;
> + mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
> + frame_size, frame_size_ch, frame_size_mv);
> +
> + for (i = 0; i < ctx->total_dpb_count; i++) {
> + /* Bank2 */
> + mfc_debug(2, "Luma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.luma);
> + WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
> + S5P_FIMV_D_LUMA_DPB + i * 4);
> + mfc_debug(2, "\tChroma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.chroma);
> + WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
> + S5P_FIMV_D_CHROMA_DPB + i * 4);
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode ==
> + S5P_FIMV_CODEC_H264_MVC_DEC) {
> + /* To test alignment */
> + align_gap = buf_addr1;
> + buf_addr1 = ALIGN(buf_addr1, 16);
> + align_gap = buf_addr1 - align_gap;
> + buf_size1 -= align_gap;
> +
> + mfc_debug(2, "\tBuf1: %x, size: %d\n",
> + buf_addr1, buf_size1);
> + WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER + i * 4);
> + buf_addr1 += frame_size_mv;
> + buf_size1 -= frame_size_mv;
> + }
> + }
> +
> + mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
> + buf_addr1, buf_size1, ctx->total_dpb_count);
> + if (buf_size1 < 0) {
> + mfc_debug(2, "Not enough memory has been allocated.\n");
> + return -ENOMEM;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
> +
> + mfc_debug(2, "After setting buffers.\n");
> + return 0;
> +}
> +
> +/* Set registers for encoding stream buffer */
> +int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long addr, unsigned int size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
> + WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
> +
> + mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
> + addr, size);
> +
> + return 0;
> +}
> +
> +void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long y_addr, unsigned long c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR); /* 256B align */
> + WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR);
> +
> + mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
> + mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
> +}
> +
> +void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long *y_addr, unsigned long *c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long enc_recon_y_addr, enc_recon_c_addr;
> +
> + *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR);
> + *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR);
> +
> + enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR);
> + enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR);
> +
> + mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
> + mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
> +}
> +
> +/* Set encoding ref & codec buffer */
> +int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + size_t buf_addr1, buf_size1;
> + int i;
> +
> + mfc_debug_enter();
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> +
> + mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> +
> + for (i = 0; i < ctx->dpb_count; i++) {
> + WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB + (4 * i));
> + buf_addr1 += ctx->luma_dpb_size;
> + WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB + (4 * i));
> + buf_addr1 += ctx->chroma_dpb_size;
> + WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER + (4 * i));
> + buf_addr1 += ctx->me_buffer_size;
> + buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
> + ctx->me_buffer_size);
> + }
> +
> + WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR);
> + WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE);
> + buf_addr1 += ctx->scratch_buf_size;
> + buf_size1 -= ctx->scratch_buf_size;
> +
> + WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0);
> + buf_addr1 += ctx->tmv_buffer_size >> 1;
> + WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1);
> + buf_addr1 += ctx->tmv_buffer_size >> 1;
> + buf_size1 -= ctx->tmv_buffer_size;
> +
> + mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
> + buf_addr1, buf_size1, ctx->dpb_count);
> + if (buf_size1 < 0) {
> + mfc_debug(2, "Not enough memory has been allocated.\n");
> + return -ENOMEM;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + /* multi-slice control */
> + /* multi-slice MB number or bit size */
> + WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE);
> + if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> + WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
> + } else if (ctx->slice_mode ==
> + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
> + WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
> + } else {
> + WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
> + WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS);
> + }
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + /* width */
> + WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH); /* 16 align */
> + /* height */
> + WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT); /* 16 align */
> +
> + /* cropped width */
> + WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
> + /* cropped height */
> + WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
> + /* cropped offset */
> + WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
> +
> + /* pictype : IDR period */
> + reg = 0;
> + reg |= p->gop_size & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> + /* multi-slice control */
> + /* multi-slice MB number or bit size */
> + ctx->slice_mode = p->slice_mode;
> + reg = 0;
> + if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> + reg |= (0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> + ctx->slice_size.mb = p->slice_mb;
> + } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
> + reg |= (0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> + ctx->slice_size.bits = p->slice_bit;
> + } else {
> + reg &= ~(0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> + }
> +
> + s5p_mfc_set_slice_mode(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
> + 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_NV12M) {
> + /* 0: Linear, 1: 2D tiled*/
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> + reg &= ~(0x1 << 7);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
> + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
> + /* 0: Linear, 1: 2D tiled*/
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> + reg &= ~(0x1 << 7);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
> + } else 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);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x0, 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) {
> + reg = 0;
> + /** enable */
> + reg |= (1 << 31);
> + /** cr value */
> + reg |= ((p->pad_cr & 0xFF) << 16);
> + /** cb value */
> + reg |= ((p->pad_cb & 0xFF) << 8);
> + /** y value */
> + reg |= p->pad_luma & 0xFF;
> + WRITEL(reg, S5P_FIMV_E_PADDING_CTRL);
> + }
> +
> + /* rate control config. */
> + reg = 0;
> + /* frame-level rate control */
> + reg |= ((p->rc_frame & 0x1) << 9);
> + 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);
> +
> + /* reaction coefficient */
> + if (p->rc_frame) {
> + if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
> + WRITEL(1, S5P_FIMV_E_RC_RPARAM);
> + else /* loose CBR */
> + WRITEL(2, S5P_FIMV_E_RC_RPARAM);
> + }
> +
> + /* seq header ctrl */
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> + reg &= ~(0x1 << 2);
> + reg |= ((p->seq_hdr_mode & 0x1) << 2);
> +
> + /* frame skip mode */
> + reg &= ~(0x3);
> + reg |= (p->frame_skip_mode & 0x3);
> + 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] */
> + reg = 0;
> + reg &= ~(0x3FFF);
> + reg = 256;
> + WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE);
> +
> + reg = 0;
> + reg &= ~(0x3FFF);
> + reg = 256;
> + WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE);
> +
> + 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_RC_ROI_CTRL);
> + WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
> +
> + WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE);
> + WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT);
> + WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT);
> +
> + WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
> + WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> + unsigned int reg = 0;
> + int i;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* pictype : number of B */
> + reg = READL(S5P_FIMV_E_GOP_CONFIG);
> + reg &= ~(0x3 << 16);
> + reg |= ((p->num_b_frame & 0x3) << 16);
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> + /* profile & level */
> + reg = 0;
> + /** level */
> + reg |= ((p_h264->level & 0xFF) << 8);
> + /** profile - 0 ~ 3 */
> + reg |= p_h264->profile & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_h264->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_h264->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_h264->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p_h264->cpb_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> + }
> +
> + /* interlace */
> + reg = 0;
> + reg |= ((p_h264->interlace & 0x1) << 3);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* height */
> + if (p_h264->interlace) {
> + WRITEL(ctx->img_height >> 1,
> + S5P_FIMV_E_FRAME_HEIGHT); /* 32 align */
> + /* cropped height */
> + 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_h264->loop_filter_mode & 0x3) << 1);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* loopfilter alpha offset */
> + if (p_h264->loop_filter_alpha < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_h264->loop_filter_alpha & 0xF);
> + }
> + WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
> +
> + /* loopfilter beta offset */
> + if (p_h264->loop_filter_beta < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_h264->loop_filter_beta) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_h264->loop_filter_beta & 0xF);
> + }
> + WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
> +
> + /* entropy coding mode */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1);
> + reg |= p_h264->entropy_mode & 0x1;
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* number of ref. picture */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 7);
> + reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* 8x8 transform enable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x3 << 12);
> + reg |= ((p_h264->_8x8_transform & 0x3) << 12);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* macroblock adaptive scaling features */
> + WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG);
> + if (p->rc_mb) {
> + reg = 0;
> + /** dark region */
> + reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
> + /** smooth region */
> + reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
> + /** static region */
> + reg |= ((p_h264->rc_mb_static & 0x1) << 1);
> + /** high activity region */
> + reg |= p_h264->rc_mb_activity & 0x1;
> + WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
> + }
> +
> + /* aspect ratio VUI */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 5);
> + reg |= ((p_h264->vui_sar & 0x1) << 5);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
> + WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
> + if (p_h264->vui_sar) {
> + /* aspect ration IDC */
> + reg = 0;
> + reg |= p_h264->vui_sar_idc & 0xFF;
> + WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO);
> + if (p_h264->vui_sar_idc == 0xFF) {
> + /* extended SAR */
> + reg = 0;
> + reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
> + reg |= p_h264->vui_ext_sar_height & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
> + }
> + }
> +
> + /* intra picture period for H.264 open GOP */
> + /* control */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 4);
> + reg |= ((p_h264->open_gop & 0x1) << 4);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> + /* value */
> + WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD);
> + if (p_h264->open_gop) {
> + reg = 0;
> + reg |= p_h264->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 */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 6);
> + reg |= ((p_h264->aso & 0x1) << 6);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> + /* hier qp enable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 8);
> + reg |= ((p_h264->open_gop & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> + reg = 0;
> + if (p_h264->hier_qp && p_h264->hier_qp_layer) {
> + reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
> + reg |= p_h264->hier_qp_layer & 0x7;
> + WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
> + /* QP value for each layer */
> + for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
> + WRITEL(p_h264->hier_qp_layer_qp[i],
> + S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 + i * 4);
> + }
> + /* number of coding layer should be zero when hierarchical is disable */
> + WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
> +
> + /* frame packing SEI generation */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS);
> + reg &= ~(0x1 << 25);
> + reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> + if (p_h264->sei_frame_packing) {
> + reg = 0;
> + /** current frame0 flag */
> + reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
> + /** arrangement type */
> + reg |= p_h264->sei_fp_arrangement_type & 0x3;
> + WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO);
> + }
> +
> + if (p_h264->fmo) {
> + switch (p_h264->fmo_map_type) {
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
> + if (p_h264->fmo_slice_grp > 4)
> + p_h264->fmo_slice_grp = 4;
> + for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
> + WRITEL(p_h264->fmo_run_len[i] - 1,
> + S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 +
> + i * 4);
> + break;
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
> + if (p_h264->fmo_slice_grp > 4)
> + p_h264->fmo_slice_grp = 4;
> + break;
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
> + if (p_h264->fmo_slice_grp > 2)
> + p_h264->fmo_slice_grp = 2;
> + WRITEL(p_h264->fmo_chg_dir & 0x1,
> + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR);
> + /* the valid range is 0 ~ number of macroblocks -1 */
> + WRITEL(p_h264->fmo_chg_rate,
> + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1);
> + break;
> + default:
> + mfc_err("Unsupported map type for FMO: %d\n",
> + p_h264->fmo_map_type);
> + p_h264->fmo_map_type = 0;
> + p_h264->fmo_slice_grp = 1;
> + break;
> + }
> +
> + WRITEL(p_h264->fmo_map_type,
> + S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE);
> + WRITEL(p_h264->fmo_slice_grp - 1,
> + S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
> + } else {
> + WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
> + }
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* pictype : number of B */
> + reg = READL(S5P_FIMV_E_GOP_CONFIG);
> + reg &= ~(0x3 << 16);
> + reg |= ((p->num_b_frame & 0x3) << 16);
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> + /* profile & level */
> + reg = 0;
> + /** level */
> + reg |= ((p_mpeg4->level & 0xFF) << 8);
> + /** profile - 0 ~ 1 */
> + reg |= p_mpeg4->profile & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_mpeg4->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_mpeg4->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_mpeg4->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> + }
> +
> + /* Disable HEC */
> + WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS);
> + WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* profile & level */
> + reg = 0;
> + /** profile */
> + reg |= (0x1 << 4);
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_h263->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_h263->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_h263->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> + }
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Initialize decoding */
> +int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int reg = 0;
> + int fmo_aso_ctrl = 0;
> +
> + mfc_debug_enter();
> + mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_CH_SEQ_HEADER);
> + mfc_debug(2, "BUFs: %08x %08x %08x\n",
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR));
> +
> + /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
> + reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK);
> +
> + /* When user sets desplay_delay to 0,
> + * It works as "display_delay enable" and delay set to 0.
> + * If user wants display_delay disable, It should be
> + * set to negative value. */
> + if (ctx->display_delay >= 0) {
> + reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT);
> + WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY);
> + }
> + /* Setup loop filter, for decoding this is only valid for MPEG4 */
> + if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC) {
> + mfc_debug(2, "Set loop filter to: %d\n",
> + ctx->loop_filter_mpeg4);
> + reg |= (ctx->loop_filter_mpeg4 <<
> + S5P_FIMV_D_OPT_LF_CTRL_SHIFT);
> + }
> + if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
> + reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT);
> +
> + WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
> +
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
> + WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
> + else
> + WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
> +
> + /* sei parse */
> + WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
> +
> + mfc_debug_leave();
> + return 0;
> +}
> +
> +static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int dpb;
> + if (flush)
> + dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
> + else
> + dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
> + WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> +}
> +
> +/* Decode a single frame */
> +int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);
> + WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);
> + WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + /* Issue different commands to instance basing on whether it
> + * is the last frame or not. */
> + switch (last_frame) {
> + case 0:
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
> + break;
> + case 1:
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_LAST_FRAME, NULL);
> + break;
> + }
> +
> + mfc_debug(2, "Decoding a usual frame.\n");
> + return 0;
> +}
> +
> +int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> + s5p_mfc_set_enc_params_h264(ctx);
> + else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
> + s5p_mfc_set_enc_params_mpeg4(ctx);
> + else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
> + s5p_mfc_set_enc_params_h263(ctx);
> + else {
> + mfc_err("Unknown codec for encoding (%x).\n",
> + ctx->codec_mode);
> + return -EINVAL;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
> +
> + return 0;
> +}
> +
> +int s5p_mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> + int i;
> +
> + if (p_h264->aso) {
> + for (i = 0; i < 8; i++)
> + WRITEL(p_h264->aso_slice_order[i],
> + S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 + i * 4);
> + }
> + return 0;
> +}
> +
> +/* Encode a single frame */
> +int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_debug(2, "++\n");
> +
> + /* memory structure cur. frame */
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> + s5p_mfc_h264_set_aso_slice_order(ctx);
> +
> + s5p_mfc_set_slice_mode(ctx);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> + s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
> +
> + mfc_debug(2, "--\n");
> +
> + return 0;
> +}
> +
> +static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
> +{
> + unsigned long flags;
> + int new_ctx;
> + int cnt;
> +
> + spin_lock_irqsave(&dev->condlock, flags);
> + mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
> + dev->ctx_work_bits);
> + new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
> + cnt = 0;
> + while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
> + new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
> + cnt++;
> + if (cnt > MFC_NUM_CONTEXTS) {
> + /* No contexts to run */
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return -EAGAIN;
> + }
> + }
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return new_ctx;
> +}
> +
> +static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf *temp_vb;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + /* Frames are being decoded */
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "No src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return;
> + }
> + /* Get the next source buffer */
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + temp_vb->used = 1;
> + s5p_mfc_set_dec_stream_buffer(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_decode_one_frame(ctx, 1);
> +}
> +
> +static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf *temp_vb;
> + unsigned long flags;
> + int last_frame = 0;
> + unsigned int index;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + /* Frames are being decoded */
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "No src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> + /* Get the next source buffer */
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + temp_vb->used = 1;
> + s5p_mfc_set_dec_stream_buffer(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
> + temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + index = temp_vb->b->v4l2_buf.index;
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
> + last_frame = 1;
> + mfc_debug(2, "Setting ctx->state to FINISHING\n");
> + ctx->state = MFCINST_FINISHING;
> + }
> + s5p_mfc_decode_one_frame(ctx, last_frame);
> +
> + return 0;
> +}
> +
> +static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + struct s5p_mfc_buf *src_mb;
> + unsigned long src_y_addr, src_c_addr, dst_addr;
> + /*
> + unsigned int src_y_size, src_c_size;
> + */
> + unsigned int dst_size;
> + unsigned int index;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "no src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> +
> + if (list_empty(&ctx->dst_queue)) {
> + mfc_debug(2, "no dst buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> +
> + src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + src_mb->used = 1;
> + src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> + src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> +
> + mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
> + mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
> +
> + s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
> +
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_mb->used = 1;
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> +
> + s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> +
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + index = src_mb->b->v4l2_buf.index;
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_encode_one_frame(ctx);
> +
> + return 0;
> +}
> +
> +static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *temp_vb;
> +
> + /* Initializing decoding - parsing header */
> + spin_lock_irqsave(&dev->irqlock, flags);
> + mfc_debug(2, "Preparing to init decoding.\n");
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
> + s5p_mfc_set_dec_stream_buffer(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
> + temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_decode(ctx);
> +}
> +
> +static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + unsigned long dst_addr;
> + unsigned int dst_size;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> + s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_encode(ctx);
> +}
> +
> +static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> + /* Header was parsed now start processing
> + * First set the output frame buffers
> + * s5p_mfc_alloc_dec_buffers(ctx); */
> +
> + if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
> + mfc_err("It seems that not all destionation buffers were\n"
> + "mmaped.MFC requires that all destination are mmaped\n"
> + "before starting processing.\n");
> + return -EAGAIN;
> + }
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_set_dec_frame_buffer(ctx);
> + if (ret) {
> + mfc_err("Failed to alloc frame mem.\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> +
> + ret = s5p_mfc_alloc_codec_buffers(ctx);
> + if (ret) {
> + mfc_err("Failed to allocate encoding buffers.\n");
> + return -ENOMEM;
> + }
> +
> + /* Header was generated now starting processing
> + * First set the reference frame buffers
> + */
> + if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
> + mfc_err("It seems that destionation buffers were not\n"
> + "requested.MFC requires that header should be generated\n"
> + "before allocating codec buffer.\n");
> + return -EAGAIN;
> + }
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_set_enc_ref_buffer(ctx);
> + if (ret) {
> + mfc_err("Failed to alloc frame mem.\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +/* Try running an operation on hardware */
> +void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_ctx *ctx;
> + int new_ctx;
> + unsigned int ret = 0;
> +
> + mfc_debug(1, "Try run dev: %p\n", dev);
> +
> + /* Check whether hardware is not running */
> + if (test_and_set_bit(0, &dev->hw_lock) != 0) {
> + /* This is perfectly ok, the scheduled ctx should wait */
> + mfc_debug(1, "Couldn't lock HW.\n");
> + return;
> + }
> +
> + /* Choose the context to run */
> + new_ctx = s5p_mfc_get_new_ctx(dev);
> + if (new_ctx < 0) {
> + /* No contexts to run */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
> + mfc_err("Failed to unlock hardware.\n");
> + return;
> + }
> +
> + mfc_debug(1, "No ctx is scheduled to be run.\n");
> + return;
> + }
> +
> + mfc_debug(1, "New context: %d\n", new_ctx);
> + ctx = dev->ctx[new_ctx];
> + mfc_debug(1, "Seting new context to %p\n", ctx);
> + /* Got context to run in ctx */
> + mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
> + ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
> + mfc_debug(1, "ctx->state=%d\n", ctx->state);
> + /* Last frame has already been sent to MFC
> + * Now obtaining frames from MFC buffer */
> +
> + s5p_mfc_clock_on();
> + if (ctx->type == MFCINST_DECODER) {
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_dec_frame(ctx);
> + break;
> + case MFCINST_INIT:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_open_inst_cmd(ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_close_inst_cmd(ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + case MFCINST_HEAD_PARSED:
> + ret = s5p_mfc_run_init_dec_buffers(ctx);
> + break;
> + case MFCINST_RES_CHANGE_INIT:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RES_CHANGE_FLUSH:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RES_CHANGE_END:
> + mfc_debug(2, "Finished remaining frames after resolution change.\n");
> + ctx->capture_state = QUEUE_FREE;
> + mfc_debug(2, "Will re-init the codec`.\n");
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else if (ctx->type == MFCINST_ENCODER) {
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_enc_frame(ctx);
> + break;
> + case MFCINST_INIT:
> + ret = s5p_mfc_open_inst_cmd(ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + ret = s5p_mfc_close_inst_cmd(ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_enc(ctx);
> + break;
> + case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
> + ret = s5p_mfc_run_init_enc_buffers(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else {
> + mfc_err("invalid context type: %d\n", ctx->type);
> + ret = -EAGAIN;
> + }
> +
> + if (ret) {
> + /* Free hardware lock */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> + mfc_err("Failed to unlock hardware.\n");
> +
> + /* This is in deed imporant, as no operation has been
> + * scheduled, reduce the clock count as no one will
> + * ever do this, because no interrupt related to this try_run
> + * will ever come from hardware. */
> + s5p_mfc_clock_off();
> + }
> +}
> +
> +
> +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
> +{
> + struct s5p_mfc_buf *b;
> + int i;
> +
> + while (!list_empty(lh)) {
> + b = list_entry(lh->next, struct s5p_mfc_buf, list);
> + for (i = 0; i < b->b->num_planes; i++)
> + vb2_set_plane_payload(b->b, i, 0);
> + vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
> + list_del(&b->list);
> + }
> +}
> +
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> +{
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT);
> +}
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + s5p_mfc_clock_on();
> + WRITEL(data, ofs);
> + s5p_mfc_clock_off();
> +}
> +
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> +
> + s5p_mfc_clock_on();
> + ret = READL(ofs);
> + s5p_mfc_clock_off();
> +
> + return ret;
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> new file mode 100644
> index 0000000..93ce2d8
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> @@ -0,0 +1,140 @@
> +/*
> + * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> + *
> + * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
> + * Contains declarations of hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef S5P_MFC_OPR_V6_H_
> +#define S5P_MFC_OPR_V6_H_
> +
> +#include "s5p_mfc_common.h"
> +
> +#define MFC_CTRL_MODE_CUSTOM MFC_CTRL_MODE_SFR
> +
> +int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
> +
> +int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> + unsigned int start_num_byte,
> + unsigned int buf_size);
> +
> +void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long y_addr, unsigned long c_addr);
> +int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long addr, unsigned int size);
> +void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> + unsigned long *y_addr, unsigned long *c_addr);
> +int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
> +
> +int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
> +int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
> +
> +/* Memory allocation */
> +int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> +
> +int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
> +
> +int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
> +
> +#define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
> + S5P_FIMV_SI_DISPLAY_Y_ADR))
> +#define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \
> + S5P_FIMV_D_DISPLAY_LUMA_ADDR))
> +#define s5p_mfc_get_dspl_status() readl(dev->regs_base + \
> + S5P_FIMV_D_DISPLAY_STATUS)
> +#define s5p_mfc_get_decoded_status() readl(dev->regs_base + \
> + S5P_FIMV_D_DECODED_STATUS)
> +#define s5p_mfc_get_dec_frame_type() (readl(dev->regs_base + \
> + S5P_FIMV_D_DECODED_FRAME_TYPE) \
> + & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_disp_frame_type() (readl(ctx->dev->regs_base + \
> + S5P_FIMV_D_DISPLAY_FRAME_TYPE) \
> + & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
> + S5P_FIMV_D_DECODED_NAL_SIZE)
> +#define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
> + S5P_FIMV_RISC2HOST_CMD) & \
> + S5P_FIMV_RISC2HOST_CMD_MASK)
> +#define s5p_mfc_get_int_err() readl(dev->regs_base + \
> + S5P_FIMV_ERROR_CODE)
> +#define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
> + S5P_FIMV_ERR_DEC_SHIFT)
> +#define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
> + S5P_FIMV_ERR_DSPL_SHIFT)
> +#define s5p_mfc_get_img_width() readl(dev->regs_base + \
> + S5P_FIMV_D_DISPLAY_FRAME_WIDTH)
> +#define s5p_mfc_get_img_height() readl(dev->regs_base + \
> + S5P_FIMV_D_DISPLAY_FRAME_HEIGHT)
> +#define s5p_mfc_get_dpb_count() readl(dev->regs_base + \
> + S5P_FIMV_D_MIN_NUM_DPB)
> +#define s5p_mfc_get_inst_no() readl(dev->regs_base + \
> + S5P_FIMV_RET_INSTANCE_ID)
> +#define s5p_mfc_get_enc_dpb_count() readl(dev->regs_base + \
> + S5P_FIMV_E_NUM_DPB)
> +#define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \
> + S5P_FIMV_E_STREAM_SIZE)
> +#define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
> + S5P_FIMV_E_SLICE_TYPE)
> +#define s5p_mfc_get_enc_pic_count() readl(dev->regs_base + \
> + S5P_FIMV_E_PICTURE_COUNT)
> +#define s5p_mfc_get_sei_avail_status() readl(dev->regs_base + \
> + S5P_FIMV_D_FRAME_PACK_SEI_AVAIL)
> +#define s5p_mfc_get_mvc_num_views() readl(dev->regs_base + \
> + S5P_FIMV_D_MVC_NUM_VIEWS)
> +#define s5p_mfc_get_mvc_view_id() readl(dev->regs_base + \
> + S5P_FIMV_D_MVC_VIEW_ID)
> +
> +#define mb_width(x_size) ((x_size + 15) / 16)
> +#define mb_height(y_size) ((y_size + 15) / 16)
> +#define s5p_mfc_dec_mv_size(x, y) (mb_width(x) * \
> + (((mb_height(y)+1)/2)*2) * 64 + 128)
> +
> +/* Definition */
> +#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
> +#define ENC_MULTI_SLICE_BIT_MIN 2800
> +#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_H264_H263 1
> +#define TIGHT_CBR_MAX 10
> +
> +/* Definitions for shared memory compatibility */
> +#define PIC_TIME_TOP S5P_FIMV_D_RET_PICTURE_TAG_TOP
> +#define PIC_TIME_BOT S5P_FIMV_D_RET_PICTURE_TAG_BOT
> +#define CROP_INFO_H S5P_FIMV_D_DISPLAY_CROP_INFO1
> +#define CROP_INFO_V S5P_FIMV_D_DISPLAY_CROP_INFO2
> +
> +void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs);
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs);
> +
> +#endif /* S5P_MFC_OPR_V6_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> index 738a607..4fa0b54 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> @@ -20,7 +20,11 @@
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_pm.h"
>
> -#define MFC_CLKNAME "sclk_mfc"
> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> +#define MFC_CLKNAME "sclk_mfc"
> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> +#define MFC_CLKNAME "aclk_333"
I think it can handle clkname without new config.

Thank you,
Kyungmin Park
> +#endif
> #define MFC_GATE_CLK_NAME "mfc"
>
> #define CLK_DEBUG
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> index 91fdbac..9ee269d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> @@ -21,26 +21,28 @@ int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> - SHARED_BUF_SIZE);
> - if (IS_ERR(ctx->shm_alloc)) {
> + ctx->shm.alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> + buf_size->shm);
> + if (IS_ERR(ctx->shm.alloc)) {
> mfc_err("failed to allocate shared memory\n");
> - return PTR_ERR(ctx->shm_alloc);
> + return PTR_ERR(ctx->shm.alloc);
> }
> - /* shm_ofs only keeps the offset from base (port a) */
> - ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
> + /* shared memory offset only keeps the offset from base (port a) */
> + ctx->shm.ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm.alloc)
> - dev->bank1;
> - BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> - if (!ctx->shm) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_ofs = 0;
> - ctx->shm_alloc = NULL;
> + BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
> + ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
> + if (!ctx->shm.virt) {
> + vb2_dma_contig_memops.put(ctx->shm.alloc);
> + ctx->shm.alloc = NULL;
> + ctx->shm.ofs = 0;
> mfc_err("failed to virt addr of shared memory\n");
> return -ENOMEM;
> }
> - memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> + memset((void *)ctx->shm.virt, 0, buf_size->shm);
> wmb();
> return 0;
> }
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> index cf962a4..8400ab0 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> @@ -71,20 +71,23 @@ enum MFC_SHM_OFS {
> DBG_HISTORY_INPUT1 = 0xD4, /* C */
> DBG_HISTORY_OUTPUT = 0xD8, /* C */
> HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
> + FRAME_PACK_SEI_ENABLE = 0x168, /* C */
> + FRAME_PACK_SEI_AVAIL = 0x16c, /* D */
> + FRAME_PACK_SEI_INFO = 0x17c, /* E */
> };
>
> int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
>
> -#define s5p_mfc_write_shm(ctx, x, ofs) \
> - do { \
> - writel(x, (ctx->shm + ofs)); \
> - wmb(); \
> +#define s5p_mfc_write_shm(ctx, x, ofs) \
> + do { \
> + writel(x, (ctx->shm.virt + ofs)); \
> + wmb(); \
> } while (0)
>
> static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
> {
> rmb();
> - return readl(ctx->shm + ofs);
> + return readl(ctx->shm.virt + ofs);
> }
>
> #endif /* S5P_MFC_SHM_H_ */
> diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
> index 9abd9ab..61d6583 100644
> --- a/drivers/media/video/v4l2-ctrls.c
> +++ b/drivers/media/video/v4l2-ctrls.c
> @@ -502,7 +502,6 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> return mpeg4_profile;
> case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
> return jpeg_chroma_subsampling;
> -
> default:
> return NULL;
> }
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html