diff options
Diffstat (limited to 'drivers/media/platform/s5p-mfc')
21 files changed, 2493 insertions, 1214 deletions
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile index 379008c6d09..15f59b324fe 100644 --- a/drivers/media/platform/s5p-mfc/Makefile +++ b/drivers/media/platform/s5p-mfc/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc.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_pm.o diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h index 363a97cc768..51cb2dd0e13 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h @@ -141,6 +141,7 @@ #define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4 #define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8 #define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0 +#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6 0xf47c /* Display information register */ #define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500 @@ -229,6 +230,7 @@ #define S5P_FIMV_E_PADDING_CTRL_V6 0xf7a4 #define S5P_FIMV_E_MV_HOR_RANGE_V6 0xf7ac #define S5P_FIMV_E_MV_VER_RANGE_V6 0xf7b0 +#define S5P_FIMV_E_MV_RANGE_V6_MASK 0x3fff #define S5P_FIMV_E_VBV_BUFFER_SIZE_V6 0xf84c #define S5P_FIMV_E_VBV_INIT_DELAY_V6 0xf850 @@ -374,14 +376,13 @@ #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 /* Buffer size requirements defined by hardware */ -#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8) +#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 3) * 8) #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ - ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \ + (((((imw + 127) / 64) * 16) * DIV_ROUND_UP(imh, 64) * 256) + \ (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ - ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \ - (2048/16 * 256 + 8320)) + ((w) * 144 + 8192 * (h) + 49216 + 1048576) #define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \ (2096 * ((w) + (h) + 1)) #define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400) diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h new file mode 100644 index 00000000000..1a5c6fdf784 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h @@ -0,0 +1,60 @@ +/* + * Register definition file for Samsung MFC V7.x Interface (FIMV) driver + * + * Copyright (c) 2013 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 version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _REGS_MFC_V7_H +#define _REGS_MFC_V7_H + +#include "regs-mfc-v6.h" + +/* Additional features of v7 */ +#define S5P_FIMV_CODEC_VP8_ENC_V7 25 + +/* Additional registers for v7 */ +#define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0 +#define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4 +#define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8 +#define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7 0xf9ec +#define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7 0xf9f0 +#define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7 0xf9f4 + +#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7 0xfa70 +#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7 0xfa74 + +#define S5P_FIMV_E_VP8_OPTIONS_V7 0xfdb0 +#define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7 0xfdb4 +#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7 0xfdb8 +#define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4 + +/* MFCv7 variant defines */ +#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */ +#define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */ +#define MFC_VERSION_V7 0x72 +#define MFC_NUM_PORTS_V7 1 + +#define MFC_LUMA_PAD_BYTES_V7 256 +#define MFC_CHROMA_PAD_BYTES_V7 128 + +/* MFCv7 Context buffer sizes */ +#define MFC_CTX_BUF_SIZE_V7 (30 * SZ_1K) /* 30KB */ +#define MFC_H264_DEC_CTX_BUF_SIZE_V7 (2 * SZ_1M) /* 2MB */ +#define MFC_OTHER_DEC_CTX_BUF_SIZE_V7 (20 * SZ_1K) /* 20KB */ +#define MFC_H264_ENC_CTX_BUF_SIZE_V7 (100 * SZ_1K) /* 100KB */ +#define MFC_OTHER_ENC_CTX_BUF_SIZE_V7 (10 * SZ_1K) /* 10KB */ + +/* Buffer size defines */ +#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \ + (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216) + +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \ + (((w) * 48) + 8192 + ((((w) + 1) / 2) * 128) + 144 + \ + ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4)) + +#endif /*_REGS_MFC_V7_H*/ diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h new file mode 100644 index 00000000000..cc7cbec51b5 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h @@ -0,0 +1,124 @@ +/* + * Register definition file for Samsung MFC V8.x Interface (FIMV) driver + * + * Copyright (c) 2014 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 version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _REGS_MFC_V8_H +#define _REGS_MFC_V8_H + +#include <linux/sizes.h> +#include "regs-mfc-v7.h" + +/* Additional registers for v8 */ +#define S5P_FIMV_D_MVC_NUM_VIEWS_V8 0xf104 +#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8 0xf144 +#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8 0xf148 +#define S5P_FIMV_D_MV_BUFFER_SIZE_V8 0xf150 + +#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8 0xf138 +#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8 0xf13c + +#define S5P_FIMV_D_FIRST_PLANE_DPB_V8 0xf160 +#define S5P_FIMV_D_SECOND_PLANE_DPB_V8 0xf260 +#define S5P_FIMV_D_MV_BUFFER_V8 0xf460 + +#define S5P_FIMV_D_NUM_MV_V8 0xf134 +#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8 0xf154 + +#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8 0xf560 +#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8 0xf564 + +#define S5P_FIMV_D_CPB_BUFFER_ADDR_V8 0xf5b0 +#define S5P_FIMV_D_CPB_BUFFER_SIZE_V8 0xf5b4 +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8 0xf5bc +#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V8 0xf5c0 +#define S5P_FIMV_D_SLICE_IF_ENABLE_V8 0xf5c4 +#define S5P_FIMV_D_STREAM_DATA_SIZE_V8 0xf5d0 + +/* Display information register */ +#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8 0xf600 +#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8 0xf604 + +/* Display status */ +#define S5P_FIMV_D_DISPLAY_STATUS_V8 0xf608 + +#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8 0xf60c +#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8 0xf610 + +#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8 0xf618 +#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V8 0xf61c +#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V8 0xf620 +#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V8 0xf624 + +/* Decoded picture information register */ +#define S5P_FIMV_D_DECODED_STATUS_V8 0xf644 +#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8 0xf648 +#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8 0xf64c +#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR_V8 0xf650 +#define S5P_FIMV_D_DECODED_FRAME_TYPE_V8 0xf654 +#define S5P_FIMV_D_DECODED_NAL_SIZE_V8 0xf664 + +/* Returned value register for specific setting */ +#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8 0xf674 +#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8 0xf678 +#define S5P_FIMV_D_MVC_VIEW_ID_V8 0xf6d8 + +/* SEI related information */ +#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8 0xf6dc + +/* Encoder Registers */ +#define S5P_FIMV_E_FIXED_PICTURE_QP_V8 0xf794 +#define S5P_FIMV_E_RC_CONFIG_V8 0xf798 +#define S5P_FIMV_E_RC_QP_BOUND_V8 0xf79c +#define S5P_FIMV_E_RC_RPARAM_V8 0xf7a4 +#define S5P_FIMV_E_MB_RC_CONFIG_V8 0xf7a8 +#define S5P_FIMV_E_PADDING_CTRL_V8 0xf7ac +#define S5P_FIMV_E_MV_HOR_RANGE_V8 0xf7b4 +#define S5P_FIMV_E_MV_VER_RANGE_V8 0xf7b8 + +#define S5P_FIMV_E_VBV_BUFFER_SIZE_V8 0xf78c +#define S5P_FIMV_E_VBV_INIT_DELAY_V8 0xf790 + +#define S5P_FIMV_E_ASPECT_RATIO_V8 0xfb4c +#define S5P_FIMV_E_EXTENDED_SAR_V8 0xfb50 +#define S5P_FIMV_E_H264_OPTIONS_V8 0xfb54 + +/* MFCv8 Context buffer sizes */ +#define MFC_CTX_BUF_SIZE_V8 (30 * SZ_1K) /* 30KB */ +#define MFC_H264_DEC_CTX_BUF_SIZE_V8 (2 * SZ_1M) /* 2MB */ +#define MFC_OTHER_DEC_CTX_BUF_SIZE_V8 (20 * SZ_1K) /* 20KB */ +#define MFC_H264_ENC_CTX_BUF_SIZE_V8 (100 * SZ_1K) /* 100KB */ +#define MFC_OTHER_ENC_CTX_BUF_SIZE_V8 (10 * SZ_1K) /* 10KB */ + +/* Buffer size defines */ +#define S5P_FIMV_TMV_BUFFER_SIZE_V8(w, h) (((w) + 1) * ((h) + 1) * 8) + +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(w, h) (((w) * 704) + 2176) +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(w, h) \ + (((w) * 576 + (h) * 128) + 4128) + +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(w, h) \ + (((w) * 592) + 2336) +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(w, h) \ + (((w) * 576) + 10512 + \ + ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4)) +#define S5P_FIMV_ME_BUFFER_SIZE_V8(imw, imh, mbw, mbh) \ + ((DIV_ROUND_UP((mbw * 16), 64) * DIV_ROUND_UP((mbh * 16), 64) * 256) \ + + (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) + +/* BUffer alignment defines */ +#define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64 + +/* MFCv8 variant defines */ +#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */ +#define MAX_CPB_SIZE_V8 (3 * SZ_1M) /* 3MB */ +#define MFC_VERSION_V8 0x80 +#define MFC_NUM_PORTS_V8 1 + +#endif /*_REGS_MFC_V8_H*/ diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h index 9319e93599a..6ccc3f8c122 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h @@ -382,7 +382,7 @@ #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16 #define S5P_FIMV_R2H_CMD_ERR_RET 32 -/* Dummy definition for MFCv6 compatibilty */ +/* Dummy definition for MFCv6 compatibility */ #define S5P_FIMV_CODEC_H264_MVC_DEC -1 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1 #define S5P_FIMV_MFC_RESET -1 diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 681bc6ba149..41723180d10 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -21,6 +21,7 @@ #include <linux/videodev2.h> #include <media/v4l2-event.h> #include <linux/workqueue.h> +#include <linux/of.h> #include <media/videobuf2-core.h> #include "s5p_mfc_common.h" #include "s5p_mfc_ctrl.h" @@ -176,21 +177,6 @@ unlock: mutex_unlock(&dev->mfc_mutex); } -static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - - if (!vdev) { - mfc_err("failed to get video_device"); - return MFCNODE_INVALID; - } - if (vdev->index == 0) - return MFCNODE_DECODER; - else if (vdev->index == 1) - return MFCNODE_ENCODER; - return MFCNODE_INVALID; -} - static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev) { mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT); @@ -238,16 +224,19 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); /* Copy timestamp / timecode from decoded src to dst and set - appropraite flags */ + appropriate flags */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) { - memcpy(&dst_buf->b->v4l2_buf.timecode, - &src_buf->b->v4l2_buf.timecode, - sizeof(struct v4l2_timecode)); - memcpy(&dst_buf->b->v4l2_buf.timestamp, - &src_buf->b->v4l2_buf.timestamp, - sizeof(struct timeval)); + dst_buf->b->v4l2_buf.timecode = + src_buf->b->v4l2_buf.timecode; + dst_buf->b->v4l2_buf.timestamp = + src_buf->b->v4l2_buf.timestamp; + dst_buf->b->v4l2_buf.flags &= + ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_buf->b->v4l2_buf.flags |= + src_buf->b->v4l2_buf.flags + & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; switch (frame_type) { case S5P_FIMV_DECODE_FRAME_I_FRAME: dst_buf->b->v4l2_buf.flags |= @@ -273,10 +262,9 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) struct s5p_mfc_buf *dst_buf; size_t dspl_y_addr; unsigned int frame_type; - unsigned int index; dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); - frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); + frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_disp_frame_type, ctx); /* If frame is same as previous then skip and do not dequeue */ if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { @@ -310,7 +298,6 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) vb2_buffer_done(dst_buf->b, err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); - index = dst_buf->b->v4l2_buf.index; break; } } @@ -322,14 +309,15 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev = ctx->dev; unsigned int dst_frame_status; + unsigned int dec_frame_status; struct s5p_mfc_buf *src_buf; unsigned long flags; unsigned int res_change; - unsigned int index; - dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; + dec_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dec_status, dev) + & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK) >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT; @@ -354,16 +342,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, /* All frames remaining in the buffer have been extracted */ if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) { if (ctx->state == MFCINST_RES_CHANGE_FLUSH) { + static const struct v4l2_event ev_src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = + V4L2_EVENT_SRC_CH_RESOLUTION, + }; + s5p_mfc_handle_frame_all_extracted(ctx); ctx->state = MFCINST_RES_CHANGE_END; + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); + goto leave_handle_frame; } else { s5p_mfc_handle_frame_all_extracted(ctx); } } - if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY || - dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY) + if (dec_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) s5p_mfc_handle_frame_copy_time(ctx); /* A frame has been decoded and is in the buffer */ @@ -381,15 +376,17 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, dev); if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && + ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC && ctx->consumed_stream + STUFF_BYTE < src_buf->b->v4l2_planes[0].bytesused) { /* Run MFC again on the same buffer */ mfc_debug(2, "Running again the same buffer\n"); ctx->after_packed_pb = 1; } else { - index = src_buf->b->v4l2_buf.index; mfc_debug(2, "MFC needs next buffer\n"); ctx->consumed_stream = 0; + if (src_buf->flags & MFC_BUF_FLAG_EOS) + ctx->state = MFCINST_FINISHING; list_del(&src_buf->list); ctx->src_queue_cnt--; if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0) @@ -401,14 +398,18 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, leave_handle_frame: spin_unlock_irqrestore(&dev->irqlock, flags); if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) - || ctx->dst_queue_cnt < ctx->dpb_count) + || ctx->dst_queue_cnt < ctx->pb_count) clear_work_bit(ctx); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); if (test_and_clear_bit(0, &dev->hw_lock) == 0) BUG(); s5p_mfc_clock_off(); - s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + /* if suspending, wake up device and do not try_run again*/ + if (test_bit(0, &dev->enter_suspend)) + wake_up_dev(dev, reason, err); + else + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } /* Error handling for interrupt */ @@ -428,7 +429,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, case MFCINST_FINISHING: case MFCINST_FINISHED: case MFCINST_RUNNING: - /* It is higly probable that an error occured + /* It is highly probable that an error occurred * while decoding a frame */ clear_work_bit(ctx); ctx->state = MFCINST_ERROR; @@ -477,7 +478,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); - ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, + ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, dev); ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count, dev); @@ -566,7 +567,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *mb_entry; - mfc_debug(2, "Stream completed"); + mfc_debug(2, "Stream completed\n"); s5p_mfc_clear_int_flags(dev); ctx->int_type = reason; @@ -586,8 +587,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, clear_work_bit(ctx); - if (test_and_clear_bit(0, &dev->hw_lock) == 0) - WARN_ON(1); + WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); wake_up(&ctx->queue); @@ -612,7 +612,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err); switch (reason) { case S5P_MFC_R2H_CMD_ERR_RET: - /* An error has occured */ + /* An error has occurred */ if (ctx->state == MFCINST_RUNNING && s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >= dev->warn_start) @@ -652,6 +652,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET: clear_work_bit(ctx); + ctx->inst_no = MFC_NO_INSTANCE_SET; ctx->state = MFCINST_FREE; wake_up(&ctx->queue); goto irq_cleanup_hw; @@ -676,6 +677,12 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) s5p_mfc_handle_stream_complete(ctx, reason, err); break; + case S5P_MFC_R2H_CMD_DPB_FLUSH_RET: + clear_work_bit(ctx); + ctx->state = MFCINST_RUNNING; + wake_up(&ctx->queue); + goto irq_cleanup_hw; + default: mfc_debug(2, "Unknown int reason\n"); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); @@ -700,6 +707,7 @@ irq_cleanup_hw: /* Open an MFC node */ static int s5p_mfc_open(struct file *file) { + struct video_device *vdev = video_devdata(file); struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = NULL; struct vb2_queue *q; @@ -737,7 +745,7 @@ static int s5p_mfc_open(struct file *file) /* Mark context as idle */ clear_work_bit_irqsave(ctx); dev->ctx[ctx->num] = ctx; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { ctx->type = MFCINST_DECODER; ctx->c_ops = get_dec_codec_ops(); s5p_mfc_dec_init(ctx); @@ -747,7 +755,7 @@ static int s5p_mfc_open(struct file *file) mfc_err("Failed to setup mfc controls\n"); goto err_ctrls_setup; } - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { ctx->type = MFCINST_ENCODER; ctx->c_ops = get_enc_codec_ops(); /* only for encoder */ @@ -765,7 +773,7 @@ static int s5p_mfc_open(struct file *file) goto err_bad_node; } ctx->fh.ctrl_handler = &ctx->ctrl_handler; - ctx->inst_no = -1; + ctx->inst_no = MFC_NO_INSTANCE_SET; /* Load firmware if this is the first instance */ if (dev->num_inst == 1) { dev->watchdog_timer.expires = jiffies + @@ -777,23 +785,25 @@ static int s5p_mfc_open(struct file *file) goto err_pwr_enable; } s5p_mfc_clock_on(); - ret = s5p_mfc_alloc_and_load_firmware(dev); - if (ret) - goto err_alloc_fw; + ret = s5p_mfc_load_firmware(dev); + if (ret) { + s5p_mfc_clock_off(); + goto err_load_fw; + } /* Init the FW */ ret = s5p_mfc_init_hw(dev); + s5p_mfc_clock_off(); if (ret) goto err_init_hw; - s5p_mfc_clock_off(); } /* Init videobuf2 queue for CAPTURE */ q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; q->drv_priv = &ctx->fh; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { @@ -801,6 +811,7 @@ static int s5p_mfc_open(struct file *file) goto err_queue_init; } q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ret = vb2_queue_init(q); if (ret) { mfc_err("Failed to initialize videobuf2 queue(capture)\n"); @@ -811,10 +822,10 @@ static int s5p_mfc_open(struct file *file) q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; q->io_modes = VB2_MMAP; q->drv_priv = &ctx->fh; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { @@ -822,6 +833,7 @@ static int s5p_mfc_open(struct file *file) goto err_queue_init; } q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ret = vb2_queue_init(q); if (ret) { mfc_err("Failed to initialize videobuf2 queue(output)\n"); @@ -831,23 +843,22 @@ static int s5p_mfc_open(struct file *file) mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; - /* Deinit when failure occured */ + /* Deinit when failure occurred */ err_queue_init: + if (dev->num_inst == 1) + s5p_mfc_deinit_hw(dev); err_init_hw: - s5p_mfc_release_firmware(dev); -err_alloc_fw: - dev->ctx[ctx->num] = NULL; - del_timer_sync(&dev->watchdog_timer); - s5p_mfc_clock_off(); +err_load_fw: err_pwr_enable: if (dev->num_inst == 1) { if (s5p_mfc_power_off() < 0) mfc_err("power off failed\n"); - s5p_mfc_release_firmware(dev); + del_timer_sync(&dev->watchdog_timer); } err_ctrls_setup: s5p_mfc_dec_ctrls_delete(ctx); err_bad_node: + dev->ctx[ctx->num] = NULL; err_no_ctx: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); @@ -872,40 +883,19 @@ static int s5p_mfc_release(struct file *file) vb2_queue_release(&ctx->vq_dst); /* Mark context as idle */ clear_work_bit_irqsave(ctx); - /* If instance was initialised then - * return instance and free reosurces */ - if (ctx->inst_no != MFC_NO_INSTANCE_SET) { + /* If instance was initialised and not yet freed, + * return instance and free resources */ + if (ctx->state != MFCINST_FREE && ctx->state != MFCINST_INIT) { mfc_debug(2, "Has to free instance\n"); - ctx->state = MFCINST_RETURN_INST; - set_work_bit_irqsave(ctx); - s5p_mfc_clean_ctx_int_flags(ctx); - s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - /* Wait until instance is returned or timeout occured */ - if (s5p_mfc_wait_for_done_ctx - (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { - s5p_mfc_clock_off(); - mfc_err("Err returning instance\n"); - } - mfc_debug(2, "After free instance\n"); - /* Free resources */ - s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); - s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); - if (ctx->type == MFCINST_DECODER) - s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, - ctx); - - ctx->inst_no = MFC_NO_INSTANCE_SET; + s5p_mfc_close_mfc_inst(dev, ctx); } /* hardware locking scheme */ if (dev->curr_ctx == ctx->num) clear_bit(0, &dev->hw_lock); dev->num_inst--; if (dev->num_inst == 0) { - mfc_debug(2, "Last instance - release firmware\n"); - /* reset <-> F/W release */ - s5p_mfc_reset(dev); + mfc_debug(2, "Last instance\n"); s5p_mfc_deinit_hw(dev); - s5p_mfc_release_firmware(dev); del_timer_sync(&dev->watchdog_timer); if (s5p_mfc_power_off() < 0) mfc_err("Power off failed\n"); @@ -1013,6 +1003,48 @@ static int match_child(struct device *dev, void *data) return !strcmp(dev_name(dev), (char *)data); } +static void *mfc_get_drv_data(struct platform_device *pdev); + +static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev) +{ + unsigned int mem_info[2] = { }; + + dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev, + sizeof(struct device), GFP_KERNEL); + if (!dev->mem_dev_l) { + mfc_err("Not enough memory\n"); + return -ENOMEM; + } + device_initialize(dev->mem_dev_l); + of_property_read_u32_array(dev->plat_dev->dev.of_node, + "samsung,mfc-l", mem_info, 2); + if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0], + mem_info[0], mem_info[1], + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { + mfc_err("Failed to declare coherent memory for\n" + "MFC device\n"); + return -ENOMEM; + } + + dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev, + sizeof(struct device), GFP_KERNEL); + if (!dev->mem_dev_r) { + mfc_err("Not enough memory\n"); + return -ENOMEM; + } + device_initialize(dev->mem_dev_r); + of_property_read_u32_array(dev->plat_dev->dev.of_node, + "samsung,mfc-r", mem_info, 2); + if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0], + mem_info[0], mem_info[1], + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { + pr_err("Failed to declare coherent memory for\n" + "MFC device\n"); + return -ENOMEM; + } + return 0; +} + /* MFC probe function */ static int s5p_mfc_probe(struct platform_device *pdev) { @@ -1036,8 +1068,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) return -ENODEV; } - dev->variant = (struct s5p_mfc_variant *) - platform_get_device_id(pdev)->driver_data; + dev->variant = mfc_get_drv_data(pdev); ret = s5p_mfc_init_pm(dev); if (ret < 0) { @@ -1047,11 +1078,9 @@ static int s5p_mfc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->regs_base = devm_request_and_ioremap(&pdev->dev, res); - if (dev->regs_base == NULL) { - dev_err(&pdev->dev, "Failed to obtain io memory\n"); - return -ENOENT; - } + dev->regs_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->regs_base)) + return PTR_ERR(dev->regs_base); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { @@ -1061,41 +1090,50 @@ static int s5p_mfc_probe(struct platform_device *pdev) } dev->irq = res->start; ret = devm_request_irq(&pdev->dev, dev->irq, s5p_mfc_irq, - IRQF_DISABLED, pdev->name, dev); + 0, pdev->name, dev); if (ret) { dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret); goto err_res; } - dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l", - match_child); - if (!dev->mem_dev_l) { - mfc_err("Mem child (L) device get failed\n"); - ret = -ENODEV; - goto err_res; - } - - dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r", - match_child); - if (!dev->mem_dev_r) { - mfc_err("Mem child (R) device get failed\n"); - ret = -ENODEV; - goto err_res; + if (pdev->dev.of_node) { + ret = s5p_mfc_alloc_memdevs(dev); + if (ret < 0) + goto err_res; + } else { + dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, + "s5p-mfc-l", match_child); + if (!dev->mem_dev_l) { + mfc_err("Mem child (L) device get failed\n"); + ret = -ENODEV; + goto err_res; + } + dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, + "s5p-mfc-r", match_child); + if (!dev->mem_dev_r) { + mfc_err("Mem child (R) device get failed\n"); + ret = -ENODEV; + goto err_res; + } } dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); - if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) { + if (IS_ERR(dev->alloc_ctx[0])) { ret = PTR_ERR(dev->alloc_ctx[0]); goto err_res; } dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); - if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) { + if (IS_ERR(dev->alloc_ctx[1])) { ret = PTR_ERR(dev->alloc_ctx[1]); goto err_mem_init_ctx_1; } mutex_init(&dev->mfc_mutex); + ret = s5p_mfc_alloc_firmware(dev); + if (ret) + goto err_alloc_fw; + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_v4l2_dev_reg; @@ -1108,9 +1146,9 @@ static int s5p_mfc_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_dec_alloc; } - vfd->fops = &s5p_mfc_fops, + vfd->fops = &s5p_mfc_fops; vfd->ioctl_ops = get_dec_v4l2_ioctl_ops(); - vfd->release = video_device_release, + vfd->release = video_device_release; vfd->lock = &dev->mfc_mutex; vfd->v4l2_dev = &dev->v4l2_dev; vfd->vfl_dir = VFL_DIR_M2M; @@ -1133,9 +1171,9 @@ static int s5p_mfc_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_enc_alloc; } - vfd->fops = &s5p_mfc_fops, + vfd->fops = &s5p_mfc_fops; vfd->ioctl_ops = get_enc_v4l2_ioctl_ops(); - vfd->release = video_device_release, + vfd->release = video_device_release; vfd->lock = &dev->mfc_mutex; vfd->v4l2_dev = &dev->v4l2_dev; vfd->vfl_dir = VFL_DIR_M2M; @@ -1163,6 +1201,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) /* Initialize HW ops and commands based on MFC version */ s5p_mfc_init_hw_ops(dev); s5p_mfc_init_hw_cmds(dev); + s5p_mfc_init_regs(dev); pr_debug("%s--\n", __func__); return 0; @@ -1177,6 +1216,8 @@ err_dec_reg: err_dec_alloc: v4l2_device_unregister(&dev->v4l2_dev); err_v4l2_dev_reg: + s5p_mfc_release_firmware(dev); +err_alloc_fw: vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); err_mem_init_ctx_1: vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); @@ -1202,8 +1243,13 @@ static int s5p_mfc_remove(struct platform_device *pdev) video_unregister_device(dev->vfd_enc); video_unregister_device(dev->vfd_dec); v4l2_device_unregister(&dev->v4l2_dev); + s5p_mfc_release_firmware(dev); vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); + if (pdev->dev.of_node) { + put_device(dev->mem_dev_l); + put_device(dev->mem_dev_r); + } s5p_mfc_final_pm(dev); return 0; @@ -1230,9 +1276,7 @@ static int s5p_mfc_suspend(struct device *dev) /* Try and lock the HW */ /* Wait on the interrupt waitqueue */ ret = wait_event_interruptible_timeout(m_dev->queue, - m_dev->int_cond || m_dev->ctx[m_dev->curr_ctx]->int_cond, - msecs_to_jiffies(MFC_INT_TIMEOUT)); - + m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT)); if (ret == 0) { mfc_err("Waiting for hardware to finish timed out\n"); return -EIO; @@ -1303,10 +1347,10 @@ struct s5p_mfc_buf_align mfc_buf_align_v5 = { static struct s5p_mfc_variant mfc_drvdata_v5 = { .version = MFC_VERSION, + .version_bit = MFC_V5_BIT, .port_num = MFC_NUM_PORTS, .buf_size = &buf_size_v5, .buf_align = &mfc_buf_align_v5, - .mclk_name = "sclk_mfc", .fw_name = "s5p-mfc.fw", }; @@ -1330,13 +1374,67 @@ struct s5p_mfc_buf_align mfc_buf_align_v6 = { static struct s5p_mfc_variant mfc_drvdata_v6 = { .version = MFC_VERSION_V6, + .version_bit = MFC_V6_BIT, .port_num = MFC_NUM_PORTS_V6, .buf_size = &buf_size_v6, .buf_align = &mfc_buf_align_v6, - .mclk_name = "aclk_333", .fw_name = "s5p-mfc-v6.fw", }; +struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = { + .dev_ctx = MFC_CTX_BUF_SIZE_V7, + .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V7, + .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V7, + .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V7, + .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V7, +}; + +struct s5p_mfc_buf_size buf_size_v7 = { + .fw = MAX_FW_SIZE_V7, + .cpb = MAX_CPB_SIZE_V7, + .priv = &mfc_buf_size_v7, +}; + +struct s5p_mfc_buf_align mfc_buf_align_v7 = { + .base = 0, +}; + +static struct s5p_mfc_variant mfc_drvdata_v7 = { + .version = MFC_VERSION_V7, + .version_bit = MFC_V7_BIT, + .port_num = MFC_NUM_PORTS_V7, + .buf_size = &buf_size_v7, + .buf_align = &mfc_buf_align_v7, + .fw_name = "s5p-mfc-v7.fw", +}; + +struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { + .dev_ctx = MFC_CTX_BUF_SIZE_V8, + .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V8, + .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V8, + .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V8, + .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V8, +}; + +struct s5p_mfc_buf_size buf_size_v8 = { + .fw = MAX_FW_SIZE_V8, + .cpb = MAX_CPB_SIZE_V8, + .priv = &mfc_buf_size_v8, +}; + +struct s5p_mfc_buf_align mfc_buf_align_v8 = { + .base = 0, +}; + +static struct s5p_mfc_variant mfc_drvdata_v8 = { + .version = MFC_VERSION_V8, + .version_bit = MFC_V8_BIT, + .port_num = MFC_NUM_PORTS_V8, + .buf_size = &buf_size_v8, + .buf_align = &mfc_buf_align_v8, + .fw_name = "s5p-mfc-v8.fw", +}; + static struct platform_device_id mfc_driver_ids[] = { { .name = "s5p-mfc", @@ -1347,11 +1445,52 @@ static struct platform_device_id mfc_driver_ids[] = { }, { .name = "s5p-mfc-v6", .driver_data = (unsigned long)&mfc_drvdata_v6, + }, { + .name = "s5p-mfc-v7", + .driver_data = (unsigned long)&mfc_drvdata_v7, + }, { + .name = "s5p-mfc-v8", + .driver_data = (unsigned long)&mfc_drvdata_v8, }, {}, }; MODULE_DEVICE_TABLE(platform, mfc_driver_ids); +static const struct of_device_id exynos_mfc_match[] = { + { + .compatible = "samsung,mfc-v5", + .data = &mfc_drvdata_v5, + }, { + .compatible = "samsung,mfc-v6", + .data = &mfc_drvdata_v6, + }, { + .compatible = "samsung,mfc-v7", + .data = &mfc_drvdata_v7, + }, { + .compatible = "samsung,mfc-v8", + .data = &mfc_drvdata_v8, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_mfc_match); + +static void *mfc_get_drv_data(struct platform_device *pdev) +{ + struct s5p_mfc_variant *driver_data = NULL; + + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(exynos_mfc_match, + pdev->dev.of_node); + if (match) + driver_data = (struct s5p_mfc_variant *)match->data; + } else { + driver_data = (struct s5p_mfc_variant *) + platform_get_device_id(pdev)->driver_data; + } + return driver_data; +} + static struct platform_driver s5p_mfc_driver = { .probe = s5p_mfc_probe, .remove = s5p_mfc_remove, @@ -1359,7 +1498,8 @@ static struct platform_driver s5p_mfc_driver = { .driver = { .name = S5P_MFC_NAME, .owner = THIS_MODULE, - .pm = &s5p_mfc_pm_ops + .pm = &s5p_mfc_pm_ops, + .of_match_table = exynos_mfc_match, }, }; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c index f0a41c95df8..242c033cf8b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c @@ -20,7 +20,7 @@ static struct s5p_mfc_hw_cmds *s5p_mfc_cmds; void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) { - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); else s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c index 138778083c6..9a6efd6c132 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c @@ -16,7 +16,7 @@ #include "s5p_mfc_debug.h" /* This function is used to send a command to the MFC */ -int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd, +static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd, struct s5p_mfc_cmd_args *args) { int cur_cmd; @@ -41,7 +41,7 @@ int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd, } /* Initialize the MFC */ -int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; @@ -52,7 +52,7 @@ int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) } /* Suspend the MFC hardware */ -int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; @@ -61,7 +61,7 @@ int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev) } /* Wake up the MFC hardware */ -int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; @@ -71,7 +71,7 @@ int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev) } -int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_cmd_args h2r_args; @@ -111,7 +111,7 @@ int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) break; default: h2r_args.arg[0] = S5P_FIMV_CODEC_NONE; - }; + } h2r_args.arg[1] = 0; /* no crc & no pixelcache */ h2r_args.arg[2] = ctx->ctx.ofs; h2r_args.arg[3] = ctx->ctx.size; @@ -124,7 +124,7 @@ int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) return ret; } -int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_cmd_args h2r_args; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c index 754bfbcb1c4..ec1a5947ed7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c @@ -17,7 +17,7 @@ #include "s5p_mfc_intr.h" #include "s5p_mfc_opr.h" -int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, +static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, struct s5p_mfc_cmd_args *args) { mfc_debug(2, "Issue the command: %d\n", cmd); @@ -32,7 +32,7 @@ int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, return 0; } -int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_sys_init_cmd_v6(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; @@ -44,7 +44,7 @@ int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) &h2r_args); } -int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; @@ -53,7 +53,7 @@ int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) &h2r_args); } -int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; @@ -63,7 +63,7 @@ int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) } /* Open a new instance and get its number */ -int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_cmd_args h2r_args; @@ -108,9 +108,12 @@ int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) case S5P_MFC_CODEC_H263_ENC: codec_type = S5P_FIMV_CODEC_H263_ENC_V6; break; + case S5P_MFC_CODEC_VP8_ENC: + codec_type = S5P_FIMV_CODEC_VP8_ENC_V7; + break; default: codec_type = S5P_FIMV_CODEC_NONE_V6; - }; + } mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6); mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6); mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); @@ -121,7 +124,7 @@ int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) } /* Close instance */ -int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_cmd_args h2r_args; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index f02e0497ca9..b04360cd34f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -23,7 +23,7 @@ #include <media/v4l2-ioctl.h> #include <media/videobuf2-core.h> #include "regs-mfc.h" -#include "regs-mfc-v6.h" +#include "regs-mfc-v8.h" /* Definitions related to MFC memory */ @@ -64,7 +64,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) #define MFC_ENC_CAP_PLANE_COUNT 1 #define MFC_ENC_OUT_PLANE_COUNT 2 #define STUFF_BYTE 4 -#define MFC_MAX_CTRLS 70 +#define MFC_MAX_CTRLS 77 #define S5P_MFC_CODEC_NONE -1 #define S5P_MFC_CODEC_H264_DEC 0 @@ -80,6 +80,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) #define S5P_MFC_CODEC_H264_MVC_ENC 21 #define S5P_MFC_CODEC_MPEG4_ENC 22 #define S5P_MFC_CODEC_H263_ENC 23 +#define S5P_MFC_CODEC_VP8_ENC 24 #define S5P_MFC_R2H_CMD_EMPTY 0 #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 @@ -113,15 +114,6 @@ enum s5p_mfc_fmt_type { }; /** - * enum s5p_mfc_node_type - The type of an MFC device node. - */ -enum s5p_mfc_node_type { - MFCNODE_INVALID = -1, - MFCNODE_DECODER = 0, - MFCNODE_ENCODER = 1, -}; - -/** * enum s5p_mfc_inst_type - The type of an MFC instance. */ enum s5p_mfc_inst_type { @@ -138,6 +130,7 @@ enum s5p_mfc_inst_state { MFCINST_INIT = 100, MFCINST_GOT_INST, MFCINST_HEAD_PARSED, + MFCINST_HEAD_PRODUCED, MFCINST_BUFS_SET, MFCINST_RUNNING, MFCINST_FINISHING, @@ -145,6 +138,7 @@ enum s5p_mfc_inst_state { MFCINST_RETURN_INST, MFCINST_ERROR, MFCINST_ABORT, + MFCINST_FLUSH, MFCINST_RES_CHANGE_INIT, MFCINST_RES_CHANGE_FLUSH, MFCINST_RES_CHANGE_END, @@ -228,9 +222,9 @@ struct s5p_mfc_buf_align { struct s5p_mfc_variant { unsigned int version; unsigned int port_num; + u32 version_bit; struct s5p_mfc_buf_size *buf_size; struct s5p_mfc_buf_align *buf_align; - char *mclk_name; char *fw_name; }; @@ -277,8 +271,9 @@ struct s5p_mfc_priv_buf { * @int_err: error number for last interrupt * @queue: waitqueue for waiting for completion of device commands * @fw_size: size of firmware - * @bank1: address of the beggining of bank 1 memory - * @bank2: address of the beggining of bank 2 memory + * @fw_virt_addr: virtual firmware address + * @bank1: address of the beginning of bank 1 memory + * @bank2: address of the beginning of bank 2 memory * @hw_lock: used for hardware locking * @ctx: array of driver contexts * @curr_ctx: number of the currently running context @@ -317,8 +312,9 @@ struct s5p_mfc_dev { unsigned int int_err; wait_queue_head_t queue; size_t fw_size; - size_t bank1; - size_t bank2; + void *fw_virt_addr; + dma_addr_t bank1; + dma_addr_t bank2; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; int curr_ctx; @@ -334,6 +330,7 @@ struct s5p_mfc_dev { int warn_start; struct s5p_mfc_hw_ops *mfc_ops; struct s5p_mfc_hw_cmds *mfc_cmds; + const struct s5p_mfc_regs *mfc_regs; }; /** @@ -405,11 +402,33 @@ struct s5p_mfc_mpeg4_enc_params { }; /** + * struct s5p_mfc_vp8_enc_params - encoding parameters for vp8 + */ +struct s5p_mfc_vp8_enc_params { + u8 imd_4x4; + enum v4l2_vp8_num_partitions num_partitions; + enum v4l2_vp8_num_ref_frames num_ref; + u8 filter_level; + u8 filter_sharpness; + u32 golden_frame_ref_period; + enum v4l2_vp8_golden_frame_sel golden_frame_sel; + u8 hier_layer; + u8 hier_layer_qp[3]; + u8 rc_min_qp; + u8 rc_max_qp; + u8 rc_frame_qp; + u8 rc_p_frame_qp; + u8 profile; +}; + +/** * struct s5p_mfc_enc_params - general encoding parameters */ struct s5p_mfc_enc_params { u16 width; u16 height; + u32 mv_h_range; + u32 mv_v_range; u16 gop_size; enum v4l2_mpeg_video_multi_slice_mode slice_mode; @@ -435,9 +454,10 @@ struct s5p_mfc_enc_params { u32 rc_framerate_num; u32 rc_framerate_denom; - union { + struct { struct s5p_mfc_h264_enc_params h264; struct s5p_mfc_mpeg4_enc_params mpeg4; + struct s5p_mfc_vp8_enc_params vp8; } codec; }; @@ -493,15 +513,9 @@ struct s5p_mfc_codec_ops { * flushed * @head_processed: flag mentioning whether the header data is processed * completely or not - * @bank1_buf: handle to memory allocated for temporary buffers from + * @bank1: handle to memory allocated for temporary buffers from * memory bank 1 - * @bank1_phys: address of the temporary buffers from memory bank 1 - * @bank1_size: size of the memory allocated for temporary buffers from - * memory bank 1 - * @bank2_buf: handle to memory allocated for temporary buffers from - * memory bank 2 - * @bank2_phys: address of the temporary buffers from memory bank 2 - * @bank2_size: size of the memory allocated for temporary buffers from + * @bank2: handle to memory allocated for temporary buffers from * memory bank 2 * @capture_state: state of the capture buffers queue * @output_state: state of the output buffers queue @@ -581,14 +595,8 @@ struct s5p_mfc_ctx { unsigned int dpb_flush_flag; unsigned int head_processed; - /* Buffers */ - void *bank1_buf; - size_t bank1_phys; - size_t bank1_size; - - void *bank2_buf; - size_t bank2_phys; - size_t bank2_size; + struct s5p_mfc_priv_buf bank1; + struct s5p_mfc_priv_buf bank2; enum s5p_mfc_queue_state capture_state; enum s5p_mfc_queue_state output_state; @@ -611,7 +619,7 @@ struct s5p_mfc_ctx { int after_packed_pb; int sei_fp_parse; - int dpb_count; + int pb_count; int total_dpb_count; int mv_count; /* Buffers */ @@ -656,6 +664,7 @@ struct s5p_mfc_fmt { u32 codec_mode; enum s5p_mfc_fmt_type type; u32 num_planes; + u32 versions; }; /** @@ -692,6 +701,14 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); #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) +#define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0) +#define IS_MFCV7_PLUS(dev) (dev->variant->version >= 0x70 ? 1 : 0) +#define IS_MFCV8(dev) (dev->variant->version >= 0x80 ? 1 : 0) + +#define MFC_V5_BIT BIT(0) +#define MFC_V6_BIT BIT(1) +#define MFC_V7_BIT BIT(2) +#define MFC_V8_BIT BIT(3) + #endif /* S5P_MFC_COMMON_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 585b7b0ed8e..6c3f8f74390 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -22,16 +22,62 @@ #include "s5p_mfc_opr.h" #include "s5p_mfc_pm.h" -static void *s5p_mfc_bitproc_buf; -static size_t s5p_mfc_bitproc_phys; -static unsigned char *s5p_mfc_bitproc_virt; +/* Allocate memory for firmware */ +int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) +{ + void *bank2_virt; + dma_addr_t bank2_dma_addr; + + dev->fw_size = dev->variant->buf_size->fw; + + if (dev->fw_virt_addr) { + mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); + return -ENOMEM; + } + + dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, + &dev->bank1, GFP_KERNEL); -/* Allocate and load firmware */ -int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) + if (IS_ERR_OR_NULL(dev->fw_virt_addr)) { + dev->fw_virt_addr = NULL; + mfc_err("Allocating bitprocessor buffer failed\n"); + return -ENOMEM; + } + + if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { + bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, + &bank2_dma_addr, GFP_KERNEL); + + if (IS_ERR(dev->fw_virt_addr)) { + mfc_err("Allocating bank2 base failed\n"); + dma_free_coherent(dev->mem_dev_l, dev->fw_size, + dev->fw_virt_addr, dev->bank1); + dev->fw_virt_addr = NULL; + return -ENOMEM; + } + + /* Valid buffers passed to MFC encoder with LAST_FRAME command + * should not have address of bank2 - MFC will treat it as a null frame. + * To avoid such situation we set bank2 address below the pool address. + */ + dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER); + + dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, + bank2_virt, bank2_dma_addr); + + } else { + /* In this case bank2 can point to the same address as bank1. + * Firmware will always occupy the beginning of this area so it is + * impossible having a video frame buffer with zero address. */ + dev->bank2 = dev->bank1; + } + return 0; +} + +/* Load firmware */ +int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) { struct firmware *fw_blob; - size_t bank2_base_phys; - void *b_base; int err; /* Firmare has to be present as a separate file or compiled @@ -44,77 +90,17 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); return -EINVAL; } - dev->fw_size = dev->variant->buf_size->fw; if (fw_blob->size > dev->fw_size) { mfc_err("MFC firmware is too big to be loaded\n"); release_firmware(fw_blob); return -ENOMEM; } - if (s5p_mfc_bitproc_buf) { - mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); - release_firmware(fw_blob); - return -ENOMEM; - } - s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size); - if (IS_ERR(s5p_mfc_bitproc_buf)) { - s5p_mfc_bitproc_buf = NULL; - mfc_err("Allocating bitprocessor buffer failed\n"); - release_firmware(fw_blob); - return -ENOMEM; - } - s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie( - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf); - if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) { - mfc_err("The base memory for bank 1 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; - } - s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf); - if (!s5p_mfc_bitproc_virt) { - mfc_err("Bitprocessor memory remap failed\n"); - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); - s5p_mfc_bitproc_phys = 0; - s5p_mfc_bitproc_buf = NULL; + if (!dev->fw_virt_addr) { + mfc_err("MFC firmware is not allocated\n"); release_firmware(fw_blob); - return -EIO; - } - dev->bank1 = s5p_mfc_bitproc_phys; - if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { - b_base = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], - 1 << MFC_BASE_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; - } - /* Valid buffers passed to MFC encoder with LAST_FRAME command - * should not have address of bank2 - MFC will treat it as a null frame. - * To avoid such situation we set bank2 address below the pool address. - */ - dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); - } else { - dev->bank2 = dev->bank1; + return -EINVAL; } - memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); + memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); mfc_debug_leave(); @@ -142,12 +128,12 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev) release_firmware(fw_blob); return -ENOMEM; } - if (s5p_mfc_bitproc_buf == NULL || s5p_mfc_bitproc_phys == 0) { - mfc_err("MFC firmware is not allocated or was not mapped correctly\n"); + if (!dev->fw_virt_addr) { + mfc_err("MFC firmware is not allocated\n"); release_firmware(fw_blob); return -EINVAL; } - memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); + memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); mfc_debug_leave(); @@ -159,12 +145,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) { /* Before calling this function one has to make sure * that MFC is no longer processing */ - if (!s5p_mfc_bitproc_buf) + if (!dev->fw_virt_addr) return -EINVAL; - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); - s5p_mfc_bitproc_virt = NULL; - s5p_mfc_bitproc_phys = 0; - s5p_mfc_bitproc_buf = NULL; + dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr, + dev->bank1); + dev->fw_virt_addr = NULL; return 0; } @@ -177,7 +162,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) mfc_debug_enter(); - if (IS_MFCV6(dev)) { + if (IS_MFCV6_PLUS(dev)) { /* Reset IP */ /* except RISC, reset */ mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); @@ -226,7 +211,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) { - if (IS_MFCV6(dev)) { + if (IS_MFCV6_PLUS(dev)) { mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); mfc_debug(2, "Base Address : %08x\n", dev->bank1); } else { @@ -239,7 +224,7 @@ static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) { - if (IS_MFCV6(dev)) { + if (IS_MFCV6_PLUS(dev)) { /* Zero initialization should be done before RESET. * Nothing to do here. */ } else { @@ -257,8 +242,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) int ret; mfc_debug_enter(); - if (!s5p_mfc_bitproc_buf) + if (!dev->fw_virt_addr) { + mfc_err("Firmware memory is not allocated.\n"); return -EINVAL; + } /* 0. MFC reset */ mfc_debug(2, "MFC reset..\n"); @@ -275,7 +262,7 @@ 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); - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); else mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); @@ -312,7 +299,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) s5p_mfc_clock_off(); return -EIO; } - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); else ver = mfc_read(dev, S5P_FIMV_FW_VERSION); @@ -391,7 +378,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) return ret; } /* 4. Release reset signal to the RISC */ - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); else mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); @@ -413,3 +400,65 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) return 0; } +int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) +{ + int ret = 0; + + ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); + if (ret) { + mfc_err("Failed allocating instance buffer\n"); + goto err; + } + + if (ctx->type == MFCINST_DECODER) { + ret = s5p_mfc_hw_call(dev->mfc_ops, + alloc_dec_temp_buffers, ctx); + if (ret) { + mfc_err("Failed allocating temporary buffers\n"); + goto err_free_inst_buf; + } + } + + set_work_bit_irqsave(ctx); + s5p_mfc_clean_ctx_int_flags(ctx); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + if (s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { + /* Error or timeout */ + mfc_err("Error getting instance from hardware\n"); + ret = -EIO; + goto err_free_desc_buf; + } + + mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); + return ret; + +err_free_desc_buf: + if (ctx->type == MFCINST_DECODER) + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); +err_free_inst_buf: + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); +err: + return ret; +} + +void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) +{ + ctx->state = MFCINST_RETURN_INST; + set_work_bit_irqsave(ctx); + s5p_mfc_clean_ctx_int_flags(ctx); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + /* Wait until instance is returned or timeout occurred */ + if (s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) + mfc_err("Err returning instance\n"); + + /* Free resources */ + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); + if (ctx->type == MFCINST_DECODER) + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); + + ctx->inst_no = MFC_NO_INSTANCE_SET; + ctx->state = MFCINST_FREE; +} diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index 90aa9b9886d..8e5df041edf 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h @@ -16,7 +16,8 @@ #include "s5p_mfc_common.h" int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); -int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev); +int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev); +int s5p_mfc_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); @@ -27,4 +28,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev); int s5p_mfc_reset(struct s5p_mfc_dev *dev); +int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx); +void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx); + #endif /* S5P_MFC_CTRL_H */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h index bd5cd4ae993..8e608f5aa0d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h @@ -30,8 +30,8 @@ extern int debug; #define mfc_debug(level, fmt, args...) #endif -#define mfc_debug_enter() mfc_debug(5, "enter") -#define mfc_debug_leave() mfc_debug(5, "leave") +#define mfc_debug_enter() mfc_debug(5, "enter\n") +#define mfc_debug_leave() mfc_debug(5, "leave\n") #define mfc_err(fmt, args...) \ do { \ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6dad9a74f61..4d93835dec9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -22,17 +22,16 @@ #include <linux/videodev2.h> #include <linux/workqueue.h> #include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> #include <media/videobuf2-core.h> #include "s5p_mfc_common.h" +#include "s5p_mfc_ctrl.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" -#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264 -#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16 - static struct s5p_mfc_fmt formats[] = { { .name = "4:2:0 2 Planes 16x16 Tiles", @@ -40,6 +39,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V6_BIT | MFC_V7_BIT, }, { .name = "4:2:0 2 Planes 64x32 Tiles", @@ -47,6 +47,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V5_BIT, }, { .name = "4:2:0 2 Planes Y/CbCr", @@ -54,6 +55,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, }, { .name = "4:2:0 2 Planes Y/CrCb", @@ -61,6 +63,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, }, { .name = "H264 Encoded Stream", @@ -68,6 +71,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_H264_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "H264/MVC Encoded Stream", @@ -75,6 +80,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, }, { .name = "H263 Encoded Stream", @@ -82,6 +88,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_H263_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "MPEG1 Encoded Stream", @@ -89,6 +97,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "MPEG2 Encoded Stream", @@ -96,6 +106,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "MPEG4 Encoded Stream", @@ -103,6 +115,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "XviD Encoded Stream", @@ -110,6 +124,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "VC1 Encoded Stream", @@ -117,6 +133,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_VC1_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "VC1 RCV Encoded Stream", @@ -124,6 +142,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "VP8 Encoded Stream", @@ -131,6 +151,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_VP8_DEC, .type = MFC_FMT_DEC, .num_planes = 1, + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, }, }; @@ -209,11 +230,11 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) /* Context is to decode a frame */ if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_RUNNING && - ctx->dst_queue_cnt >= ctx->dpb_count) + ctx->dst_queue_cnt >= ctx->pb_count) return 1; /* Context is to return last frame */ if (ctx->state == MFCINST_FINISHING && - ctx->dst_queue_cnt >= ctx->dpb_count) + ctx->dst_queue_cnt >= ctx->pb_count) return 1; /* Context is to set buffers */ if (ctx->src_queue_cnt >= 1 && @@ -223,7 +244,7 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) /* Resolution change */ if ((ctx->state == MFCINST_RES_CHANGE_INIT || ctx->state == MFCINST_RES_CHANGE_FLUSH) && - ctx->dst_queue_cnt >= ctx->dpb_count) + ctx->dst_queue_cnt >= ctx->pb_count) return 1; if (ctx->state == MFCINST_RES_CHANGE_END && ctx->src_queue_cnt >= 1) @@ -261,8 +282,10 @@ static int vidioc_querycap(struct file *file, void *priv, } /* Enumerate format */ -static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, + bool mplane, bool out) { + struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_fmt *fmt; int i, j = 0; @@ -275,6 +298,8 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) continue; else if (!out && formats[i].type != MFC_FMT_RAW) continue; + else if ((dev->variant->version_bit & formats[i].versions) == 0) + continue; if (j == f->index) break; @@ -291,25 +316,25 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, false, false); + return vidioc_enum_fmt(file, f, false, false); } static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, true, false); + return vidioc_enum_fmt(file, f, true, false); } -static int vidioc_enum_fmt_vid_out(struct file *file, void *prov, +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, false, true); + return vidioc_enum_fmt(file, f, false, true); } -static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, +static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, true, true); + return vidioc_enum_fmt(file, f, true, true); } /* Get format */ @@ -343,7 +368,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) pix_mp->num_planes = 2; /* Set pixelformat to the format in which MFC outputs the decoded frame */ - pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT; + pix_mp->pixelformat = ctx->dst_fmt->fourcc; pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; @@ -381,8 +406,12 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) 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"); + if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) { + mfc_err("Unknown codec\n"); + return -EINVAL; + } + if ((dev->variant->version_bit & fmt->versions) == 0) { + mfc_err("Unsupported format by this MFC version.\n"); return -EINVAL; } } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -391,12 +420,8 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) 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 (!IS_MFCV6(dev) && - (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { - mfc_err("Not supported format.\n"); + if ((dev->variant->version_bit & fmt->versions) == 0) { + mfc_err("Unsupported format by this MFC version.\n"); return -EINVAL; } } @@ -410,7 +435,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); @@ -424,157 +448,162 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) 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_MFC_CODEC_NONE) { - mfc_err("Unknown codec\n"); - ret = -EINVAL; + /* dst_fmt is validated by call to vidioc_try_fmt */ + ctx->dst_fmt = find_format(f, MFC_FMT_RAW); + ret = 0; goto out; - } - if (fmt->type != MFC_FMT_DEC) { - mfc_err("Wrong format selected, you should choose " - "format for decoding\n"); + } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* src_fmt is validated by call to vidioc_try_fmt */ + ctx->src_fmt = find_format(f, MFC_FMT_DEC); + ctx->codec_mode = ctx->src_fmt->codec_mode; + mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); + pix_mp->height = 0; + pix_mp->width = 0; + if (pix_mp->plane_fmt[0].sizeimage) + ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; + else + pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = + DEF_CPB_SIZE; + pix_mp->plane_fmt[0].bytesperline = 0; + ctx->state = MFCINST_INIT; + ret = 0; + goto out; + } else { + mfc_err("Wrong type error for S_FMT : %d", f->type); 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); - pix_mp->height = 0; - pix_mp->width = 0; - if (pix_mp->plane_fmt[0].sizeimage) - ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; - else - pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = - DEF_CPB_SIZE; - pix_mp->plane_fmt[0].bytesperline = 0; - ctx->state = MFCINST_INIT; + out: mfc_debug_leave(); return ret; } -/* Reqeust buffers */ -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) +static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, + struct v4l2_requestbuffers *reqbufs) { - struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - if (reqbufs->memory != V4L2_MEMORY_MMAP) { - mfc_err("Only V4L2_MEMORY_MAP is supported\n"); - return -EINVAL; - } - if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - /* Can only request buffers after an instance has been opened.*/ - if (ctx->state == MFCINST_INIT) { - ctx->src_bufs_cnt = 0; - if (reqbufs->count == 0) { - mfc_debug(2, "Freeing buffers\n"); - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_src, reqbufs); - s5p_mfc_clock_off(); - return ret; - } - /* Decoding */ - if (ctx->output_state != QUEUE_FREE) { - mfc_err("Bufs have already been requested\n"); - return -EINVAL; - } - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_src, reqbufs); - s5p_mfc_clock_off(); - if (ret) { - mfc_err("vb2_reqbufs on output failed\n"); - return ret; - } - mfc_debug(2, "vb2_reqbufs: %d\n", ret); - ctx->output_state = QUEUE_BUFS_REQUESTED; - } - } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - ctx->dst_bufs_cnt = 0; - if (reqbufs->count == 0) { - mfc_debug(2, "Freeing buffers\n"); - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); - s5p_mfc_clock_off(); - return ret; - } - if (ctx->capture_state != QUEUE_FREE) { - mfc_err("Bufs have already been requested\n"); - return -EINVAL; + s5p_mfc_clock_on(); + + if (reqbufs->count == 0) { + mfc_debug(2, "Freeing buffers\n"); + ret = vb2_reqbufs(&ctx->vq_src, reqbufs); + if (ret) + goto out; + s5p_mfc_close_mfc_inst(dev, ctx); + ctx->src_bufs_cnt = 0; + ctx->output_state = QUEUE_FREE; + } else if (ctx->output_state == QUEUE_FREE) { + /* Can only request buffers when we have a valid format set. */ + WARN_ON(ctx->src_bufs_cnt != 0); + if (ctx->state != MFCINST_INIT) { + mfc_err("Reqbufs called in an invalid state\n"); + ret = -EINVAL; + goto out; } - ctx->capture_state = QUEUE_BUFS_REQUESTED; - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); - s5p_mfc_clock_off(); + + mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n", + reqbufs->count); + ret = vb2_reqbufs(&ctx->vq_src, reqbufs); + if (ret) + goto out; + + ret = s5p_mfc_open_mfc_inst(dev, ctx); if (ret) { - mfc_err("vb2_reqbufs on capture failed\n"); - return ret; - } - if (reqbufs->count < ctx->dpb_count) { - mfc_err("Not enough buffers allocated\n"); reqbufs->count = 0; - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); - s5p_mfc_clock_off(); - return -ENOMEM; + vb2_reqbufs(&ctx->vq_src, reqbufs); + goto out; } + + ctx->output_state = QUEUE_BUFS_REQUESTED; + } else { + mfc_err("Buffers have already been requested\n"); + ret = -EINVAL; + } +out: + s5p_mfc_clock_off(); + if (ret) + mfc_err("Failed allocating buffers for OUTPUT queue\n"); + return ret; +} + +static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, + struct v4l2_requestbuffers *reqbufs) +{ + int ret = 0; + + s5p_mfc_clock_on(); + + if (reqbufs->count == 0) { + mfc_debug(2, "Freeing buffers\n"); + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); + if (ret) + goto out; + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); + ctx->dst_bufs_cnt = 0; + } else if (ctx->capture_state == QUEUE_FREE) { + WARN_ON(ctx->dst_bufs_cnt != 0); + mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n", + reqbufs->count); + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); + if (ret) + goto out; + + ctx->capture_state = QUEUE_BUFS_REQUESTED; ctx->total_dpb_count = reqbufs->count; + ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); if (ret) { mfc_err("Failed to allocate decoding buffers\n"); reqbufs->count = 0; - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); - s5p_mfc_clock_off(); - return -ENOMEM; - } - if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { - ctx->capture_state = QUEUE_BUFS_MMAPED; - } else { - mfc_err("Not all buffers passed to buf_init\n"); - reqbufs->count = 0; - s5p_mfc_clock_on(); - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); - s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, - ctx); - s5p_mfc_clock_off(); - return -ENOMEM; + vb2_reqbufs(&ctx->vq_dst, reqbufs); + ret = -ENOMEM; + ctx->capture_state = QUEUE_FREE; + goto out; } + + WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); + ctx->capture_state = QUEUE_BUFS_MMAPED; + if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - s5p_mfc_wait_for_done_ctx(ctx, - S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); + s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, + 0); + } else { + mfc_err("Buffers have already been requested\n"); + ret = -EINVAL; } +out: + s5p_mfc_clock_off(); + if (ret) + mfc_err("Failed allocating buffers for CAPTURE queue\n"); return ret; } +/* Reqeust buffers */ +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); + + if (reqbufs->memory != V4L2_MEMORY_MMAP) { + mfc_err("Only V4L2_MEMORY_MAP is supported\n"); + return -EINVAL; + } + + if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + return reqbufs_output(dev, ctx, reqbufs); + } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + return reqbufs_capture(dev, ctx, reqbufs); + } else { + mfc_err("Invalid type requested\n"); + return -EINVAL; + } +} + /* Query buffer */ static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) @@ -588,7 +617,7 @@ static int vidioc_querybuf(struct file *file, void *priv, return -EINVAL; } mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); - if (ctx->state == MFCINST_INIT && + if (ctx->state == MFCINST_GOT_INST && buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ret = vb2_querybuf(&ctx->vq_src, buf); } else if (ctx->state == MFCINST_RUNNING && @@ -623,17 +652,27 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) /* Dequeue a buffer */ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { + const struct v4l2_event ev = { + .type = V4L2_EVENT_EOS + }; struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + int ret; if (ctx->state == MFCINST_ERROR) { mfc_err("Call on DQBUF after unrecoverable error\n"); return -EIO; } if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); - else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); - return -EINVAL; + ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); + else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); + if (ret == 0 && ctx->state == MFCINST_FINISHED && + list_empty(&ctx->vq_dst.done_list)) + v4l2_event_queue_fh(&ctx->fh, &ev); + } else { + ret = -EINVAL; + } + return ret; } /* Export DMA buffer */ @@ -654,39 +693,11 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); - struct s5p_mfc_dev *dev = ctx->dev; int ret = -EINVAL; mfc_debug_enter(); - if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - - if (ctx->state == MFCINST_INIT) { - ctx->dst_bufs_cnt = 0; - ctx->src_bufs_cnt = 0; - ctx->capture_state = QUEUE_FREE; - ctx->output_state = QUEUE_FREE; - s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, - ctx); - s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, - ctx); - set_work_bit_irqsave(ctx); - s5p_mfc_clean_ctx_int_flags(ctx); - s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - - if (s5p_mfc_wait_for_done_ctx(ctx, - S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { - /* Error or timeout */ - mfc_err("Error getting instance from hardware\n"); - s5p_mfc_hw_call(dev->mfc_ops, - release_instance_buffer, ctx); - s5p_mfc_hw_call(dev->mfc_ops, - release_dec_desc_buffer, ctx); - return -EIO; - } - mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); - } + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ret = vb2_streamon(&ctx->vq_src, type); - } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ret = vb2_streamon(&ctx->vq_dst, type); mfc_debug_leave(); @@ -740,7 +751,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: if (ctx->state >= MFCINST_HEAD_PARSED && ctx->state < MFCINST_ABORT) { - ctrl->val = ctx->dpb_count; + ctrl->val = ctx->pb_count; break; } else if (ctx->state != MFCINST_INIT) { v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); @@ -752,7 +763,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); if (ctx->state >= MFCINST_HEAD_PARSED && ctx->state < MFCINST_ABORT) { - ctrl->val = ctx->dpb_count; + ctrl->val = ctx->pb_count; } else { v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); return -EINVAL; @@ -809,6 +820,61 @@ static int vidioc_g_crop(struct file *file, void *priv, return 0; } +int vidioc_decoder_cmd(struct file *file, void *priv, + struct v4l2_decoder_cmd *cmd) +{ + struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_buf *buf; + unsigned long flags; + + switch (cmd->cmd) { + case V4L2_ENC_CMD_STOP: + if (cmd->flags != 0) + return -EINVAL; + + if (!ctx->vq_src.streaming) + return -EINVAL; + + spin_lock_irqsave(&dev->irqlock, flags); + if (list_empty(&ctx->src_queue)) { + mfc_err("EOS: empty src queue, entering finishing state"); + ctx->state = MFCINST_FINISHING; + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); + spin_unlock_irqrestore(&dev->irqlock, flags); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + } else { + mfc_err("EOS: marking last buffer of stream"); + buf = list_entry(ctx->src_queue.prev, + struct s5p_mfc_buf, list); + if (buf->flags & MFC_BUF_FLAG_USED) + ctx->state = MFCINST_FINISHING; + else + buf->flags |= MFC_BUF_FLAG_EOS; + spin_unlock_irqrestore(&dev->irqlock, flags); + } + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(fh, sub, 2, NULL); + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subscribe(fh, sub); + default: + return -EINVAL; + } +} + + /* v4l2_ioctl_ops */ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { .vidioc_querycap = vidioc_querycap, @@ -830,6 +896,9 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_crop = vidioc_g_crop, + .vidioc_decoder_cmd = vidioc_decoder_cmd, + .vidioc_subscribe_event = vidioc_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static int s5p_mfc_queue_setup(struct vb2_queue *vq, @@ -857,10 +926,10 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, /* Output plane count is 2 - one for Y and one for CbCr */ *plane_count = 2; /* Setup buffer count */ - if (*buf_count < ctx->dpb_count) - *buf_count = ctx->dpb_count; - if (*buf_count > ctx->dpb_count + MFC_MAX_EXTRA_DPB) - *buf_count = ctx->dpb_count + MFC_MAX_EXTRA_DPB; + if (*buf_count < ctx->pb_count) + *buf_count = ctx->pb_count; + if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB) + *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB; if (*buf_count > MFC_MAX_BUFFERS) *buf_count = MFC_MAX_BUFFERS; } else { @@ -875,7 +944,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[0] = ctx->luma_size; psize[1] = ctx->chroma_size; - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; else @@ -887,7 +956,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[0] = ctx->dec_src_buf_size; allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; } else { - mfc_err("This video node is dedicated to decoding. Decoding not initalised\n"); + mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); return -EINVAL; } return 0; @@ -976,7 +1045,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) return 0; } -static int s5p_mfc_stop_streaming(struct vb2_queue *q) +static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); @@ -991,25 +1060,35 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); aborted = 1; } - spin_lock_irqsave(&dev->irqlock, flags); if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + spin_lock_irqsave(&dev->irqlock, flags); s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, &ctx->vq_dst); INIT_LIST_HEAD(&ctx->dst_queue); ctx->dst_queue_cnt = 0; ctx->dpb_flush_flag = 1; ctx->dec_dst_flag = 0; + spin_unlock_irqrestore(&dev->irqlock, flags); + if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { + ctx->state = MFCINST_FLUSH; + set_work_bit_irqsave(ctx); + s5p_mfc_clean_ctx_int_flags(ctx); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + if (s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) + mfc_err("Err flushing buffers\n"); + } } if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + spin_lock_irqsave(&dev->irqlock, flags); s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, &ctx->vq_src); INIT_LIST_HEAD(&ctx->src_queue); ctx->src_queue_cnt = 0; + spin_unlock_irqrestore(&dev->irqlock, flags); } if (aborted) ctx->state = MFCINST_RUNNING; - spin_unlock_irqrestore(&dev->irqlock, flags); - return 0; } @@ -1129,10 +1208,16 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx) { struct v4l2_format f; - f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC; + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; ctx->src_fmt = find_format(&f, MFC_FMT_DEC); - f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC; + if (IS_MFCV8(ctx->dev)) + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; + else if (IS_MFCV6_PLUS(ctx->dev)) + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; + else + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; ctx->dst_fmt = find_format(&f, MFC_FMT_RAW); 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/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index f92f6ddd739..d26b2484ca1 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -26,6 +26,7 @@ #include <media/v4l2-ctrls.h> #include <media/videobuf2-core.h> #include "s5p_mfc_common.h" +#include "s5p_mfc_ctrl.h" #include "s5p_mfc_debug.h" #include "s5p_mfc_enc.h" #include "s5p_mfc_intr.h" @@ -41,6 +42,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V6_BIT | MFC_V7_BIT, }, { .name = "4:2:0 2 Planes 64x32 Tiles", @@ -48,6 +50,7 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V5_BIT, }, { .name = "4:2:0 2 Planes Y/CbCr", @@ -55,6 +58,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "4:2:0 2 Planes Y/CrCb", @@ -62,6 +67,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, .num_planes = 2, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "H264 Encoded Stream", @@ -69,6 +76,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_H264_ENC, .type = MFC_FMT_ENC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "MPEG4 Encoded Stream", @@ -76,6 +85,8 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_MPEG4_ENC, .type = MFC_FMT_ENC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, }, { .name = "H263 Encoded Stream", @@ -83,6 +94,16 @@ static struct s5p_mfc_fmt formats[] = { .codec_mode = S5P_MFC_CODEC_H263_ENC, .type = MFC_FMT_ENC, .num_planes = 1, + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | + MFC_V8_BIT, + }, + { + .name = "VP8 Encoded Stream", + .fourcc = V4L2_PIX_FMT_VP8, + .codec_mode = S5P_MFC_CODEC_VP8_ENC, + .type = MFC_FMT_ENC, + .num_planes = 1, + .versions = MFC_V7_BIT | MFC_V8_BIT, }, }; @@ -106,7 +127,7 @@ static struct mfc_control controls[] = { .minimum = 0, .maximum = (1 << 16) - 1, .step = 1, - .default_value = 0, + .default_value = 12, }, { .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, @@ -201,6 +222,24 @@ static struct mfc_control controls[] = { .default_value = 0, }, { + .id = V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Horizontal MV Search Range", + .minimum = 16, + .maximum = 128, + .step = 16, + .default_value = 32, + }, + { + .id = V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Vertical MV Search Range", + .minimum = 16, + .maximum = 128, + .step = 16, + .default_value = 32, + }, + { .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0, @@ -232,6 +271,7 @@ static struct mfc_control controls[] = { .minimum = 0, .maximum = 1, .default_value = 0, + .step = 1, .menu_skip_mask = 0, }, { @@ -348,7 +388,7 @@ static struct mfc_control controls[] = { .minimum = 0, .maximum = 51, .step = 1, - .default_value = 1, + .default_value = 51, }, { .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, @@ -391,7 +431,7 @@ static struct mfc_control controls[] = { .minimum = 1, .maximum = 31, .step = 1, - .default_value = 1, + .default_value = 31, }, { .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP, @@ -436,7 +476,7 @@ static struct mfc_control controls[] = { .minimum = 0, .maximum = 51, .step = 1, - .default_value = 1, + .default_value = 51, }, { .id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, @@ -556,6 +596,100 @@ static struct mfc_control controls[] = { .step = 1, .default_value = 0, }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS, + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .maximum = V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS, + .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION, + .menu_skip_mask = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES, + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .maximum = V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME, + .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME, + .menu_skip_mask = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 63, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 7, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = (1 << 16) - 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL, + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, + .maximum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD, + .default_value = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, + .menu_skip_mask = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_MAX_QP, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 127, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_MIN_QP, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 11, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 10, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 10, + }, + { + .id = V4L2_CID_MPEG_VIDEO_VPX_PROFILE, + .type = V4L2_CTRL_TYPE_INTEGER, + .minimum = 0, + .maximum = 3, + .step = 1, + .default_value = 0, + }, }; #define NUM_CTRLS ARRAY_SIZE(controls) @@ -591,7 +725,7 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) return 1; /* context is ready to encode a frame */ if ((ctx->state == MFCINST_RUNNING || - ctx->state == MFCINST_HEAD_PARSED) && + ctx->state == MFCINST_HEAD_PRODUCED) && ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) return 1; /* context is ready to encode remaining frames */ @@ -648,30 +782,35 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) struct s5p_mfc_enc_params *p = &ctx->enc_params; struct s5p_mfc_buf *dst_mb; unsigned long flags; + unsigned int enc_pb_count; if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) { spin_lock_irqsave(&dev->irqlock, flags); - dst_mb = list_entry(ctx->dst_queue.next, - struct s5p_mfc_buf, list); - list_del(&dst_mb->list); - ctx->dst_queue_cnt--; - vb2_set_plane_payload(dst_mb->b, 0, - s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev)); - vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); + if (!list_empty(&ctx->dst_queue)) { + dst_mb = list_entry(ctx->dst_queue.next, + struct s5p_mfc_buf, list); + list_del(&dst_mb->list); + ctx->dst_queue_cnt--; + vb2_set_plane_payload(dst_mb->b, 0, + s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, + dev)); + vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); + } spin_unlock_irqrestore(&dev->irqlock, flags); } - if (IS_MFCV6(dev)) { - ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */ - } else { + + if (!IS_MFCV6_PLUS(dev)) { ctx->state = MFCINST_RUNNING; if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - } - - if (IS_MFCV6(dev)) - ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, + } else { + enc_pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_enc_dpb_count, dev); + if (ctx->pb_count < enc_pb_count) + ctx->pb_count = enc_pb_count; + ctx->state = MFCINST_HEAD_PRODUCED; + } return 0; } @@ -716,9 +855,9 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); - mfc_debug(2, "Encoded slice type: %d", slice_type); - mfc_debug(2, "Encoded stream size: %d", strm_size); - mfc_debug(2, "Display order: %d", + mfc_debug(2, "Encoded slice type: %d\n", slice_type); + mfc_debug(2, "Encoded stream size: %d\n", strm_size); + mfc_debug(2, "Display order: %d\n", mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); spin_lock_irqsave(&dev->irqlock, flags); if (slice_type >= 0) { @@ -761,8 +900,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) mfc_debug(2, "enc src count: %d, enc ref count: %d\n", ctx->src_queue_cnt, ctx->ref_queue_cnt); } - if (strm_size > 0) { - /* at least one more dest. buffers exist always */ + if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) { mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); list_del(&mb_entry->list); @@ -815,8 +953,10 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, + bool mplane, bool out) { + struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_fmt *fmt; int i, j = 0; @@ -829,6 +969,9 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) continue; else if (!out && formats[i].type != MFC_FMT_ENC) continue; + else if ((dev->variant->version_bit & formats[i].versions) == 0) + continue; + if (j == f->index) { fmt = &formats[i]; strlcpy(f->description, fmt->name, @@ -844,25 +987,25 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, false, false); + return vidioc_enum_fmt(file, f, false, false); } static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, true, false); + return vidioc_enum_fmt(file, f, true, false); } static int vidioc_enum_fmt_vid_out(struct file *file, void *prov, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, false, true); + return vidioc_enum_fmt(file, f, false, true); } static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, true, true); + return vidioc_enum_fmt(file, f, true, true); } static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) @@ -903,6 +1046,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) 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; struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; @@ -912,11 +1056,14 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) mfc_err("failed to try output format\n"); return -EINVAL; } - if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { mfc_err("must be set encoding output size\n"); return -EINVAL; } + if ((dev->variant->version_bit & fmt->versions) == 0) { + mfc_err("Unsupported format by this MFC version.\n"); + return -EINVAL; + } pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->plane_fmt[0].sizeimage; @@ -931,6 +1078,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) mfc_err("failed to try output format\n"); return -EINVAL; } + if ((dev->variant->version_bit & fmt->versions) == 0) { + mfc_err("Unsupported format by this MFC version.\n"); + return -EINVAL; + } + v4l_bound_align_image(&pix_fmt_mp->width, 8, 1920, 1, &pix_fmt_mp->height, 4, 1080, 1, 0); } else { @@ -944,7 +1096,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); - struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; int ret = 0; @@ -957,55 +1108,18 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) goto out; } if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - fmt = find_format(f, MFC_FMT_ENC); - if (!fmt) { - mfc_err("failed to set capture format\n"); - return -EINVAL; - } + /* dst_fmt is validated by call to vidioc_try_fmt */ + ctx->dst_fmt = find_format(f, MFC_FMT_ENC); ctx->state = MFCINST_INIT; - ctx->dst_fmt = fmt; ctx->codec_mode = ctx->dst_fmt->codec_mode; ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage; pix_fmt_mp->plane_fmt[0].bytesperline = 0; ctx->dst_bufs_cnt = 0; ctx->capture_state = QUEUE_FREE; - s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); - set_work_bit_irqsave(ctx); - s5p_mfc_clean_ctx_int_flags(ctx); - s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - if (s5p_mfc_wait_for_done_ctx(ctx, \ - S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) { - /* Error or timeout */ - mfc_err("Error getting instance from hardware\n"); - s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, - ctx); - ret = -EIO; - goto out; - } - mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); + ret = s5p_mfc_open_mfc_inst(dev, ctx); } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - fmt = find_format(f, MFC_FMT_RAW); - if (!fmt) { - 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; - goto out; - } - ctx->src_fmt = fmt; + /* src_fmt is validated by call to vidioc_try_fmt */ + ctx->src_fmt = find_format(f, MFC_FMT_RAW); ctx->img_width = pix_fmt_mp->width; ctx->img_height = pix_fmt_mp->height; mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode); @@ -1023,7 +1137,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ctx->output_state = QUEUE_FREE; } else { mfc_err("invalid buf type\n"); - return -EINVAL; + ret = -EINVAL; } out: mfc_debug_leave(); @@ -1054,15 +1168,13 @@ static int vidioc_reqbufs(struct file *file, void *priv, } ctx->capture_state = QUEUE_BUFS_REQUESTED; - if (!IS_MFCV6(dev)) { - ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, - 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; - } + ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, + 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) { @@ -1070,6 +1182,19 @@ static int vidioc_reqbufs(struct file *file, void *priv, ctx->output_state); return -EINVAL; } + + if (IS_MFCV6_PLUS(dev)) { + /* Check for min encoder buffers */ + if (ctx->pb_count && + (reqbufs->count < ctx->pb_count)) { + reqbufs->count = ctx->pb_count; + mfc_debug(2, "Minimum %d output buffers needed\n", + ctx->pb_count); + } else { + ctx->pb_count = reqbufs->count; + } + } + ret = vb2_reqbufs(&ctx->vq_src, reqbufs); if (ret != 0) { mfc_err("error in vb2_reqbufs() for E(S)\n"); @@ -1309,6 +1434,12 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_VBV_SIZE: p->vbv_size = ctrl->val; break; + case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: + p->mv_h_range = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: + p->mv_v_range = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: p->codec.h264.cpb_size = ctrl->val; break; @@ -1339,7 +1470,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) S5P_FIMV_ENC_PROFILE_H264_BASELINE; break; case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: - if (IS_MFCV6(dev)) + if (IS_MFCV6_PLUS(dev)) p->codec.h264.profile = S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; else @@ -1468,6 +1599,42 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: p->codec.mpeg4.quarter_pixel = ctrl->val; break; + case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: + p->codec.vp8.num_partitions = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: + p->codec.vp8.imd_4x4 = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: + p->codec.vp8.num_ref = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: + p->codec.vp8.filter_level = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: + p->codec.vp8.filter_sharpness = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: + p->codec.vp8.golden_frame_ref_period = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: + p->codec.vp8.golden_frame_sel = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP: + p->codec.vp8.rc_min_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP: + p->codec.vp8.rc_max_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP: + p->codec.vp8.rc_frame_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: + p->codec.vp8.rc_p_frame_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: + p->codec.vp8.profile = ctrl->val; + break; default: v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n", ctrl->id, ctrl->val); @@ -1532,12 +1699,14 @@ int vidioc_encoder_cmd(struct file *file, void *priv, spin_lock_irqsave(&dev->irqlock, flags); if (list_empty(&ctx->src_queue)) { - mfc_debug(2, "EOS: empty src queue, entering finishing state"); + mfc_debug(2, "EOS: empty src queue, entering finishing state\n"); ctx->state = MFCINST_FINISHING; + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); spin_unlock_irqrestore(&dev->irqlock, flags); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { - mfc_debug(2, "EOS: marking last buffer of stream"); + mfc_debug(2, "EOS: marking last buffer of stream\n"); buf = list_entry(ctx->src_queue.prev, struct s5p_mfc_buf, list); if (buf->flags & MFC_BUF_FLAG_USED) @@ -1606,9 +1775,9 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) mfc_err("failed to get plane cookie\n"); return -EINVAL; } - mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx", - vb->v4l2_buf.index, i, - vb2_dma_contig_plane_dma_addr(vb, i)); + mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx\n", + vb->v4l2_buf.index, i, + vb2_dma_contig_plane_dma_addr(vb, i)); } return 0; } @@ -1646,9 +1815,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, *buf_count = 1; if (*buf_count > MFC_MAX_BUFFERS) *buf_count = MFC_MAX_BUFFERS; + psize[0] = ctx->luma_size; psize[1] = ctx->chroma_size; - if (IS_MFCV6(dev)) { + + if (IS_MFCV6_PLUS(dev)) { allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; allocators[1] = @@ -1757,15 +1928,32 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); struct s5p_mfc_dev *dev = ctx->dev; - v4l2_ctrl_handler_setup(&ctx->ctrl_handler); + if (IS_MFCV6_PLUS(dev) && + (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { + + if ((ctx->state == MFCINST_GOT_INST) && + (dev->curr_ctx == ctx->num) && dev->hw_lock) { + s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_SEQ_DONE_RET, + 0); + } + + if (ctx->src_bufs_cnt < ctx->pb_count) { + mfc_err("Need minimum %d OUTPUT buffers\n", + ctx->pb_count); + return -ENOBUFS; + } + } + /* If context is ready then dev = work->data;schedule it to run */ if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + return 0; } -static int s5p_mfc_stop_streaming(struct vb2_queue *q) +static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); @@ -1794,7 +1982,6 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) ctx->src_queue_cnt = 0; } spin_unlock_irqrestore(&dev->irqlock, flags); - return 0; } static void s5p_mfc_buf_queue(struct vb2_buffer *vb) @@ -1895,7 +2082,9 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, &cfg, NULL); } else { - if (controls[i].type == V4L2_CTRL_TYPE_MENU) { + if ((controls[i].type == V4L2_CTRL_TYPE_MENU) || + (controls[i].type == + V4L2_CTRL_TYPE_INTEGER_MENU)) { ctx->ctrls[i] = v4l2_ctrl_new_std_menu( &ctx->ctrl_handler, &s5p_mfc_enc_ctrl_ops, controls[i].id, @@ -1917,6 +2106,7 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) if (controls[i].is_volatile && ctx->ctrls[i]) ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE; } + v4l2_ctrl_handler_setup(&ctx->ctrl_handler); return 0; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 6932e90d406..c9a227428e6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ +#include "s5p_mfc_debug.h" #include "s5p_mfc_opr.h" #include "s5p_mfc_opr_v5.h" #include "s5p_mfc_opr_v6.h" @@ -20,7 +21,7 @@ static struct s5p_mfc_hw_ops *s5p_mfc_ops; void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) { - if (IS_MFCV6(dev)) { + if (IS_MFCV6_PLUS(dev)) { s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; } else { @@ -29,3 +30,38 @@ void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) } dev->mfc_ops = s5p_mfc_ops; } + +void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) +{ + if (IS_MFCV6_PLUS(dev)) + dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); +} + +int s5p_mfc_alloc_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b) +{ + + mfc_debug(3, "Allocating priv: %d\n", b->size); + + b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); + + if (!b->virt) { + mfc_err("Allocating private buffer failed\n"); + return -ENOMEM; + } + + mfc_debug(3, "Allocated addr %p %08x\n", b->virt, b->dma); + return 0; +} + +void s5p_mfc_release_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b) +{ + if (b->virt) { + dma_free_coherent(dev, b->size, b->virt, b->dma); + b->virt = NULL; + b->dma = 0; + b->size = 0; + } +} + diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 420abecafec..7a7ad32ee60 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -17,6 +17,259 @@ #include "s5p_mfc_common.h" +struct s5p_mfc_regs { + + /* codec common registers */ + void *risc_on; + void *risc2host_int; + void *host2risc_int; + void *risc_base_address; + void *mfc_reset; + void *host2risc_command; + void *risc2host_command; + void *mfc_bus_reset_ctrl; + void *firmware_version; + void *instance_id; + void *codec_type; + void *context_mem_addr; + void *context_mem_size; + void *pixel_format; + void *metadata_enable; + void *mfc_version; + void *dbg_info_enable; + void *dbg_buffer_addr; + void *dbg_buffer_size; + void *hed_control; + void *mfc_timeout_value; + void *hed_shared_mem_addr; + void *dis_shared_mem_addr;/* only v7 */ + void *ret_instance_id; + void *error_code; + void *dbg_buffer_output_size; + void *metadata_status; + void *metadata_addr_mb_info; + void *metadata_size_mb_info; + void *dbg_info_stage_counter; + + /* decoder registers */ + void *d_crc_ctrl; + void *d_dec_options; + void *d_display_delay; + void *d_set_frame_width; + void *d_set_frame_height; + void *d_sei_enable; + void *d_min_num_dpb; + void *d_min_first_plane_dpb_size; + void *d_min_second_plane_dpb_size; + void *d_min_third_plane_dpb_size;/* only v8 */ + void *d_min_num_mv; + void *d_mvc_num_views; + void *d_min_num_dis;/* only v7 */ + void *d_min_first_dis_size;/* only v7 */ + void *d_min_second_dis_size;/* only v7 */ + void *d_min_third_dis_size;/* only v7 */ + void *d_post_filter_luma_dpb0;/* v7 and v8 */ + void *d_post_filter_luma_dpb1;/* v7 and v8 */ + void *d_post_filter_luma_dpb2;/* only v7 */ + void *d_post_filter_chroma_dpb0;/* v7 and v8 */ + void *d_post_filter_chroma_dpb1;/* v7 and v8 */ + void *d_post_filter_chroma_dpb2;/* only v7 */ + void *d_num_dpb; + void *d_num_mv; + void *d_init_buffer_options; + void *d_first_plane_dpb_stride_size;/* only v8 */ + void *d_second_plane_dpb_stride_size;/* only v8 */ + void *d_third_plane_dpb_stride_size;/* only v8 */ + void *d_first_plane_dpb_size; + void *d_second_plane_dpb_size; + void *d_third_plane_dpb_size;/* only v8 */ + void *d_mv_buffer_size; + void *d_first_plane_dpb; + void *d_second_plane_dpb; + void *d_third_plane_dpb; + void *d_mv_buffer; + void *d_scratch_buffer_addr; + void *d_scratch_buffer_size; + void *d_metadata_buffer_addr; + void *d_metadata_buffer_size; + void *d_nal_start_options;/* v7 and v8 */ + void *d_cpb_buffer_addr; + void *d_cpb_buffer_size; + void *d_available_dpb_flag_upper; + void *d_available_dpb_flag_lower; + void *d_cpb_buffer_offset; + void *d_slice_if_enable; + void *d_picture_tag; + void *d_stream_data_size; + void *d_dynamic_dpb_flag_upper;/* v7 and v8 */ + void *d_dynamic_dpb_flag_lower;/* v7 and v8 */ + void *d_display_frame_width; + void *d_display_frame_height; + void *d_display_status; + void *d_display_first_plane_addr; + void *d_display_second_plane_addr; + void *d_display_third_plane_addr;/* only v8 */ + void *d_display_frame_type; + void *d_display_crop_info1; + void *d_display_crop_info2; + void *d_display_picture_profile; + void *d_display_luma_crc;/* v7 and v8 */ + void *d_display_chroma0_crc;/* v7 and v8 */ + void *d_display_chroma1_crc;/* only v8 */ + void *d_display_luma_crc_top;/* only v6 */ + void *d_display_chroma_crc_top;/* only v6 */ + void *d_display_luma_crc_bot;/* only v6 */ + void *d_display_chroma_crc_bot;/* only v6 */ + void *d_display_aspect_ratio; + void *d_display_extended_ar; + void *d_decoded_frame_width; + void *d_decoded_frame_height; + void *d_decoded_status; + void *d_decoded_first_plane_addr; + void *d_decoded_second_plane_addr; + void *d_decoded_third_plane_addr;/* only v8 */ + void *d_decoded_frame_type; + void *d_decoded_crop_info1; + void *d_decoded_crop_info2; + void *d_decoded_picture_profile; + void *d_decoded_nal_size; + void *d_decoded_luma_crc; + void *d_decoded_chroma0_crc; + void *d_decoded_chroma1_crc;/* only v8 */ + void *d_ret_picture_tag_top; + void *d_ret_picture_tag_bot; + void *d_ret_picture_time_top; + void *d_ret_picture_time_bot; + void *d_chroma_format; + void *d_vc1_info;/* v7 and v8 */ + void *d_mpeg4_info; + void *d_h264_info; + void *d_metadata_addr_concealed_mb; + void *d_metadata_size_concealed_mb; + void *d_metadata_addr_vc1_param; + void *d_metadata_size_vc1_param; + void *d_metadata_addr_sei_nal; + void *d_metadata_size_sei_nal; + void *d_metadata_addr_vui; + void *d_metadata_size_vui; + void *d_metadata_addr_mvcvui;/* v7 and v8 */ + void *d_metadata_size_mvcvui;/* v7 and v8 */ + void *d_mvc_view_id; + void *d_frame_pack_sei_avail; + void *d_frame_pack_arrgment_id; + void *d_frame_pack_sei_info; + void *d_frame_pack_grid_pos; + void *d_display_recovery_sei_info;/* v7 and v8 */ + void *d_decoded_recovery_sei_info;/* v7 and v8 */ + void *d_display_first_addr;/* only v7 */ + void *d_display_second_addr;/* only v7 */ + void *d_display_third_addr;/* only v7 */ + void *d_decoded_first_addr;/* only v7 */ + void *d_decoded_second_addr;/* only v7 */ + void *d_decoded_third_addr;/* only v7 */ + void *d_used_dpb_flag_upper;/* v7 and v8 */ + void *d_used_dpb_flag_lower;/* v7 and v8 */ + + /* encoder registers */ + void *e_frame_width; + void *e_frame_height; + void *e_cropped_frame_width; + void *e_cropped_frame_height; + void *e_frame_crop_offset; + void *e_enc_options; + void *e_picture_profile; + void *e_vbv_buffer_size; + void *e_vbv_init_delay; + void *e_fixed_picture_qp; + void *e_rc_config; + void *e_rc_qp_bound; + void *e_rc_qp_bound_pb;/* v7 and v8 */ + void *e_rc_mode; + void *e_mb_rc_config; + void *e_padding_ctrl; + void *e_air_threshold; + void *e_mv_hor_range; + void *e_mv_ver_range; + void *e_num_dpb; + void *e_luma_dpb; + void *e_chroma_dpb; + void *e_me_buffer; + void *e_scratch_buffer_addr; + void *e_scratch_buffer_size; + void *e_tmv_buffer0; + void *e_tmv_buffer1; + void *e_ir_buffer_addr;/* v7 and v8 */ + void *e_source_first_plane_addr; + void *e_source_second_plane_addr; + void *e_source_third_plane_addr;/* v7 and v8 */ + void *e_source_first_plane_stride;/* v7 and v8 */ + void *e_source_second_plane_stride;/* v7 and v8 */ + void *e_source_third_plane_stride;/* v7 and v8 */ + void *e_stream_buffer_addr; + void *e_stream_buffer_size; + void *e_roi_buffer_addr; + void *e_param_change; + void *e_ir_size; + void *e_gop_config; + void *e_mslice_mode; + void *e_mslice_size_mb; + void *e_mslice_size_bits; + void *e_frame_insertion; + void *e_rc_frame_rate; + void *e_rc_bit_rate; + void *e_rc_roi_ctrl; + void *e_picture_tag; + void *e_bit_count_enable; + void *e_max_bit_count; + void *e_min_bit_count; + void *e_metadata_buffer_addr; + void *e_metadata_buffer_size; + void *e_encoded_source_first_plane_addr; + void *e_encoded_source_second_plane_addr; + void *e_encoded_source_third_plane_addr;/* v7 and v8 */ + void *e_stream_size; + void *e_slice_type; + void *e_picture_count; + void *e_ret_picture_tag; + void *e_stream_buffer_write_pointer; /* only v6 */ + void *e_recon_luma_dpb_addr; + void *e_recon_chroma_dpb_addr; + void *e_metadata_addr_enc_slice; + void *e_metadata_size_enc_slice; + void *e_mpeg4_options; + void *e_mpeg4_hec_period; + void *e_aspect_ratio; + void *e_extended_sar; + void *e_h264_options; + void *e_h264_options_2;/* v7 and v8 */ + void *e_h264_lf_alpha_offset; + void *e_h264_lf_beta_offset; + void *e_h264_i_period; + void *e_h264_fmo_slice_grp_map_type; + void *e_h264_fmo_num_slice_grp_minus1; + void *e_h264_fmo_slice_grp_change_dir; + void *e_h264_fmo_slice_grp_change_rate_minus1; + void *e_h264_fmo_run_length_minus1_0; + void *e_h264_aso_slice_order_0; + void *e_h264_chroma_qp_offset; + void *e_h264_num_t_layer; + void *e_h264_hierarchical_qp_layer0; + void *e_h264_frame_packing_sei_info; + void *e_h264_nal_control;/* v7 and v8 */ + void *e_mvc_frame_qp_view1; + void *e_mvc_rc_bit_rate_view1; + void *e_mvc_rc_qbound_view1; + void *e_mvc_rc_mode_view1; + void *e_mvc_inter_view_prediction_on; + void *e_vp8_options;/* v7 and v8 */ + void *e_vp8_filter_options;/* v7 and v8 */ + void *e_vp8_golden_frame_option;/* v7 and v8 */ + void *e_vp8_num_t_layer;/* v7 and v8 */ + void *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */ + void *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */ + void *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */ +}; + struct s5p_mfc_hw_ops { int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx); void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx); @@ -80,5 +333,11 @@ struct s5p_mfc_hw_ops { }; void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); +void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); +int s5p_mfc_alloc_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b); +void s5p_mfc_release_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b); + #endif /* S5P_MFC_OPR_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index bf7d010a410..58ec7bb26eb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -34,52 +34,40 @@ #define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT) /* Allocate temporary buffers for decoding */ -int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_dec_temp_buffers_v5(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; + int ret; - 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->dsc.size = buf_size->dsc; + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->dsc); + if (ret) { + mfc_err("Failed to allocate temporary buffer\n"); + return ret; } - 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)); - ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc); - if (ctx->dsc.virt == NULL) { - vb2_dma_contig_memops.put(ctx->dsc.alloc); - ctx->dsc.dma = 0; - ctx->dsc.alloc = NULL; - mfc_err("Remapping DESC buffer failed\n"); - return -ENOMEM; - } - memset(ctx->dsc.virt, 0, buf_size->dsc); + memset(ctx->dsc.virt, 0, ctx->dsc.size); wmb(); return 0; } + /* Release temporary buffers for decoding */ -void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) { - if (ctx->dsc.dma) { - vb2_dma_contig_memops.put(ctx->dsc.alloc); - ctx->dsc.alloc = NULL; - ctx->dsc.dma = 0; - } + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->dsc); } /* Allocate codec buffers */ -int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; unsigned int enc_ref_y_size = 0; unsigned int enc_ref_c_size = 0; unsigned int guard_width, guard_height; + int ret; if (ctx->type == MFCINST_DECODER) { mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", @@ -113,208 +101,160 @@ int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Codecs have different memory requirements */ switch (ctx->codec_mode) { case S5P_MFC_CODEC_H264_DEC: - ctx->bank1_size = + ctx->bank1.size = ALIGN(S5P_FIMV_DEC_NB_IP_SIZE + S5P_FIMV_DEC_VERT_NB_MV_SIZE, S5P_FIMV_DEC_BUF_ALIGN); - ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size; + ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size; break; case S5P_MFC_CODEC_MPEG4_DEC: - ctx->bank1_size = + ctx->bank1.size = ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE + S5P_FIMV_DEC_UPNB_MV_SIZE + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + S5P_FIMV_DEC_STX_PARSER_SIZE + S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE, S5P_FIMV_DEC_BUF_ALIGN); - ctx->bank2_size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_VC1RCV_DEC: case S5P_MFC_CODEC_VC1_DEC: - ctx->bank1_size = + ctx->bank1.size = ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + S5P_FIMV_DEC_UPNB_MV_SIZE + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + S5P_FIMV_DEC_NB_DCAC_SIZE + 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE, S5P_FIMV_DEC_BUF_ALIGN); - ctx->bank2_size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_MPEG2_DEC: - ctx->bank1_size = 0; - ctx->bank2_size = 0; + ctx->bank1.size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_H263_DEC: - ctx->bank1_size = + ctx->bank1.size = ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + S5P_FIMV_DEC_UPNB_MV_SIZE + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + S5P_FIMV_DEC_NB_DCAC_SIZE, S5P_FIMV_DEC_BUF_ALIGN); - ctx->bank2_size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_H264_ENC: - ctx->bank1_size = (enc_ref_y_size * 2) + + ctx->bank1.size = (enc_ref_y_size * 2) + S5P_FIMV_ENC_UPMV_SIZE + S5P_FIMV_ENC_COLFLG_SIZE + S5P_FIMV_ENC_INTRAMD_SIZE + S5P_FIMV_ENC_NBORINFO_SIZE; - ctx->bank2_size = (enc_ref_y_size * 2) + + ctx->bank2.size = (enc_ref_y_size * 2) + (enc_ref_c_size * 4) + S5P_FIMV_ENC_INTRAPRED_SIZE; break; case S5P_MFC_CODEC_MPEG4_ENC: - ctx->bank1_size = (enc_ref_y_size * 2) + + ctx->bank1.size = (enc_ref_y_size * 2) + S5P_FIMV_ENC_UPMV_SIZE + S5P_FIMV_ENC_COLFLG_SIZE + S5P_FIMV_ENC_ACDCCOEF_SIZE; - ctx->bank2_size = (enc_ref_y_size * 2) + + ctx->bank2.size = (enc_ref_y_size * 2) + (enc_ref_c_size * 4); break; case S5P_MFC_CODEC_H263_ENC: - ctx->bank1_size = (enc_ref_y_size * 2) + + ctx->bank1.size = (enc_ref_y_size * 2) + S5P_FIMV_ENC_UPMV_SIZE + S5P_FIMV_ENC_ACDCCOEF_SIZE; - ctx->bank2_size = (enc_ref_y_size * 2) + + ctx->bank2.size = (enc_ref_y_size * 2) + (enc_ref_c_size * 4); 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 = NULL; - printk(KERN_ERR - "Buf alloc for decoding failed (port A)\n"); - return -ENOMEM; + if (ctx->bank1.size > 0) { + + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); + if (ret) { + mfc_err("Failed to allocate Bank1 temporary buffer\n"); + return ret; } - 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)); + BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); } /* Allocate only if memory from bank 2 is necessary */ - if (ctx->bank2_size > 0) { - ctx->bank2_buf = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size); - if (IS_ERR(ctx->bank2_buf)) { - ctx->bank2_buf = NULL; - mfc_err("Buf alloc for decoding failed (port B)\n"); - return -ENOMEM; + if (ctx->bank2.size > 0) { + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, &ctx->bank2); + if (ret) { + mfc_err("Failed to allocate Bank2 temporary buffer\n"); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); + return ret; } - ctx->bank2_phys = s5p_mfc_mem_cookie( - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf); - BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); + BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); } return 0; } /* Release buffers allocated for codec */ -void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { - if (ctx->bank1_buf) { - vb2_dma_contig_memops.put(ctx->bank1_buf); - ctx->bank1_buf = NULL; - ctx->bank1_phys = 0; - ctx->bank1_size = 0; - } - if (ctx->bank2_buf) { - vb2_dma_contig_memops.put(ctx->bank2_buf); - ctx->bank2_buf = NULL; - ctx->bank2_phys = 0; - ctx->bank2_size = 0; - } + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_r, &ctx->bank2); } /* Allocate memory for instance data buffer */ -int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_instance_buffer_v5(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; + int ret; if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) ctx->ctx.size = buf_size->h264_ctx; else 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.alloc)) { - mfc_err("Allocating context buffer failed\n"); - ctx->ctx.alloc = NULL; - return -ENOMEM; + + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); + if (ret) { + mfc_err("Failed to allocate instance buffer\n"); + return ret; } - 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.alloc); - ctx->ctx.alloc = NULL; - ctx->ctx.ofs = 0; - ctx->ctx.dma = 0; - return -ENOMEM; - } + /* Zero content of the allocated memory */ memset(ctx->ctx.virt, 0, ctx->ctx.size); wmb(); /* Initialize shared memory */ - ctx->shm.alloc = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK1_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); + ctx->shm.size = buf_size->shm; + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->shm); + if (ret) { + mfc_err("Failed to allocate shared memory buffer\n"); + return ret; } + /* shared memory offset only keeps the offset from base (port a) */ - ctx->shm.ofs = s5p_mfc_mem_cookie( - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc) - - dev->bank1; + ctx->shm.ofs = ctx->shm.dma - dev->bank1; 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.virt, 0, buf_size->shm); + memset(ctx->shm.virt, 0, buf_size->shm); wmb(); return 0; } /* Release instance buffer */ -void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) -{ - 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.ofs = 0; - ctx->shm.virt = NULL; - } +static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) +{ + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->shm); } -int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) { /* NOP */ return 0; } -void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev) +static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev) { /* NOP */ } @@ -333,7 +273,7 @@ static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx, return readl(ctx->shm.virt + ofs); } -void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx) { unsigned int guard_width, guard_height; @@ -375,7 +315,7 @@ void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx) } } -void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_enc_calc_src_size_v5(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); @@ -421,8 +361,9 @@ static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx) } /* Set registers for decoding stream buffer */ -int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr, - unsigned int start_num_byte, unsigned int buf_size) +static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, + int buf_addr, unsigned int start_num_byte, + unsigned int buf_size) { struct s5p_mfc_dev *dev = ctx->dev; @@ -434,7 +375,7 @@ int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr, } /* Set decoding frame buffer */ -int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) { unsigned int frame_size, i; unsigned int frame_size_ch, frame_size_mv; @@ -443,10 +384,10 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) size_t buf_addr1, buf_addr2; int buf_size1, buf_size2; - buf_addr1 = ctx->bank1_phys; - buf_size1 = ctx->bank1_size; - buf_addr2 = ctx->bank2_phys; - buf_size2 = ctx->bank2_size; + buf_addr1 = ctx->bank1.dma; + buf_size1 = ctx->bank1.size; + buf_addr2 = ctx->bank2.dma; + buf_size2 = ctx->bank2.size; dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~S5P_FIMV_DPB_COUNT_MASK; mfc_write(dev, ctx->total_dpb_count | dpb, @@ -523,7 +464,6 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) mfc_err("Unknown codec for decoding (%x)\n", ctx->codec_mode); return -EINVAL; - break; } frame_size = ctx->luma_size; frame_size_ch = ctx->chroma_size; @@ -567,7 +507,7 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) } /* Set registers for encoding stream buffer */ -int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx, +static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx, unsigned long addr, unsigned int size) { struct s5p_mfc_dev *dev = ctx->dev; @@ -577,7 +517,7 @@ int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx, return 0; } -void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, +static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, unsigned long y_addr, unsigned long c_addr) { struct s5p_mfc_dev *dev = ctx->dev; @@ -586,7 +526,7 @@ void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR); } -void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, +static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, unsigned long *y_addr, unsigned long *c_addr) { struct s5p_mfc_dev *dev = ctx->dev; @@ -598,7 +538,7 @@ void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, } /* Set encoding ref & codec buffer */ -int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; size_t buf_addr1, buf_addr2; @@ -607,10 +547,10 @@ int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx) unsigned int guard_width, guard_height; int i; - buf_addr1 = ctx->bank1_phys; - buf_size1 = ctx->bank1_size; - buf_addr2 = ctx->bank2_phys; - buf_size2 = ctx->bank2_size; + buf_addr1 = ctx->bank1.dma; + buf_size1 = ctx->bank1.size; + buf_addr2 = ctx->bank2.dma; + buf_size2 = ctx->bank2.size; enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); @@ -1102,7 +1042,7 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) } /* Initialize decoding */ -int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; @@ -1138,7 +1078,7 @@ static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) } /* Decode a single frame */ -int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx, +static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx, enum s5p_mfc_decode_arg last_frame) { struct s5p_mfc_dev *dev = ctx->dev; @@ -1167,7 +1107,7 @@ int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx, return 0; } -int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; @@ -1189,7 +1129,7 @@ int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx) } /* Encode a single frame */ -int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; int cmd; @@ -1248,6 +1188,15 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) unsigned long flags; unsigned int index; + if (ctx->state == MFCINST_FINISHING) { + last_frame = MFC_DEC_LAST_FRAME; + s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0); + dev->curr_ctx = ctx->num; + s5p_mfc_clean_ctx_int_flags(ctx); + s5p_mfc_decode_one_frame_v5(ctx, last_frame); + return 0; + } + spin_lock_irqsave(&dev->irqlock, flags); /* Frames are being decoded */ if (list_empty(&ctx->src_queue)) { @@ -1326,8 +1275,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_clean_ctx_int_flags(ctx); - mfc_debug(2, "encoding buffer with index=%d state=%d", - src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); + mfc_debug(2, "encoding buffer with index=%d state=%d\n", + src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); s5p_mfc_encode_one_frame_v5(ctx); return 0; } @@ -1414,7 +1363,7 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) } /* Try running an operation on hardware */ -void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) +static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) { struct s5p_mfc_ctx *ctx; int new_ctx; @@ -1530,7 +1479,7 @@ void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) } -void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) +static void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) { struct s5p_mfc_buf *b; int i; @@ -1544,52 +1493,52 @@ void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) } } -void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev) +static void s5p_mfc_clear_int_flags_v5(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); } -int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT; } -int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT; } -int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS); } -int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS); } -int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) & S5P_FIMV_DECODE_FRAME_MASK; } -int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx) { return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >> S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) & S5P_FIMV_DECODE_FRAME_MASK; } -int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES); } -int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev) { int reason; reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) & @@ -1633,102 +1582,102 @@ int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev) break; default: reason = S5P_MFC_R2H_CMD_EMPTY; - }; + } return reason; } -int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2); } -int s5p_mfc_err_dec_v5(unsigned int err) +static int s5p_mfc_err_dec_v5(unsigned int err) { return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT; } -int s5p_mfc_err_dspl_v5(unsigned int err) +static int s5p_mfc_err_dspl_v5(unsigned int err) { return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT; } -int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_HRESOL); } -int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_VRESOL); } -int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER); } -int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev) { /* NOP */ return -1; } -int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1); } -int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE); } -int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE); } -int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev) { return -1; } -int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT); } -int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL); } -int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev) { return -1; } -int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev) { return -1; } -unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx) +static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP); } -unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx) +static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT); } -unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx) +static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, CROP_INFO_H); } -unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx) +static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, CROP_INFO_V); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 3a8cfd9fc1b..4f5e0ead90c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -43,13 +43,13 @@ } 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) +#define READL(reg) \ + (WARN_ON_ONCE(!(reg)) ? 0 : readl(reg)) +#define WRITEL(data, reg) \ + (WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg))) /* Allocate temporary buffers for decoding */ -int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) { /* NOP */ @@ -57,22 +57,17 @@ int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) } /* Release temproary buffers for decoding */ -void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx) { /* NOP */ } -int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) -{ - /* NOP */ - return -1; -} - /* Allocate codec buffers */ -int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; unsigned int mb_width, mb_height; + int ret; mb_width = MB_WIDTH(ctx->img_width); mb_height = MB_HEIGHT(ctx->img_height); @@ -82,19 +77,31 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) 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 = S5P_FIMV_NUM_TMV_BUFFERS_V6 * + if (IS_MFCV8(dev)) + ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * + ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height), + S5P_FIMV_TMV_BUFFER_ALIGN_V6); + else + ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), S5P_FIMV_TMV_BUFFER_ALIGN_V6); + ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * S5P_FIMV_LUMA_MB_TO_PIXEL_V6, S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * S5P_FIMV_CHROMA_MB_TO_PIXEL_V6, S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6); - ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( - ctx->img_width, ctx->img_height, - mb_width, mb_height), - S5P_FIMV_ME_BUFFER_ALIGN_V6); + if (IS_MFCV8(dev)) + ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8( + ctx->img_width, ctx->img_height, + mb_width, mb_height), + S5P_FIMV_ME_BUFFER_ALIGN_V6); + else + ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( + ctx->img_width, ctx->img_height, + mb_width, mb_height), + S5P_FIMV_ME_BUFFER_ALIGN_V6); mfc_debug(2, "recon luma size: %d chroma size: %d\n", ctx->luma_dpb_size, ctx->chroma_dpb_size); @@ -106,24 +113,38 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) switch (ctx->codec_mode) { case S5P_MFC_CODEC_H264_DEC: case S5P_MFC_CODEC_H264_MVC_DEC: - ctx->scratch_buf_size = - S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( + if (IS_MFCV8(dev)) + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8( + mb_width, + mb_height); + else + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( mb_width, mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = + ctx->bank1.size = ctx->scratch_buf_size + (ctx->mv_count * ctx->mv_size); break; case S5P_MFC_CODEC_MPEG4_DEC: - ctx->scratch_buf_size = - S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( - mb_width, - mb_height); + if (IS_MFCV7_PLUS(dev)) { + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7( + mb_width, + mb_height); + } else { + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( + mb_width, + mb_height); + } + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = ctx->scratch_buf_size; + ctx->bank1.size = ctx->scratch_buf_size; break; case S5P_MFC_CODEC_VC1RCV_DEC: case S5P_MFC_CODEC_VC1_DEC: @@ -133,11 +154,11 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = ctx->scratch_buf_size; + ctx->bank1.size = ctx->scratch_buf_size; break; case S5P_MFC_CODEC_MPEG2_DEC: - ctx->bank1_size = 0; - ctx->bank2_size = 0; + ctx->bank1.size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_H263_DEC: ctx->scratch_buf_size = @@ -146,29 +167,41 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = ctx->scratch_buf_size; + ctx->bank1.size = ctx->scratch_buf_size; break; case S5P_MFC_CODEC_VP8_DEC: - ctx->scratch_buf_size = - S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( - mb_width, - mb_height); + if (IS_MFCV8(dev)) + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8( + mb_width, + mb_height); + else + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( + mb_width, + mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = ctx->scratch_buf_size; + ctx->bank1.size = ctx->scratch_buf_size; break; case S5P_MFC_CODEC_H264_ENC: - ctx->scratch_buf_size = - S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( + if (IS_MFCV8(dev)) + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8( mb_width, mb_height); + else + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( + mb_width, + mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = + ctx->bank1.size = ctx->scratch_buf_size + ctx->tmv_buffer_size + - (ctx->dpb_count * (ctx->luma_dpb_size + + (ctx->pb_count * (ctx->luma_dpb_size + ctx->chroma_dpb_size + ctx->me_buffer_size)); - ctx->bank2_size = 0; + ctx->bank2.size = 0; break; case S5P_MFC_CODEC_MPEG4_ENC: case S5P_MFC_CODEC_H263_ENC: @@ -178,49 +211,59 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) mb_height); ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); - ctx->bank1_size = + ctx->bank1.size = + ctx->scratch_buf_size + ctx->tmv_buffer_size + + (ctx->pb_count * (ctx->luma_dpb_size + + ctx->chroma_dpb_size + ctx->me_buffer_size)); + ctx->bank2.size = 0; + break; + case S5P_MFC_CODEC_VP8_ENC: + if (IS_MFCV8(dev)) + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8( + mb_width, + mb_height); + else + ctx->scratch_buf_size = + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( + mb_width, + mb_height); + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); + ctx->bank1.size = ctx->scratch_buf_size + ctx->tmv_buffer_size + - (ctx->dpb_count * (ctx->luma_dpb_size + + (ctx->pb_count * (ctx->luma_dpb_size + ctx->chroma_dpb_size + ctx->me_buffer_size)); - ctx->bank2_size = 0; + 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; + if (ctx->bank1.size > 0) { + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); + if (ret) { + mfc_err("Failed to allocate Bank1 memory\n"); + return ret; } - 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)); + BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); } - return 0; } /* Release buffers allocated for codec */ -void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_release_codec_buffers_v6(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; - } + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); } /* Allocate memory for instance data buffer */ -int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_alloc_instance_buffer_v6(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; + int ret; mfc_debug_enter(); @@ -242,6 +285,7 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; case S5P_MFC_CODEC_MPEG4_ENC: case S5P_MFC_CODEC_H263_ENC: + case S5P_MFC_CODEC_VP8_ENC: ctx->ctx.size = buf_size->other_enc_ctx; break; default: @@ -250,25 +294,10 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) 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; + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); + if (ret) { + mfc_err("Failed to allocate instance buffer\n"); + return ret; } memset(ctx->ctx.virt, 0, ctx->ctx.size); @@ -280,46 +309,24 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) } /* Release instance buffer */ -void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_release_instance_buffer_v6(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(); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); } /* Allocate context buffers for SYS_INIT */ -int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) { struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; + int ret; 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; + dev->ctx_buf.size = buf_size->dev_ctx; + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &dev->ctx_buf); + if (ret) { + mfc_err("Failed to allocate device context buffer\n"); + return ret; } memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx); @@ -331,14 +338,9 @@ int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) } /* Release context buffers for SYS_INIT */ -void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) +static void s5p_mfc_release_dev_context_buffer_v6(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; - } + s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf); } static int calc_plane(int width, int height) @@ -355,7 +357,7 @@ static int calc_plane(int width, int height) (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6); } -void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) { ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6); ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6); @@ -365,6 +367,12 @@ void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height); ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1)); + if (IS_MFCV8(ctx->dev)) { + /* MFCv8 needs additional 64 bytes for luma,chroma dpb*/ + ctx->luma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8; + ctx->chroma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8; + } + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width, @@ -375,7 +383,7 @@ void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) } } -void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) +static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) { unsigned int mb_width, mb_height; @@ -385,58 +393,75 @@ void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); + + /* MFCv7 needs pad bytes for Luma and Chroma */ + if (IS_MFCV7_PLUS(ctx->dev)) { + ctx->luma_size += MFC_LUMA_PAD_BYTES_V7; + ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7; + } } /* Set registers for decoding stream buffer */ -int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr, - unsigned int start_num_byte, unsigned int strm_size) +static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, + int buf_addr, unsigned int start_num_byte, + unsigned int strm_size) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; 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_V6); - WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); - WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); - WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); + WRITEL(strm_size, mfc_regs->d_stream_data_size); + WRITEL(buf_addr, mfc_regs->d_cpb_buffer_addr); + WRITEL(buf_size->cpb, mfc_regs->d_cpb_buffer_size); + WRITEL(start_num_byte, mfc_regs->d_cpb_buffer_offset); mfc_debug_leave(); return 0; } /* Set decoding frame buffer */ -int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_set_dec_frame_buffer_v6(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; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; size_t buf_addr1; int buf_size1; int align_gap; - buf_addr1 = ctx->bank1_phys; - buf_size1 = ctx->bank1_size; + buf_addr1 = ctx->bank1.dma; + 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_V6); - WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); - WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); + WRITEL(ctx->total_dpb_count, mfc_regs->d_num_dpb); + WRITEL(ctx->luma_size, mfc_regs->d_first_plane_dpb_size); + WRITEL(ctx->chroma_size, mfc_regs->d_second_plane_dpb_size); + + WRITEL(buf_addr1, mfc_regs->d_scratch_buffer_addr); + WRITEL(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size); + + if (IS_MFCV8(dev)) { + WRITEL(ctx->img_width, + mfc_regs->d_first_plane_dpb_stride_size); + WRITEL(ctx->img_width, + mfc_regs->d_second_plane_dpb_stride_size); + } - WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); - WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); 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_V6); - WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6); + WRITEL(ctx->mv_size, mfc_regs->d_mv_buffer_size); + WRITEL(ctx->mv_count, mfc_regs->d_num_mv); } frame_size = ctx->luma_size; @@ -450,11 +475,11 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) 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_V6 + i * 4); + mfc_regs->d_first_plane_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_V6 + i * 4); + mfc_regs->d_second_plane_dpb + i * 4); } if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { @@ -467,7 +492,7 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) mfc_debug(2, "\tBuf1: %x, size: %d\n", buf_addr1, buf_size1); - WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4); + WRITEL(buf_addr1, mfc_regs->d_mv_buffer + i * 4); buf_addr1 += frame_size_mv; buf_size1 -= frame_size_mv; } @@ -480,7 +505,7 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) return -ENOMEM; } - WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); + WRITEL(ctx->inst_no, mfc_regs->instance_id); s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_INIT_BUFS_V6, NULL); @@ -489,92 +514,96 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) } /* Set registers for encoding stream buffer */ -int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, +static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, unsigned long addr, unsigned int size) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; - WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */ - WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); + WRITEL(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */ + WRITEL(size, mfc_regs->e_stream_buffer_size); - mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d", - addr, size); + mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n", + addr, size); return 0; } -void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, +static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, unsigned long y_addr, unsigned long c_addr) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; - WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ - WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); + WRITEL(y_addr, mfc_regs->e_source_first_plane_addr); + WRITEL(c_addr, mfc_regs->e_source_second_plane_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); + mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); + mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); } -void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, +static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, unsigned long *y_addr, unsigned long *c_addr) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; unsigned long enc_recon_y_addr, enc_recon_c_addr; - *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); - *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); + *y_addr = READL(mfc_regs->e_encoded_source_first_plane_addr); + *c_addr = READL(mfc_regs->e_encoded_source_second_plane_addr); - enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); - enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); + enc_recon_y_addr = READL(mfc_regs->e_recon_luma_dpb_addr); + enc_recon_c_addr = READL(mfc_regs->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); + mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr); + mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr); } /* Set encoding ref & codec buffer */ -int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - size_t buf_addr1, buf_size1; - int i; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; + size_t buf_addr1; + int i, buf_size1; mfc_debug_enter(); - buf_addr1 = ctx->bank1_phys; - buf_size1 = ctx->bank1_size; + buf_addr1 = ctx->bank1.dma; + 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_V6 + (4 * i)); + for (i = 0; i < ctx->pb_count; i++) { + WRITEL(buf_addr1, mfc_regs->e_luma_dpb + (4 * i)); buf_addr1 += ctx->luma_dpb_size; - WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i)); + WRITEL(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i)); buf_addr1 += ctx->chroma_dpb_size; - WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i)); + WRITEL(buf_addr1, mfc_regs->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_V6); - WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); + WRITEL(buf_addr1, mfc_regs->e_scratch_buffer_addr); + WRITEL(ctx->scratch_buf_size, mfc_regs->e_scratch_buffer_size); buf_addr1 += ctx->scratch_buf_size; buf_size1 -= ctx->scratch_buf_size; - WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6); + WRITEL(buf_addr1, mfc_regs->e_tmv_buffer0); buf_addr1 += ctx->tmv_buffer_size >> 1; - WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6); + WRITEL(buf_addr1, mfc_regs->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); + buf_addr1, buf_size1, ctx->pb_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_V6); + WRITEL(ctx->inst_no, mfc_regs->instance_id); s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_INIT_BUFS_V6, NULL); @@ -586,18 +615,19 @@ int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; /* multi-slice control */ /* multi-slice MB number or bit size */ - WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6); + WRITEL(ctx->slice_mode, mfc_regs->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_V6); + WRITEL(ctx->slice_size.mb, mfc_regs->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_V6); + WRITEL(ctx->slice_size.bits, mfc_regs->e_mslice_size_bits); } else { - WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6); - WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); + WRITEL(0x0, mfc_regs->e_mslice_size_mb); + WRITEL(0x0, mfc_regs->e_mslice_size_bits); } return 0; @@ -606,27 +636,28 @@ static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; 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_V6); /* 16 align */ + WRITEL(ctx->img_width, mfc_regs->e_frame_width); /* 16 align */ /* height */ - WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */ + WRITEL(ctx->img_height, mfc_regs->e_frame_height); /* 16 align */ /* cropped width */ - WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); + WRITEL(ctx->img_width, mfc_regs->e_cropped_frame_width); /* cropped height */ - WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); + WRITEL(ctx->img_height, mfc_regs->e_cropped_frame_height); /* cropped offset */ - WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); + WRITEL(0x0, mfc_regs->e_frame_crop_offset); /* pictype : IDR period */ reg = 0; reg |= p->gop_size & 0xFFFF; - WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); + WRITEL(reg, mfc_regs->e_gop_config); /* multi-slice control */ /* multi-slice MB number or bit size */ @@ -634,65 +665,65 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) reg = 0; if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { reg |= (0x1 << 3); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_enc_options); ctx->slice_size.bits = p->slice_bit; } else { reg &= ~(0x1 << 3); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); } s5p_mfc_set_slice_mode(ctx); /* cyclic intra refresh */ - WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6); - reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(p->intra_refresh_mb, mfc_regs->e_ir_size); + reg = READL(mfc_regs->e_enc_options); if (p->intra_refresh_mb == 0) reg &= ~(0x1 << 4); else reg |= (0x1 << 4); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* 'NON_REFERENCE_STORE_ENABLE' for debugging */ - reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); + reg = READL(mfc_regs->e_enc_options); reg &= ~(0x1 << 9); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->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_V6); + reg = READL(mfc_regs->e_enc_options); reg &= ~(0x1 << 7); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* 0: NV12(CbCr), 1: NV21(CrCb) */ - WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); + WRITEL(0x0, mfc_regs->pixel_format); } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) { /* 0: Linear, 1: 2D tiled*/ - reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); + reg = READL(mfc_regs->e_enc_options); reg &= ~(0x1 << 7); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* 0: NV12(CbCr), 1: NV21(CrCb) */ - WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); + WRITEL(0x1, mfc_regs->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_V6); + reg = READL(mfc_regs->e_enc_options); reg |= (0x1 << 7); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* 0: NV12(CbCr), 1: NV21(CrCb) */ - WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); + WRITEL(0x0, mfc_regs->pixel_format); } /* memory structure recon. frame */ /* 0: Linear, 1: 2D tiled */ - reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); + reg = READL(mfc_regs->e_enc_options); reg |= (0x1 << 8); - WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* padding control & value */ - WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6); + WRITEL(0x0, mfc_regs->e_padding_ctrl); if (p->pad) { reg = 0; /** enable */ @@ -703,68 +734,64 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) reg |= ((p->pad_cb & 0xFF) << 8); /** y value */ reg |= p->pad_luma & 0xFF; - WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_rc_config); /* bit rate */ if (p->rc_frame) WRITEL(p->rc_bitrate, - S5P_FIMV_E_RC_BIT_RATE_V6); + mfc_regs->e_rc_bit_rate); else - WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6); + WRITEL(1, mfc_regs->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_V6); + WRITEL(1, mfc_regs->e_rc_mode); else /* loose CBR */ - WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6); + WRITEL(2, mfc_regs->e_rc_mode); } /* seq header ctrl */ - reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); + reg = READL(mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_enc_options); /* 'DROP_CONTROL_ENABLE', disable */ - reg = READL(S5P_FIMV_E_RC_CONFIG_V6); + reg = READL(mfc_regs->e_rc_config); reg &= ~(0x1 << 10); - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); /* setting for MV range [16, 256] */ - reg = 0; - reg &= ~(0x3FFF); - reg = 256; - WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6); + reg = (p->mv_h_range & S5P_FIMV_E_MV_RANGE_V6_MASK); + WRITEL(reg, mfc_regs->e_mv_hor_range); - reg = 0; - reg &= ~(0x3FFF); - reg = 256; - WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6); + reg = (p->mv_v_range & S5P_FIMV_E_MV_RANGE_V6_MASK); + WRITEL(reg, mfc_regs->e_mv_ver_range); - WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6); - WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); - WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6); - WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6); - WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6); + WRITEL(0x0, mfc_regs->e_frame_insertion); + WRITEL(0x0, mfc_regs->e_roi_buffer_addr); + WRITEL(0x0, mfc_regs->e_param_change); + WRITEL(0x0, mfc_regs->e_rc_roi_ctrl); + WRITEL(0x0, mfc_regs->e_picture_tag); - WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); - WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6); - WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6); + WRITEL(0x0, mfc_regs->e_bit_count_enable); + WRITEL(0x0, mfc_regs->e_max_bit_count); + WRITEL(0x0, mfc_regs->e_min_bit_count); - WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); - WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); + WRITEL(0x0, mfc_regs->e_metadata_buffer_addr); + WRITEL(0x0, mfc_regs->e_metadata_buffer_size); mfc_debug_leave(); @@ -774,6 +801,7 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; struct s5p_mfc_enc_params *p = &ctx->enc_params; struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; unsigned int reg = 0; @@ -784,10 +812,10 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) s5p_mfc_set_enc_params(ctx); /* pictype : number of B */ - reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); + reg = READL(mfc_regs->e_gop_config); reg &= ~(0x3 << 16); reg |= ((p->num_b_frame & 0x3) << 16); - WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); + WRITEL(reg, mfc_regs->e_gop_config); /* profile & level */ reg = 0; @@ -795,18 +823,19 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) reg |= ((p_h264->level & 0xFF) << 8); /** profile - 0 ~ 3 */ reg |= p_h264->profile & 0x3F; - WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); + WRITEL(reg, mfc_regs->e_picture_profile); /* rate control config. */ - reg = READL(S5P_FIMV_E_RC_CONFIG_V6); + reg = READL(mfc_regs->e_rc_config); /** macroblock level rate control */ reg &= ~(0x1 << 8); reg |= ((p->rc_mb & 0x1) << 8); - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); + /** frame QP */ reg &= ~(0x3F); reg |= p_h264->rc_frame_qp & 0x3F; - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); /* max & min value of QP */ reg = 0; @@ -814,16 +843,16 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) 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_V6); + WRITEL(reg, mfc_regs->e_rc_qp_bound); /* other QPs */ - WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); + WRITEL(0x0, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_fixed_picture_qp); } /* frame rate */ @@ -831,38 +860,38 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) reg = 0; reg |= ((p->rc_framerate_num & 0xFFFF) << 16); reg |= p->rc_framerate_denom & 0xFFFF; - WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); + WRITEL(reg, mfc_regs->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_V6); + mfc_regs->e_vbv_buffer_size); if (p->rc_frame) - WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); } /* interlace */ reg = 0; reg |= ((p_h264->interlace & 0x1) << 3); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* height */ if (p_h264->interlace) { WRITEL(ctx->img_height >> 1, - S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */ + mfc_regs->e_frame_height); /* 32 align */ /* cropped height */ WRITEL(ctx->img_height >> 1, - S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); + mfc_regs->e_cropped_frame_height); } /* loop filter ctrl */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + reg = READL(mfc_regs->e_h264_options); reg &= ~(0x3 << 1); reg |= ((p_h264->loop_filter_mode & 0x3) << 1); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* loopfilter alpha offset */ if (p_h264->loop_filter_alpha < 0) { @@ -872,7 +901,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) reg = 0x00; reg |= (p_h264->loop_filter_alpha & 0xF); } - WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); + WRITEL(reg, mfc_regs->e_h264_lf_alpha_offset); /* loopfilter beta offset */ if (p_h264->loop_filter_beta < 0) { @@ -882,28 +911,28 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) reg = 0x00; reg |= (p_h264->loop_filter_beta & 0xF); } - WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); + WRITEL(reg, mfc_regs->e_h264_lf_beta_offset); /* entropy coding mode */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + reg = READL(mfc_regs->e_h264_options); reg &= ~(0x1); reg |= p_h264->entropy_mode & 0x1; - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* number of ref. picture */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + reg = READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 7); reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* 8x8 transform enable */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + reg = READL(mfc_regs->e_h264_options); reg &= ~(0x3 << 12); reg |= ((p_h264->_8x8_transform & 0x3) << 12); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* macroblock adaptive scaling features */ - WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6); + WRITEL(0x0, mfc_regs->e_mb_rc_config); if (p->rc_mb) { reg = 0; /** dark region */ @@ -914,92 +943,95 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) 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_V6); + WRITEL(reg, mfc_regs->e_mb_rc_config); } /* aspect ratio VUI */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 5); reg |= ((p_h264->vui_sar & 0x1) << 5); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); - WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6); - WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6); + WRITEL(0x0, mfc_regs->e_aspect_ratio); + WRITEL(0x0, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_extended_sar); } } /* intra picture period for H.264 open GOP */ /* control */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 4); reg |= ((p_h264->open_gop & 0x1) << 4); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); + /* value */ - WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6); + WRITEL(0x0, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_h264_i_period); } /* 'WEIGHTED_BI_PREDICTION' for B is disable */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x3 << 9); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 14); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* ASO */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 6); reg |= ((p_h264->aso & 0x1) << 6); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->e_h264_options); /* hier qp enable */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 8); reg |= ((p_h264->open_gop & 0x1) << 8); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_h264_num_t_layer); /* QP value for each layer */ - for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++) + for (i = 0; i < p_h264->hier_qp_layer && + i < ARRAY_SIZE(p_h264->hier_qp_layer_qp); i++) { WRITEL(p_h264->hier_qp_layer_qp[i], - S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 + - i * 4); + mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_h264_num_t_layer); /* frame packing SEI generation */ - reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); + READL(mfc_regs->e_h264_options); reg &= ~(0x1 << 25); reg |= ((p_h264->sei_frame_packing & 0x1) << 25); - WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_h264_frame_packing_sei_info); } if (p_h264->fmo) { @@ -1009,8 +1041,8 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) 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_V6 + - i * 4); + mfc_regs->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) @@ -1021,10 +1053,10 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) 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_V6); + mfc_regs->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_V6); + mfc_regs->e_h264_fmo_slice_grp_change_rate_minus1); break; default: mfc_err("Unsupported map type for FMO: %d\n", @@ -1035,11 +1067,11 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) } WRITEL(p_h264->fmo_map_type, - S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); + mfc_regs->e_h264_fmo_slice_grp_map_type); WRITEL(p_h264->fmo_slice_grp - 1, - S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); + mfc_regs->e_h264_fmo_num_slice_grp_minus1); } else { - WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); + WRITEL(0, mfc_regs->e_h264_fmo_num_slice_grp_minus1); } mfc_debug_leave(); @@ -1050,6 +1082,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; struct s5p_mfc_enc_params *p = &ctx->enc_params; struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; unsigned int reg = 0; @@ -1059,10 +1092,10 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) s5p_mfc_set_enc_params(ctx); /* pictype : number of B */ - reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); + reg = READL(mfc_regs->e_gop_config); reg &= ~(0x3 << 16); reg |= ((p->num_b_frame & 0x3) << 16); - WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); + WRITEL(reg, mfc_regs->e_gop_config); /* profile & level */ reg = 0; @@ -1070,18 +1103,19 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) reg |= ((p_mpeg4->level & 0xFF) << 8); /** profile - 0 ~ 1 */ reg |= p_mpeg4->profile & 0x3F; - WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); + WRITEL(reg, mfc_regs->e_picture_profile); /* rate control config. */ - reg = READL(S5P_FIMV_E_RC_CONFIG_V6); + reg = READL(mfc_regs->e_rc_config); /** macroblock level rate control */ reg &= ~(0x1 << 8); reg |= ((p->rc_mb & 0x1) << 8); - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); + /** frame QP */ reg &= ~(0x3F); reg |= p_mpeg4->rc_frame_qp & 0x3F; - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); /* max & min value of QP */ reg = 0; @@ -1089,16 +1123,16 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) 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_V6); + WRITEL(reg, mfc_regs->e_rc_qp_bound); /* other QPs */ - WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); + WRITEL(0x0, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_fixed_picture_qp); } /* frame rate */ @@ -1106,21 +1140,21 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) reg = 0; reg |= ((p->rc_framerate_num & 0xFFFF) << 16); reg |= p->rc_framerate_denom & 0xFFFF; - WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); if (p->rc_frame) - WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); } /* Disable HEC */ - WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6); - WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); + WRITEL(0x0, mfc_regs->e_mpeg4_options); + WRITEL(0x0, mfc_regs->e_mpeg4_hec_period); mfc_debug_leave(); @@ -1130,6 +1164,7 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; struct s5p_mfc_enc_params *p = &ctx->enc_params; struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; unsigned int reg = 0; @@ -1142,18 +1177,19 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) reg = 0; /** profile */ reg |= (0x1 << 4); - WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); + WRITEL(reg, mfc_regs->e_picture_profile); /* rate control config. */ - reg = READL(S5P_FIMV_E_RC_CONFIG_V6); + reg = READL(mfc_regs->e_rc_config); /** macroblock level rate control */ reg &= ~(0x1 << 8); reg |= ((p->rc_mb & 0x1) << 8); - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); + /** frame QP */ reg &= ~(0x3F); reg |= p_h263->rc_frame_qp & 0x3F; - WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); + WRITEL(reg, mfc_regs->e_rc_config); /* max & min value of QP */ reg = 0; @@ -1161,16 +1197,16 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) 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_V6); + WRITEL(reg, mfc_regs->e_rc_qp_bound); /* other QPs */ - WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); + WRITEL(0x0, mfc_regs->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_V6); + WRITEL(reg, mfc_regs->e_fixed_picture_qp); } /* frame rate */ @@ -1178,16 +1214,16 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) reg = 0; reg |= ((p->rc_framerate_num & 0xFFFF) << 16); reg |= p->rc_framerate_denom & 0xFFFF; - WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); + WRITEL(reg, mfc_regs->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_V6); + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); if (p->rc_frame) - WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); } mfc_debug_leave(); @@ -1195,10 +1231,104 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) return 0; } +static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) +{ + struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; + struct s5p_mfc_enc_params *p = &ctx->enc_params; + struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8; + unsigned int reg = 0; + unsigned int val = 0; + + mfc_debug_enter(); + + s5p_mfc_set_enc_params(ctx); + + /* pictype : number of B */ + reg = READL(mfc_regs->e_gop_config); + reg &= ~(0x3 << 16); + reg |= ((p->num_b_frame & 0x3) << 16); + WRITEL(reg, mfc_regs->e_gop_config); + + /* profile - 0 ~ 3 */ + reg = p_vp8->profile & 0x3; + WRITEL(reg, mfc_regs->e_picture_profile); + + /* rate control config. */ + reg = READL(mfc_regs->e_rc_config); + /** macroblock level rate control */ + reg &= ~(0x1 << 8); + reg |= ((p->rc_mb & 0x1) << 8); + WRITEL(reg, mfc_regs->e_rc_config); + + /* 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, mfc_regs->e_rc_frame_rate); + } + + /* frame QP */ + reg &= ~(0x7F); + reg |= p_vp8->rc_frame_qp & 0x7F; + WRITEL(reg, mfc_regs->e_rc_config); + + /* other QPs */ + WRITEL(0x0, mfc_regs->e_fixed_picture_qp); + if (!p->rc_frame && !p->rc_mb) { + reg = 0; + reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8); + reg |= p_vp8->rc_frame_qp & 0x7F; + WRITEL(reg, mfc_regs->e_fixed_picture_qp); + } + + /* max QP */ + reg = ((p_vp8->rc_max_qp & 0x7F) << 8); + /* min QP */ + reg |= p_vp8->rc_min_qp & 0x7F; + WRITEL(reg, mfc_regs->e_rc_qp_bound); + + /* vbv buffer size */ + if (p->frame_skip_mode == + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); + + if (p->rc_frame) + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); + } + + /* VP8 specific params */ + reg = 0; + reg |= (p_vp8->imd_4x4 & 0x1) << 10; + switch (p_vp8->num_partitions) { + case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION: + val = 0; + break; + case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS: + val = 2; + break; + case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS: + val = 4; + break; + case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS: + val = 8; + break; + } + reg |= (val & 0xF) << 3; + reg |= (p_vp8->num_ref & 0x2); + WRITEL(reg, mfc_regs->e_vp8_options); + + mfc_debug_leave(); + + return 0; +} + /* Initialize decoding */ -int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; unsigned int reg = 0; int fmo_aso_ctrl = 0; @@ -1206,9 +1336,9 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_CH_SEQ_HEADER_V6); mfc_debug(2, "BUFs: %08x %08x %08x\n", - READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), - READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), - READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6)); + READL(mfc_regs->d_cpb_buffer_addr), + READL(mfc_regs->d_cpb_buffer_addr), + READL(mfc_regs->d_cpb_buffer_addr)); /* FMO_ASO_CTRL - 0: Enable, 1: Disable */ reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6); @@ -1219,8 +1349,14 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) * set to negative value. */ if (ctx->display_delay >= 0) { reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); - WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); + WRITEL(ctx->display_delay, mfc_regs->d_display_delay); + } + + if (IS_MFCV7_PLUS(dev)) { + WRITEL(reg, mfc_regs->d_dec_options); + reg = 0; } + /* Setup loop filter, for decoding this is only valid for MPEG4 */ if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { mfc_debug(2, "Set loop filter to: %d\n", @@ -1231,18 +1367,22 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); - WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); + if (IS_MFCV7_PLUS(dev)) + WRITEL(reg, mfc_regs->d_init_buffer_options); + else + WRITEL(reg, mfc_regs->d_dec_options); /* 0: NV12(CbCr), 1: NV21(CrCb) */ if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) - WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); + WRITEL(0x1, mfc_regs->pixel_format); else - WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); + WRITEL(0x0, mfc_regs->pixel_format); + /* sei parse */ - WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); + WRITEL(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable); - WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); + WRITEL(ctx->inst_no, mfc_regs->instance_id); s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_SEQ_HEADER_V6, NULL); @@ -1253,24 +1393,28 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) 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); + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; + + if (flush) { + dev->curr_ctx = ctx->num; + s5p_mfc_clean_ctx_int_flags(ctx); + WRITEL(ctx->inst_no, mfc_regs->instance_id); + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, + S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); + } } /* Decode a single frame */ -int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, +static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, enum s5p_mfc_decode_arg last_frame) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; - WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); - WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6); + WRITEL(ctx->dec_dst_flag, mfc_regs->d_available_dpb_flag_lower); + WRITEL(ctx->slice_interface & 0x1, mfc_regs->d_slice_if_enable); - WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); + WRITEL(ctx->inst_no, mfc_regs->instance_id); /* Issue different commands to instance basing on whether it * is the last frame or not. */ switch (last_frame) { @@ -1291,9 +1435,10 @@ int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, return 0; } -int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) s5p_mfc_set_enc_params_h264(ctx); @@ -1301,38 +1446,49 @@ int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) s5p_mfc_set_enc_params_mpeg4(ctx); else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) s5p_mfc_set_enc_params_h263(ctx); + else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC) + s5p_mfc_set_enc_params_vp8(ctx); else { mfc_err("Unknown codec for encoding (%x).\n", ctx->codec_mode); return -EINVAL; } - WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); + /* Set stride lengths for v7 & above */ + if (IS_MFCV7_PLUS(dev)) { + WRITEL(ctx->img_width, mfc_regs->e_source_first_plane_stride); + WRITEL(ctx->img_width, mfc_regs->e_source_second_plane_stride); + } + + WRITEL(ctx->inst_no, mfc_regs->instance_id); s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_SEQ_HEADER_V6, NULL); return 0; } -int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; 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++) + for (i = 0; i < ARRAY_SIZE(p_h264->aso_slice_order); i++) { WRITEL(p_h264->aso_slice_order[i], - S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4); + mfc_regs->e_h264_aso_slice_order_0 + i * 4); + } } return 0; } /* Encode a single frame */ -int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; mfc_debug(2, "++\n"); @@ -1343,7 +1499,7 @@ int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) s5p_mfc_set_slice_mode(ctx); - WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); + WRITEL(ctx->inst_no, mfc_regs->instance_id); s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_FRAME_START_V6, NULL); @@ -1359,7 +1515,7 @@ static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) int cnt; spin_lock_irqsave(&dev->condlock, flags); - mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx, + mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx, dev->ctx_work_bits); new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; cnt = 0; @@ -1408,10 +1564,17 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) struct s5p_mfc_buf *temp_vb; unsigned long flags; int last_frame = 0; - unsigned int index; - spin_lock_irqsave(&dev->irqlock, flags); + if (ctx->state == MFCINST_FINISHING) { + last_frame = MFC_DEC_LAST_FRAME; + s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0); + dev->curr_ctx = ctx->num; + s5p_mfc_clean_ctx_int_flags(ctx); + s5p_mfc_decode_one_frame_v6(ctx, last_frame); + return 0; + } + spin_lock_irqsave(&dev->irqlock, flags); /* Frames are being decoded */ if (list_empty(&ctx->src_queue)) { mfc_debug(2, "No src buffers.\n"); @@ -1427,8 +1590,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) 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) { @@ -1452,7 +1613,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) unsigned int src_y_size, src_c_size; */ unsigned int dst_size; - unsigned int index; spin_lock_irqsave(&dev->irqlock, flags); @@ -1473,8 +1633,8 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) 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); + mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr); + mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr); s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); @@ -1487,8 +1647,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) 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_v6(ctx); @@ -1566,22 +1724,6 @@ 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_v6(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_v6(ctx); @@ -1593,7 +1735,7 @@ static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx) } /* Try running an operation on hardware */ -void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) +static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) { struct s5p_mfc_ctx *ctx; int new_ctx; @@ -1626,7 +1768,7 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) 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); + ctx->dst_queue_cnt, ctx->pb_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 */ @@ -1656,6 +1798,9 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) case MFCINST_HEAD_PARSED: ret = s5p_mfc_run_init_dec_buffers(ctx); break; + case MFCINST_FLUSH: + s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag); + break; case MFCINST_RES_CHANGE_INIT: s5p_mfc_run_dec_last_frames(ctx); break; @@ -1688,7 +1833,7 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) case MFCINST_GOT_INST: s5p_mfc_run_init_enc(ctx); break; - case MFCINST_HEAD_PARSED: /* Only for MFC6.x */ + case MFCINST_HEAD_PRODUCED: ret = s5p_mfc_run_init_enc_buffers(ctx); break; default: @@ -1713,7 +1858,7 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) } -void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) +static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) { struct s5p_mfc_buf *b; int i; @@ -1727,170 +1872,411 @@ void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) } } -void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) +static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) { - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6); - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6); + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; + WRITEL(0, mfc_regs->risc2host_command); + WRITEL(0, mfc_regs->risc2host_int); } -void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data, +static void s5p_mfc_write_info_v6(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); + WRITEL(data, (void *)ofs); s5p_mfc_clock_off(); } -unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) +static unsigned int +s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) { - struct s5p_mfc_dev *dev = ctx->dev; int ret; s5p_mfc_clock_on(); - ret = READL(ofs); + ret = READL((void *)ofs); s5p_mfc_clock_off(); return ret; } -int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); + return READL(dev->mfc_regs->d_display_first_plane_addr); } -int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); + return READL(dev->mfc_regs->d_decoded_first_plane_addr); } -int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6); + return READL(dev->mfc_regs->d_display_status); } -int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6); + return READL(dev->mfc_regs->d_decoded_status); } -int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) & + return READL(dev->mfc_regs->d_decoded_frame_type) & S5P_FIMV_DECODE_FRAME_MASK_V6; } -int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx) { - return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) & + struct s5p_mfc_dev *dev = ctx->dev; + return READL(dev->mfc_regs->d_display_frame_type) & S5P_FIMV_DECODE_FRAME_MASK_V6; } -int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6); + return READL(dev->mfc_regs->d_decoded_nal_size); } -int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) & + return READL(dev->mfc_regs->risc2host_command) & S5P_FIMV_RISC2HOST_CMD_MASK; } -int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6); + return READL(dev->mfc_regs->error_code); } -int s5p_mfc_err_dec_v6(unsigned int err) +static int s5p_mfc_err_dec_v6(unsigned int err) { return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6; } -int s5p_mfc_err_dspl_v6(unsigned int err) +static int s5p_mfc_err_dspl_v6(unsigned int err) { return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6; } -int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) -{ - return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); -} - -int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev) -{ - return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); -} - -int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev) -{ - return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6); -} - -int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6); + return READL(dev->mfc_regs->d_display_frame_width); } -int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6); + return READL(dev->mfc_regs->d_display_frame_height); } -int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6); + return READL(dev->mfc_regs->d_min_num_dpb); } -int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6); + return READL(dev->mfc_regs->d_min_num_mv); } -int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6); + return READL(dev->mfc_regs->ret_instance_id); } -int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6); + return READL(dev->mfc_regs->e_num_dpb); } -int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev) { - return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); + return READL(dev->mfc_regs->e_stream_size); } -int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6); + return READL(dev->mfc_regs->e_slice_type); } -int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) +static int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6); + return READL(dev->mfc_regs->e_picture_count); } -unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) +static int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) { - return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6); -} - -unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx) -{ - return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6); -} - -unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx) -{ - return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6); -} - -unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx) -{ - return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6); + struct s5p_mfc_dev *dev = ctx->dev; + return READL(dev->mfc_regs->d_frame_pack_sei_avail); +} + +static int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) +{ + return READL(dev->mfc_regs->d_mvc_num_views); +} + +static int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) +{ + return READL(dev->mfc_regs->d_mvc_view_id); +} + +static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) +{ + return s5p_mfc_read_info_v6(ctx, + (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_top); +} + +static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx) +{ + return s5p_mfc_read_info_v6(ctx, + (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_bot); +} + +static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx) +{ + return s5p_mfc_read_info_v6(ctx, + (unsigned int) ctx->dev->mfc_regs->d_display_crop_info1); +} + +static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx) +{ + return s5p_mfc_read_info_v6(ctx, + (unsigned int) ctx->dev->mfc_regs->d_display_crop_info2); +} + +static struct s5p_mfc_regs mfc_regs; + +/* Initialize registers for MFC v6 onwards */ +const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev) +{ + memset(&mfc_regs, 0, sizeof(mfc_regs)); + +#define S5P_MFC_REG_ADDR(dev, reg) ((dev)->regs_base + (reg)) +#define R(m, r) mfc_regs.m = S5P_MFC_REG_ADDR(dev, r) + /* codec common registers */ + R(risc_on, S5P_FIMV_RISC_ON_V6); + R(risc2host_int, S5P_FIMV_RISC2HOST_INT_V6); + R(host2risc_int, S5P_FIMV_HOST2RISC_INT_V6); + R(risc_base_address, S5P_FIMV_RISC_BASE_ADDRESS_V6); + R(mfc_reset, S5P_FIMV_MFC_RESET_V6); + R(host2risc_command, S5P_FIMV_HOST2RISC_CMD_V6); + R(risc2host_command, S5P_FIMV_RISC2HOST_CMD_V6); + R(firmware_version, S5P_FIMV_FW_VERSION_V6); + R(instance_id, S5P_FIMV_INSTANCE_ID_V6); + R(codec_type, S5P_FIMV_CODEC_TYPE_V6); + R(context_mem_addr, S5P_FIMV_CONTEXT_MEM_ADDR_V6); + R(context_mem_size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); + R(pixel_format, S5P_FIMV_PIXEL_FORMAT_V6); + R(ret_instance_id, S5P_FIMV_RET_INSTANCE_ID_V6); + R(error_code, S5P_FIMV_ERROR_CODE_V6); + + /* decoder registers */ + R(d_crc_ctrl, S5P_FIMV_D_CRC_CTRL_V6); + R(d_dec_options, S5P_FIMV_D_DEC_OPTIONS_V6); + R(d_display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); + R(d_sei_enable, S5P_FIMV_D_SEI_ENABLE_V6); + R(d_min_num_dpb, S5P_FIMV_D_MIN_NUM_DPB_V6); + R(d_min_num_mv, S5P_FIMV_D_MIN_NUM_MV_V6); + R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V6); + R(d_num_dpb, S5P_FIMV_D_NUM_DPB_V6); + R(d_num_mv, S5P_FIMV_D_NUM_MV_V6); + R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6); + R(d_first_plane_dpb_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); + R(d_second_plane_dpb_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); + R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6); + R(d_first_plane_dpb, S5P_FIMV_D_LUMA_DPB_V6); + R(d_second_plane_dpb, S5P_FIMV_D_CHROMA_DPB_V6); + R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V6); + R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); + R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); + R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); + R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); + R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); + R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); + R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V6); + R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6); + R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); + R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); + R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V6); + R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); + R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6); + R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6); + R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V6); + R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V6); + R(d_display_aspect_ratio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6); + R(d_display_extended_ar, S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6); + R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V6); + R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); + R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_CHROMA_ADDR_V6); + R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V6); + R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V6); + R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6); + R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6); + R(d_h264_info, S5P_FIMV_D_H264_INFO_V6); + R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V6); + R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); + + /* encoder registers */ + R(e_frame_width, S5P_FIMV_E_FRAME_WIDTH_V6); + R(e_frame_height, S5P_FIMV_E_FRAME_HEIGHT_V6); + R(e_cropped_frame_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); + R(e_cropped_frame_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); + R(e_frame_crop_offset, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); + R(e_enc_options, S5P_FIMV_E_ENC_OPTIONS_V6); + R(e_picture_profile, S5P_FIMV_E_PICTURE_PROFILE_V6); + R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); + R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); + R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V6); + R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V6); + R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V6); + R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V6); + R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V6); + R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V6); + R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V6); + R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V6); + R(e_num_dpb, S5P_FIMV_E_NUM_DPB_V6); + R(e_luma_dpb, S5P_FIMV_E_LUMA_DPB_V6); + R(e_chroma_dpb, S5P_FIMV_E_CHROMA_DPB_V6); + R(e_me_buffer, S5P_FIMV_E_ME_BUFFER_V6); + R(e_scratch_buffer_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6); + R(e_scratch_buffer_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); + R(e_tmv_buffer0, S5P_FIMV_E_TMV_BUFFER0_V6); + R(e_tmv_buffer1, S5P_FIMV_E_TMV_BUFFER1_V6); + R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); + R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); + R(e_stream_buffer_addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); + R(e_stream_buffer_size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); + R(e_roi_buffer_addr, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); + R(e_param_change, S5P_FIMV_E_PARAM_CHANGE_V6); + R(e_ir_size, S5P_FIMV_E_IR_SIZE_V6); + R(e_gop_config, S5P_FIMV_E_GOP_CONFIG_V6); + R(e_mslice_mode, S5P_FIMV_E_MSLICE_MODE_V6); + R(e_mslice_size_mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6); + R(e_mslice_size_bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); + R(e_frame_insertion, S5P_FIMV_E_FRAME_INSERTION_V6); + R(e_rc_frame_rate, S5P_FIMV_E_RC_FRAME_RATE_V6); + R(e_rc_bit_rate, S5P_FIMV_E_RC_BIT_RATE_V6); + R(e_rc_roi_ctrl, S5P_FIMV_E_RC_ROI_CTRL_V6); + R(e_picture_tag, S5P_FIMV_E_PICTURE_TAG_V6); + R(e_bit_count_enable, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); + R(e_max_bit_count, S5P_FIMV_E_MAX_BIT_COUNT_V6); + R(e_min_bit_count, S5P_FIMV_E_MIN_BIT_COUNT_V6); + R(e_metadata_buffer_addr, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); + R(e_metadata_buffer_size, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); + R(e_encoded_source_first_plane_addr, + S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); + R(e_encoded_source_second_plane_addr, + S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); + R(e_stream_size, S5P_FIMV_E_STREAM_SIZE_V6); + R(e_slice_type, S5P_FIMV_E_SLICE_TYPE_V6); + R(e_picture_count, S5P_FIMV_E_PICTURE_COUNT_V6); + R(e_ret_picture_tag, S5P_FIMV_E_RET_PICTURE_TAG_V6); + R(e_recon_luma_dpb_addr, S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); + R(e_recon_chroma_dpb_addr, S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); + R(e_mpeg4_options, S5P_FIMV_E_MPEG4_OPTIONS_V6); + R(e_mpeg4_hec_period, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); + R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V6); + R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V6); + R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V6); + R(e_h264_lf_alpha_offset, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); + R(e_h264_lf_beta_offset, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); + R(e_h264_i_period, S5P_FIMV_E_H264_I_PERIOD_V6); + R(e_h264_fmo_slice_grp_map_type, + S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); + R(e_h264_fmo_num_slice_grp_minus1, + S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); + R(e_h264_fmo_slice_grp_change_dir, + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6); + R(e_h264_fmo_slice_grp_change_rate_minus1, + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6); + R(e_h264_fmo_run_length_minus1_0, + S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6); + R(e_h264_aso_slice_order_0, S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6); + R(e_h264_num_t_layer, S5P_FIMV_E_H264_NUM_T_LAYER_V6); + R(e_h264_hierarchical_qp_layer0, + S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6); + R(e_h264_frame_packing_sei_info, + S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6); + + if (!IS_MFCV7_PLUS(dev)) + goto done; + + /* Initialize registers used in MFC v7+ */ + R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); + R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); + R(e_source_third_plane_addr, S5P_FIMV_E_SOURCE_THIRD_ADDR_V7); + R(e_source_first_plane_stride, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); + R(e_source_second_plane_stride, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); + R(e_source_third_plane_stride, S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7); + R(e_encoded_source_first_plane_addr, + S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); + R(e_encoded_source_second_plane_addr, + S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); + R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7); + + if (!IS_MFCV8(dev)) + goto done; + + /* Initialize registers used in MFC v8 only. + * Also, over-write the registers which have + * a different offset for MFC v8. */ + R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V8); + R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V8); + R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V8); + R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V8); + R(d_first_plane_dpb_size, S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8); + R(d_second_plane_dpb_size, S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8); + R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8); + R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8); + R(d_first_plane_dpb_stride_size, + S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8); + R(d_second_plane_dpb_stride_size, + S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8); + R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V8); + R(d_num_mv, S5P_FIMV_D_NUM_MV_V8); + R(d_first_plane_dpb, S5P_FIMV_D_FIRST_PLANE_DPB_V8); + R(d_second_plane_dpb, S5P_FIMV_D_SECOND_PLANE_DPB_V8); + R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V8); + R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8); + R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8); + R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V8); + R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8); + R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8); + R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8); + R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8); + R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V8); + R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V8); + R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V8); + R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8); + R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V8); + R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8); + R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8); + R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8); + R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V8); + R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V8); + R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8); + R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8); + R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V8); + R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V8); + + /* encoder registers */ + R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V8); + R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V8); + R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V8); + R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V8); + R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V8); + R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V8); + R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V8); + R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V8); + R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V8); + R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V8); + R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V8); + R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V8); + R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8); + +done: + return &mfc_regs; +#undef S5P_MFC_REG_ADDR +#undef R } /* Initialize opr function pointers for MFC v6 */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h index ab164efa127..80558484bb4 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h @@ -40,11 +40,6 @@ #define FRAME_DELTA_H264_H263 1 #define TIGHT_CBR_MAX 10 -/* Definitions for shared memory compatibility */ -#define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 -#define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 -#define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 -#define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 - struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void); +const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev); #endif /* S5P_MFC_OPR_V6_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 2895333866f..11d5f1dada3 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c @@ -46,23 +46,10 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) ret = clk_prepare(pm->clock_gate); if (ret) { - mfc_err("Failed to preapre clock-gating control\n"); + mfc_err("Failed to prepare clock-gating control\n"); goto err_p_ip_clk; } - pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name); - if (IS_ERR(pm->clock)) { - mfc_err("Failed to get MFC clock\n"); - ret = PTR_ERR(pm->clock); - goto err_g_ip_clk_2; - } - - ret = clk_prepare(pm->clock); - if (ret) { - mfc_err("Failed to prepare MFC clock\n"); - goto err_p_ip_clk_2; - } - atomic_set(&pm->power, 0); #ifdef CONFIG_PM_RUNTIME pm->device = &dev->plat_dev->dev; @@ -72,10 +59,6 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) atomic_set(&clk_ref, 0); #endif return 0; -err_p_ip_clk_2: - clk_put(pm->clock); -err_g_ip_clk_2: - clk_unprepare(pm->clock_gate); err_p_ip_clk: clk_put(pm->clock_gate); err_g_ip_clk: @@ -86,8 +69,6 @@ void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) { clk_unprepare(pm->clock_gate); clk_put(pm->clock_gate); - clk_unprepare(pm->clock); - clk_put(pm->clock); #ifdef CONFIG_PM_RUNTIME pm_runtime_disable(pm->device); #endif @@ -98,7 +79,7 @@ int s5p_mfc_clock_on(void) int ret; #ifdef CLK_DEBUG atomic_inc(&clk_ref); - mfc_debug(3, "+ %d", atomic_read(&clk_ref)); + mfc_debug(3, "+ %d\n", atomic_read(&clk_ref)); #endif ret = clk_enable(pm->clock_gate); return ret; @@ -108,7 +89,7 @@ void s5p_mfc_clock_off(void) { #ifdef CLK_DEBUG atomic_dec(&clk_ref); - mfc_debug(3, "- %d", atomic_read(&clk_ref)); + mfc_debug(3, "- %d\n", atomic_read(&clk_ref)); #endif clk_disable(pm->clock_gate); } |
