1*43ecec16SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0-only
2*43ecec16SMauro Carvalho Chehab /*
3*43ecec16SMauro Carvalho Chehab  * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c
4*43ecec16SMauro Carvalho Chehab  *
5*43ecec16SMauro Carvalho Chehab  * Samsung MFC (Multi Function Codec - FIMV) driver
6*43ecec16SMauro Carvalho Chehab  * This file contains hw related functions.
7*43ecec16SMauro Carvalho Chehab  *
8*43ecec16SMauro Carvalho Chehab  * Kamil Debski, Copyright (c) 2011 Samsung Electronics
9*43ecec16SMauro Carvalho Chehab  * http://www.samsung.com/
10*43ecec16SMauro Carvalho Chehab  */
11*43ecec16SMauro Carvalho Chehab 
12*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_common.h"
13*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_cmd.h"
14*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_ctrl.h"
15*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_debug.h"
16*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_intr.h"
17*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_pm.h"
18*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_opr.h"
19*43ecec16SMauro Carvalho Chehab #include "s5p_mfc_opr_v5.h"
20*43ecec16SMauro Carvalho Chehab #include <asm/cacheflush.h>
21*43ecec16SMauro Carvalho Chehab #include <linux/delay.h>
22*43ecec16SMauro Carvalho Chehab #include <linux/dma-mapping.h>
23*43ecec16SMauro Carvalho Chehab #include <linux/err.h>
24*43ecec16SMauro Carvalho Chehab #include <linux/firmware.h>
25*43ecec16SMauro Carvalho Chehab #include <linux/io.h>
26*43ecec16SMauro Carvalho Chehab #include <linux/jiffies.h>
27*43ecec16SMauro Carvalho Chehab #include <linux/mm.h>
28*43ecec16SMauro Carvalho Chehab #include <linux/sched.h>
29*43ecec16SMauro Carvalho Chehab 
30*43ecec16SMauro Carvalho Chehab #define OFFSETA(x)		(((x) - dev->dma_base[BANK_L_CTX]) >> MFC_OFFSET_SHIFT)
31*43ecec16SMauro Carvalho Chehab #define OFFSETB(x)		(((x) - dev->dma_base[BANK_R_CTX]) >> MFC_OFFSET_SHIFT)
32*43ecec16SMauro Carvalho Chehab 
33*43ecec16SMauro Carvalho Chehab /* Allocate temporary buffers for decoding */
s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx * ctx)34*43ecec16SMauro Carvalho Chehab static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
35*43ecec16SMauro Carvalho Chehab {
36*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
37*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
38*43ecec16SMauro Carvalho Chehab 	int ret;
39*43ecec16SMauro Carvalho Chehab 
40*43ecec16SMauro Carvalho Chehab 	ctx->dsc.size = buf_size->dsc;
41*43ecec16SMauro Carvalho Chehab 	ret =  s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->dsc);
42*43ecec16SMauro Carvalho Chehab 	if (ret) {
43*43ecec16SMauro Carvalho Chehab 		mfc_err("Failed to allocate temporary buffer\n");
44*43ecec16SMauro Carvalho Chehab 		return ret;
45*43ecec16SMauro Carvalho Chehab 	}
46*43ecec16SMauro Carvalho Chehab 
47*43ecec16SMauro Carvalho Chehab 	BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
48*43ecec16SMauro Carvalho Chehab 	memset(ctx->dsc.virt, 0, ctx->dsc.size);
49*43ecec16SMauro Carvalho Chehab 	wmb();
50*43ecec16SMauro Carvalho Chehab 	return 0;
51*43ecec16SMauro Carvalho Chehab }
52*43ecec16SMauro Carvalho Chehab 
53*43ecec16SMauro Carvalho Chehab 
54*43ecec16SMauro Carvalho Chehab /* Release temporary buffers for decoding */
s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx * ctx)55*43ecec16SMauro Carvalho Chehab static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
56*43ecec16SMauro Carvalho Chehab {
57*43ecec16SMauro Carvalho Chehab 	s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc);
58*43ecec16SMauro Carvalho Chehab }
59*43ecec16SMauro Carvalho Chehab 
60*43ecec16SMauro Carvalho Chehab /* Allocate codec buffers */
s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx * ctx)61*43ecec16SMauro Carvalho Chehab static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
62*43ecec16SMauro Carvalho Chehab {
63*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
64*43ecec16SMauro Carvalho Chehab 	unsigned int enc_ref_y_size = 0;
65*43ecec16SMauro Carvalho Chehab 	unsigned int enc_ref_c_size = 0;
66*43ecec16SMauro Carvalho Chehab 	unsigned int guard_width, guard_height;
67*43ecec16SMauro Carvalho Chehab 	int ret;
68*43ecec16SMauro Carvalho Chehab 
69*43ecec16SMauro Carvalho Chehab 	if (ctx->type == MFCINST_DECODER) {
70*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
71*43ecec16SMauro Carvalho Chehab 			  ctx->luma_size, ctx->chroma_size, ctx->mv_size);
72*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
73*43ecec16SMauro Carvalho Chehab 	} else if (ctx->type == MFCINST_ENCODER) {
74*43ecec16SMauro Carvalho Chehab 		enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
75*43ecec16SMauro Carvalho Chehab 			* ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
76*43ecec16SMauro Carvalho Chehab 		enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
77*43ecec16SMauro Carvalho Chehab 
78*43ecec16SMauro Carvalho Chehab 		if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
79*43ecec16SMauro Carvalho Chehab 			enc_ref_c_size = ALIGN(ctx->img_width,
80*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_NV12MT_HALIGN)
81*43ecec16SMauro Carvalho Chehab 						* ALIGN(ctx->img_height >> 1,
82*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_NV12MT_VALIGN);
83*43ecec16SMauro Carvalho Chehab 			enc_ref_c_size = ALIGN(enc_ref_c_size,
84*43ecec16SMauro Carvalho Chehab 							S5P_FIMV_NV12MT_SALIGN);
85*43ecec16SMauro Carvalho Chehab 		} else {
86*43ecec16SMauro Carvalho Chehab 			guard_width = ALIGN(ctx->img_width + 16,
87*43ecec16SMauro Carvalho Chehab 							S5P_FIMV_NV12MT_HALIGN);
88*43ecec16SMauro Carvalho Chehab 			guard_height = ALIGN((ctx->img_height >> 1) + 4,
89*43ecec16SMauro Carvalho Chehab 							S5P_FIMV_NV12MT_VALIGN);
90*43ecec16SMauro Carvalho Chehab 			enc_ref_c_size = ALIGN(guard_width * guard_height,
91*43ecec16SMauro Carvalho Chehab 					       S5P_FIMV_NV12MT_SALIGN);
92*43ecec16SMauro Carvalho Chehab 		}
93*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "recon luma size: %d chroma size: %d\n",
94*43ecec16SMauro Carvalho Chehab 			  enc_ref_y_size, enc_ref_c_size);
95*43ecec16SMauro Carvalho Chehab 	} else {
96*43ecec16SMauro Carvalho Chehab 		return -EINVAL;
97*43ecec16SMauro Carvalho Chehab 	}
98*43ecec16SMauro Carvalho Chehab 	/* Codecs have different memory requirements */
99*43ecec16SMauro Carvalho Chehab 	switch (ctx->codec_mode) {
100*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H264_DEC:
101*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size =
102*43ecec16SMauro Carvalho Chehab 		    ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
103*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_DEC_VERT_NB_MV_SIZE,
104*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_DEC_BUF_ALIGN);
105*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size;
106*43ecec16SMauro Carvalho Chehab 		break;
107*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG4_DEC:
108*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size =
109*43ecec16SMauro Carvalho Chehab 		    ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
110*43ecec16SMauro Carvalho Chehab 				     S5P_FIMV_DEC_UPNB_MV_SIZE +
111*43ecec16SMauro Carvalho Chehab 				     S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
112*43ecec16SMauro Carvalho Chehab 				     S5P_FIMV_DEC_STX_PARSER_SIZE +
113*43ecec16SMauro Carvalho Chehab 				     S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
114*43ecec16SMauro Carvalho Chehab 				     S5P_FIMV_DEC_BUF_ALIGN);
115*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = 0;
116*43ecec16SMauro Carvalho Chehab 		break;
117*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_VC1RCV_DEC:
118*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_VC1_DEC:
119*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size =
120*43ecec16SMauro Carvalho Chehab 		    ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
121*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_UPNB_MV_SIZE +
122*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
123*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_NB_DCAC_SIZE +
124*43ecec16SMauro Carvalho Chehab 			     3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
125*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_BUF_ALIGN);
126*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = 0;
127*43ecec16SMauro Carvalho Chehab 		break;
128*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG2_DEC:
129*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size = 0;
130*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = 0;
131*43ecec16SMauro Carvalho Chehab 		break;
132*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H263_DEC:
133*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size =
134*43ecec16SMauro Carvalho Chehab 		    ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
135*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_UPNB_MV_SIZE +
136*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
137*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_NB_DCAC_SIZE,
138*43ecec16SMauro Carvalho Chehab 			     S5P_FIMV_DEC_BUF_ALIGN);
139*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = 0;
140*43ecec16SMauro Carvalho Chehab 		break;
141*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H264_ENC:
142*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size = (enc_ref_y_size * 2) +
143*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_UPMV_SIZE +
144*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_COLFLG_SIZE +
145*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_INTRAMD_SIZE +
146*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_NBORINFO_SIZE;
147*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = (enc_ref_y_size * 2) +
148*43ecec16SMauro Carvalho Chehab 				   (enc_ref_c_size * 4) +
149*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_INTRAPRED_SIZE;
150*43ecec16SMauro Carvalho Chehab 		break;
151*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG4_ENC:
152*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size = (enc_ref_y_size * 2) +
153*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_UPMV_SIZE +
154*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_COLFLG_SIZE +
155*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_ACDCCOEF_SIZE;
156*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = (enc_ref_y_size * 2) +
157*43ecec16SMauro Carvalho Chehab 				   (enc_ref_c_size * 4);
158*43ecec16SMauro Carvalho Chehab 		break;
159*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H263_ENC:
160*43ecec16SMauro Carvalho Chehab 		ctx->bank1.size = (enc_ref_y_size * 2) +
161*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_UPMV_SIZE +
162*43ecec16SMauro Carvalho Chehab 				   S5P_FIMV_ENC_ACDCCOEF_SIZE;
163*43ecec16SMauro Carvalho Chehab 		ctx->bank2.size = (enc_ref_y_size * 2) +
164*43ecec16SMauro Carvalho Chehab 				   (enc_ref_c_size * 4);
165*43ecec16SMauro Carvalho Chehab 		break;
166*43ecec16SMauro Carvalho Chehab 	default:
167*43ecec16SMauro Carvalho Chehab 		break;
168*43ecec16SMauro Carvalho Chehab 	}
169*43ecec16SMauro Carvalho Chehab 	/* Allocate only if memory from bank 1 is necessary */
170*43ecec16SMauro Carvalho Chehab 	if (ctx->bank1.size > 0) {
171*43ecec16SMauro Carvalho Chehab 
172*43ecec16SMauro Carvalho Chehab 		ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1);
173*43ecec16SMauro Carvalho Chehab 		if (ret) {
174*43ecec16SMauro Carvalho Chehab 			mfc_err("Failed to allocate Bank1 temporary buffer\n");
175*43ecec16SMauro Carvalho Chehab 			return ret;
176*43ecec16SMauro Carvalho Chehab 		}
177*43ecec16SMauro Carvalho Chehab 		BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
178*43ecec16SMauro Carvalho Chehab 	}
179*43ecec16SMauro Carvalho Chehab 	/* Allocate only if memory from bank 2 is necessary */
180*43ecec16SMauro Carvalho Chehab 	if (ctx->bank2.size > 0) {
181*43ecec16SMauro Carvalho Chehab 		ret = s5p_mfc_alloc_priv_buf(dev, BANK_R_CTX, &ctx->bank2);
182*43ecec16SMauro Carvalho Chehab 		if (ret) {
183*43ecec16SMauro Carvalho Chehab 			mfc_err("Failed to allocate Bank2 temporary buffer\n");
184*43ecec16SMauro Carvalho Chehab 			s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
185*43ecec16SMauro Carvalho Chehab 			return ret;
186*43ecec16SMauro Carvalho Chehab 		}
187*43ecec16SMauro Carvalho Chehab 		BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
188*43ecec16SMauro Carvalho Chehab 	}
189*43ecec16SMauro Carvalho Chehab 	return 0;
190*43ecec16SMauro Carvalho Chehab }
191*43ecec16SMauro Carvalho Chehab 
192*43ecec16SMauro Carvalho Chehab /* Release buffers allocated for codec */
s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx * ctx)193*43ecec16SMauro Carvalho Chehab static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
194*43ecec16SMauro Carvalho Chehab {
195*43ecec16SMauro Carvalho Chehab 	s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
196*43ecec16SMauro Carvalho Chehab 	s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2);
197*43ecec16SMauro Carvalho Chehab }
198*43ecec16SMauro Carvalho Chehab 
199*43ecec16SMauro Carvalho Chehab /* Allocate memory for instance data buffer */
s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx * ctx)200*43ecec16SMauro Carvalho Chehab static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
201*43ecec16SMauro Carvalho Chehab {
202*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
203*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
204*43ecec16SMauro Carvalho Chehab 	int ret;
205*43ecec16SMauro Carvalho Chehab 
206*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
207*43ecec16SMauro Carvalho Chehab 		ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
208*43ecec16SMauro Carvalho Chehab 		ctx->ctx.size = buf_size->h264_ctx;
209*43ecec16SMauro Carvalho Chehab 	else
210*43ecec16SMauro Carvalho Chehab 		ctx->ctx.size = buf_size->non_h264_ctx;
211*43ecec16SMauro Carvalho Chehab 
212*43ecec16SMauro Carvalho Chehab 	ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);
213*43ecec16SMauro Carvalho Chehab 	if (ret) {
214*43ecec16SMauro Carvalho Chehab 		mfc_err("Failed to allocate instance buffer\n");
215*43ecec16SMauro Carvalho Chehab 		return ret;
216*43ecec16SMauro Carvalho Chehab 	}
217*43ecec16SMauro Carvalho Chehab 	ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
218*43ecec16SMauro Carvalho Chehab 
219*43ecec16SMauro Carvalho Chehab 	/* Zero content of the allocated memory */
220*43ecec16SMauro Carvalho Chehab 	memset(ctx->ctx.virt, 0, ctx->ctx.size);
221*43ecec16SMauro Carvalho Chehab 	wmb();
222*43ecec16SMauro Carvalho Chehab 
223*43ecec16SMauro Carvalho Chehab 	/* Initialize shared memory */
224*43ecec16SMauro Carvalho Chehab 	ctx->shm.size = buf_size->shm;
225*43ecec16SMauro Carvalho Chehab 	ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->shm);
226*43ecec16SMauro Carvalho Chehab 	if (ret) {
227*43ecec16SMauro Carvalho Chehab 		mfc_err("Failed to allocate shared memory buffer\n");
228*43ecec16SMauro Carvalho Chehab 		s5p_mfc_release_priv_buf(dev, &ctx->ctx);
229*43ecec16SMauro Carvalho Chehab 		return ret;
230*43ecec16SMauro Carvalho Chehab 	}
231*43ecec16SMauro Carvalho Chehab 
232*43ecec16SMauro Carvalho Chehab 	/* shared memory offset only keeps the offset from base (port a) */
233*43ecec16SMauro Carvalho Chehab 	ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK_L_CTX];
234*43ecec16SMauro Carvalho Chehab 	BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
235*43ecec16SMauro Carvalho Chehab 
236*43ecec16SMauro Carvalho Chehab 	memset(ctx->shm.virt, 0, buf_size->shm);
237*43ecec16SMauro Carvalho Chehab 	wmb();
238*43ecec16SMauro Carvalho Chehab 	return 0;
239*43ecec16SMauro Carvalho Chehab }
240*43ecec16SMauro Carvalho Chehab 
241*43ecec16SMauro Carvalho Chehab /* Release instance buffer */
s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx * ctx)242*43ecec16SMauro Carvalho Chehab static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
243*43ecec16SMauro Carvalho Chehab {
244*43ecec16SMauro Carvalho Chehab 	s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);
245*43ecec16SMauro Carvalho Chehab 	s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm);
246*43ecec16SMauro Carvalho Chehab }
247*43ecec16SMauro Carvalho Chehab 
s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev * dev)248*43ecec16SMauro Carvalho Chehab static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
249*43ecec16SMauro Carvalho Chehab {
250*43ecec16SMauro Carvalho Chehab 	/* NOP */
251*43ecec16SMauro Carvalho Chehab 
252*43ecec16SMauro Carvalho Chehab 	return 0;
253*43ecec16SMauro Carvalho Chehab }
254*43ecec16SMauro Carvalho Chehab 
s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev * dev)255*43ecec16SMauro Carvalho Chehab static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
256*43ecec16SMauro Carvalho Chehab {
257*43ecec16SMauro Carvalho Chehab 	/* NOP */
258*43ecec16SMauro Carvalho Chehab }
259*43ecec16SMauro Carvalho Chehab 
s5p_mfc_write_info_v5(struct s5p_mfc_ctx * ctx,unsigned int data,unsigned int ofs)260*43ecec16SMauro Carvalho Chehab static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
261*43ecec16SMauro Carvalho Chehab 			unsigned int ofs)
262*43ecec16SMauro Carvalho Chehab {
263*43ecec16SMauro Carvalho Chehab 	*(u32 *)(ctx->shm.virt + ofs) = data;
264*43ecec16SMauro Carvalho Chehab 	wmb();
265*43ecec16SMauro Carvalho Chehab }
266*43ecec16SMauro Carvalho Chehab 
s5p_mfc_read_info_v5(struct s5p_mfc_ctx * ctx,unsigned long ofs)267*43ecec16SMauro Carvalho Chehab static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
268*43ecec16SMauro Carvalho Chehab 				unsigned long ofs)
269*43ecec16SMauro Carvalho Chehab {
270*43ecec16SMauro Carvalho Chehab 	rmb();
271*43ecec16SMauro Carvalho Chehab 	return *(u32 *)(ctx->shm.virt + ofs);
272*43ecec16SMauro Carvalho Chehab }
273*43ecec16SMauro Carvalho Chehab 
s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx * ctx)274*43ecec16SMauro Carvalho Chehab static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
275*43ecec16SMauro Carvalho Chehab {
276*43ecec16SMauro Carvalho Chehab 	unsigned int guard_width, guard_height;
277*43ecec16SMauro Carvalho Chehab 
278*43ecec16SMauro Carvalho Chehab 	ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
279*43ecec16SMauro Carvalho Chehab 	ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
280*43ecec16SMauro Carvalho Chehab 	mfc_debug(2,
281*43ecec16SMauro Carvalho Chehab 		"SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
282*43ecec16SMauro Carvalho Chehab 		ctx->img_width,	ctx->img_height, ctx->buf_width,
283*43ecec16SMauro Carvalho Chehab 		ctx->buf_height);
284*43ecec16SMauro Carvalho Chehab 
285*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
286*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
287*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_DEC_BUF_ALIGN);
288*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size = ALIGN(ctx->buf_width *
289*43ecec16SMauro Carvalho Chehab 				ALIGN((ctx->img_height >> 1),
290*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_NV12MT_VALIGN),
291*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_DEC_BUF_ALIGN);
292*43ecec16SMauro Carvalho Chehab 		ctx->mv_size = ALIGN(ctx->buf_width *
293*43ecec16SMauro Carvalho Chehab 				ALIGN((ctx->buf_height >> 2),
294*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_NV12MT_VALIGN),
295*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_DEC_BUF_ALIGN);
296*43ecec16SMauro Carvalho Chehab 	} else {
297*43ecec16SMauro Carvalho Chehab 		guard_width =
298*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
299*43ecec16SMauro Carvalho Chehab 		guard_height =
300*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
301*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(guard_width * guard_height,
302*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_DEC_BUF_ALIGN);
303*43ecec16SMauro Carvalho Chehab 
304*43ecec16SMauro Carvalho Chehab 		guard_width =
305*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
306*43ecec16SMauro Carvalho Chehab 		guard_height =
307*43ecec16SMauro Carvalho Chehab 			ALIGN((ctx->img_height >> 1) + 4,
308*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_NV12MT_VALIGN);
309*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size = ALIGN(guard_width * guard_height,
310*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_DEC_BUF_ALIGN);
311*43ecec16SMauro Carvalho Chehab 
312*43ecec16SMauro Carvalho Chehab 		ctx->mv_size = 0;
313*43ecec16SMauro Carvalho Chehab 	}
314*43ecec16SMauro Carvalho Chehab }
315*43ecec16SMauro Carvalho Chehab 
s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx * ctx)316*43ecec16SMauro Carvalho Chehab static void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
317*43ecec16SMauro Carvalho Chehab {
318*43ecec16SMauro Carvalho Chehab 	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
319*43ecec16SMauro Carvalho Chehab 		ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
320*43ecec16SMauro Carvalho Chehab 
321*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
322*43ecec16SMauro Carvalho Chehab 			* ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
323*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
324*43ecec16SMauro Carvalho Chehab 			* ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
325*43ecec16SMauro Carvalho Chehab 
326*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
327*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size =
328*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
329*43ecec16SMauro Carvalho Chehab 	} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
330*43ecec16SMauro Carvalho Chehab 		ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
331*43ecec16SMauro Carvalho Chehab 
332*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
333*43ecec16SMauro Carvalho Chehab 			* ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
334*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size =
335*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
336*43ecec16SMauro Carvalho Chehab 			* ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
337*43ecec16SMauro Carvalho Chehab 
338*43ecec16SMauro Carvalho Chehab 		ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
339*43ecec16SMauro Carvalho Chehab 		ctx->chroma_size =
340*43ecec16SMauro Carvalho Chehab 			ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
341*43ecec16SMauro Carvalho Chehab 	}
342*43ecec16SMauro Carvalho Chehab }
343*43ecec16SMauro Carvalho Chehab 
344*43ecec16SMauro Carvalho Chehab /* Set registers for decoding temporary buffers */
s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx * ctx)345*43ecec16SMauro Carvalho Chehab static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
346*43ecec16SMauro Carvalho Chehab {
347*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
348*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
349*43ecec16SMauro Carvalho Chehab 
350*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
351*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
352*43ecec16SMauro Carvalho Chehab }
353*43ecec16SMauro Carvalho Chehab 
354*43ecec16SMauro Carvalho Chehab /* Set registers for shared buffer */
s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx * ctx)355*43ecec16SMauro Carvalho Chehab static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
356*43ecec16SMauro Carvalho Chehab {
357*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
358*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
359*43ecec16SMauro Carvalho Chehab }
360*43ecec16SMauro Carvalho Chehab 
361*43ecec16SMauro Carvalho Chehab /* Set registers for decoding stream buffer */
s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx * ctx,int buf_addr,unsigned int start_num_byte,unsigned int buf_size)362*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
363*43ecec16SMauro Carvalho Chehab 		int buf_addr, unsigned int start_num_byte,
364*43ecec16SMauro Carvalho Chehab 		unsigned int buf_size)
365*43ecec16SMauro Carvalho Chehab {
366*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
367*43ecec16SMauro Carvalho Chehab 
368*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
369*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
370*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
371*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
372*43ecec16SMauro Carvalho Chehab 	return 0;
373*43ecec16SMauro Carvalho Chehab }
374*43ecec16SMauro Carvalho Chehab 
375*43ecec16SMauro Carvalho Chehab /* Set decoding frame buffer */
s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx * ctx)376*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
377*43ecec16SMauro Carvalho Chehab {
378*43ecec16SMauro Carvalho Chehab 	unsigned int frame_size_lu, i;
379*43ecec16SMauro Carvalho Chehab 	unsigned int frame_size_ch, frame_size_mv;
380*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
381*43ecec16SMauro Carvalho Chehab 	unsigned int dpb;
382*43ecec16SMauro Carvalho Chehab 	size_t buf_addr1, buf_addr2;
383*43ecec16SMauro Carvalho Chehab 	int buf_size1, buf_size2;
384*43ecec16SMauro Carvalho Chehab 
385*43ecec16SMauro Carvalho Chehab 	buf_addr1 = ctx->bank1.dma;
386*43ecec16SMauro Carvalho Chehab 	buf_size1 = ctx->bank1.size;
387*43ecec16SMauro Carvalho Chehab 	buf_addr2 = ctx->bank2.dma;
388*43ecec16SMauro Carvalho Chehab 	buf_size2 = ctx->bank2.size;
389*43ecec16SMauro Carvalho Chehab 	dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
390*43ecec16SMauro Carvalho Chehab 						~S5P_FIMV_DPB_COUNT_MASK;
391*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->total_dpb_count | dpb,
392*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
393*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_shared_buffer(ctx);
394*43ecec16SMauro Carvalho Chehab 	switch (ctx->codec_mode) {
395*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H264_DEC:
396*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
397*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_H264_VERT_NB_MV_ADR);
398*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
399*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
400*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
401*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
402*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
403*43ecec16SMauro Carvalho Chehab 		break;
404*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG4_DEC:
405*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
406*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
407*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
408*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
409*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
410*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
411*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
412*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
413*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
414*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
415*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
416*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
417*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
418*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
419*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
420*43ecec16SMauro Carvalho Chehab 		break;
421*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H263_DEC:
422*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
423*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
424*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
425*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
426*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
427*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
428*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
429*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
430*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
431*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
432*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
433*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
434*43ecec16SMauro Carvalho Chehab 		break;
435*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_VC1_DEC:
436*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_VC1RCV_DEC:
437*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
438*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
439*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
440*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
441*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
442*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
443*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
444*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
445*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
446*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
447*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
448*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
449*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
450*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
451*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
452*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
453*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
454*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
455*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
456*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
457*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
458*43ecec16SMauro Carvalho Chehab 		break;
459*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG2_DEC:
460*43ecec16SMauro Carvalho Chehab 		break;
461*43ecec16SMauro Carvalho Chehab 	default:
462*43ecec16SMauro Carvalho Chehab 		mfc_err("Unknown codec for decoding (%x)\n",
463*43ecec16SMauro Carvalho Chehab 			ctx->codec_mode);
464*43ecec16SMauro Carvalho Chehab 		return -EINVAL;
465*43ecec16SMauro Carvalho Chehab 	}
466*43ecec16SMauro Carvalho Chehab 	frame_size_lu = ctx->luma_size;
467*43ecec16SMauro Carvalho Chehab 	frame_size_ch = ctx->chroma_size;
468*43ecec16SMauro Carvalho Chehab 	frame_size_mv = ctx->mv_size;
469*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size_lu, frame_size_ch,
470*43ecec16SMauro Carvalho Chehab 								frame_size_mv);
471*43ecec16SMauro Carvalho Chehab 	for (i = 0; i < ctx->total_dpb_count; i++) {
472*43ecec16SMauro Carvalho Chehab 		/* Bank2 */
473*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "Luma %d: %zx\n", i,
474*43ecec16SMauro Carvalho Chehab 					ctx->dst_bufs[i].cookie.raw.luma);
475*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
476*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_DEC_LUMA_ADR + i * 4);
477*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "\tChroma %d: %zx\n", i,
478*43ecec16SMauro Carvalho Chehab 					ctx->dst_bufs[i].cookie.raw.chroma);
479*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
480*43ecec16SMauro Carvalho Chehab 					       S5P_FIMV_DEC_CHROMA_ADR + i * 4);
481*43ecec16SMauro Carvalho Chehab 		if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
482*43ecec16SMauro Carvalho Chehab 			mfc_debug(2, "\tBuf2: %zx, size: %d\n",
483*43ecec16SMauro Carvalho Chehab 							buf_addr2, buf_size2);
484*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
485*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_H264_MV_ADR + i * 4);
486*43ecec16SMauro Carvalho Chehab 			buf_addr2 += frame_size_mv;
487*43ecec16SMauro Carvalho Chehab 			buf_size2 -= frame_size_mv;
488*43ecec16SMauro Carvalho Chehab 		}
489*43ecec16SMauro Carvalho Chehab 	}
490*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Buf1: %zu, buf_size1: %d\n", buf_addr1, buf_size1);
491*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
492*43ecec16SMauro Carvalho Chehab 			buf_size1,  buf_size2, ctx->total_dpb_count);
493*43ecec16SMauro Carvalho Chehab 	if (buf_size1 < 0 || buf_size2 < 0) {
494*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "Not enough memory has been allocated\n");
495*43ecec16SMauro Carvalho Chehab 		return -ENOMEM;
496*43ecec16SMauro Carvalho Chehab 	}
497*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, frame_size_lu, ALLOC_LUMA_DPB_SIZE);
498*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
499*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
500*43ecec16SMauro Carvalho Chehab 		s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
501*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
502*43ecec16SMauro Carvalho Chehab 					<< S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
503*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_SI_CH0_INST_ID);
504*43ecec16SMauro Carvalho Chehab 	return 0;
505*43ecec16SMauro Carvalho Chehab }
506*43ecec16SMauro Carvalho Chehab 
507*43ecec16SMauro Carvalho Chehab /* Set registers for encoding stream buffer */
s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx * ctx,unsigned long addr,unsigned int size)508*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
509*43ecec16SMauro Carvalho Chehab 		unsigned long addr, unsigned int size)
510*43ecec16SMauro Carvalho Chehab {
511*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
512*43ecec16SMauro Carvalho Chehab 
513*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
514*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
515*43ecec16SMauro Carvalho Chehab 	return 0;
516*43ecec16SMauro Carvalho Chehab }
517*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx * ctx,unsigned long y_addr,unsigned long c_addr)518*43ecec16SMauro Carvalho Chehab static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
519*43ecec16SMauro Carvalho Chehab 		unsigned long y_addr, unsigned long c_addr)
520*43ecec16SMauro Carvalho Chehab {
521*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
522*43ecec16SMauro Carvalho Chehab 
523*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
524*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
525*43ecec16SMauro Carvalho Chehab }
526*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx * ctx,unsigned long * y_addr,unsigned long * c_addr)527*43ecec16SMauro Carvalho Chehab static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
528*43ecec16SMauro Carvalho Chehab 		unsigned long *y_addr, unsigned long *c_addr)
529*43ecec16SMauro Carvalho Chehab {
530*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
531*43ecec16SMauro Carvalho Chehab 
532*43ecec16SMauro Carvalho Chehab 	*y_addr = dev->dma_base[BANK_R_CTX] +
533*43ecec16SMauro Carvalho Chehab 		  (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT);
534*43ecec16SMauro Carvalho Chehab 	*c_addr = dev->dma_base[BANK_R_CTX] +
535*43ecec16SMauro Carvalho Chehab 		  (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT);
536*43ecec16SMauro Carvalho Chehab }
537*43ecec16SMauro Carvalho Chehab 
538*43ecec16SMauro Carvalho Chehab /* Set encoding ref & codec buffer */
s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx * ctx)539*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
540*43ecec16SMauro Carvalho Chehab {
541*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
542*43ecec16SMauro Carvalho Chehab 	size_t buf_addr1, buf_addr2;
543*43ecec16SMauro Carvalho Chehab 	size_t buf_size1, buf_size2;
544*43ecec16SMauro Carvalho Chehab 	unsigned int enc_ref_y_size, enc_ref_c_size;
545*43ecec16SMauro Carvalho Chehab 	unsigned int guard_width, guard_height;
546*43ecec16SMauro Carvalho Chehab 	int i;
547*43ecec16SMauro Carvalho Chehab 
548*43ecec16SMauro Carvalho Chehab 	buf_addr1 = ctx->bank1.dma;
549*43ecec16SMauro Carvalho Chehab 	buf_size1 = ctx->bank1.size;
550*43ecec16SMauro Carvalho Chehab 	buf_addr2 = ctx->bank2.dma;
551*43ecec16SMauro Carvalho Chehab 	buf_size2 = ctx->bank2.size;
552*43ecec16SMauro Carvalho Chehab 	enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
553*43ecec16SMauro Carvalho Chehab 		* ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
554*43ecec16SMauro Carvalho Chehab 	enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
555*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
556*43ecec16SMauro Carvalho Chehab 		enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
557*43ecec16SMauro Carvalho Chehab 			* ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
558*43ecec16SMauro Carvalho Chehab 		enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
559*43ecec16SMauro Carvalho Chehab 	} else {
560*43ecec16SMauro Carvalho Chehab 		guard_width = ALIGN(ctx->img_width + 16,
561*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_NV12MT_HALIGN);
562*43ecec16SMauro Carvalho Chehab 		guard_height = ALIGN((ctx->img_height >> 1) + 4,
563*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_NV12MT_VALIGN);
564*43ecec16SMauro Carvalho Chehab 		enc_ref_c_size = ALIGN(guard_width * guard_height,
565*43ecec16SMauro Carvalho Chehab 				       S5P_FIMV_NV12MT_SALIGN);
566*43ecec16SMauro Carvalho Chehab 	}
567*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n", buf_size1, buf_size2);
568*43ecec16SMauro Carvalho Chehab 	switch (ctx->codec_mode) {
569*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H264_ENC:
570*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 2; i++) {
571*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETA(buf_addr1),
572*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
573*43ecec16SMauro Carvalho Chehab 			buf_addr1 += enc_ref_y_size;
574*43ecec16SMauro Carvalho Chehab 			buf_size1 -= enc_ref_y_size;
575*43ecec16SMauro Carvalho Chehab 
576*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
577*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
578*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_y_size;
579*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_y_size;
580*43ecec16SMauro Carvalho Chehab 		}
581*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 4; i++) {
582*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
583*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
584*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_c_size;
585*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_c_size;
586*43ecec16SMauro Carvalho Chehab 		}
587*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
588*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
589*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
590*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
591*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_H264_COZERO_FLAG_ADR);
592*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
593*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
594*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
595*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_H264_UP_INTRA_MD_ADR);
596*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
597*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
598*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETB(buf_addr2),
599*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_H264_UP_INTRA_PRED_ADR);
600*43ecec16SMauro Carvalho Chehab 		buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
601*43ecec16SMauro Carvalho Chehab 		buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
602*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
603*43ecec16SMauro Carvalho Chehab 					S5P_FIMV_H264_NBOR_INFO_ADR);
604*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
605*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
606*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
607*43ecec16SMauro Carvalho Chehab 			buf_size1, buf_size2);
608*43ecec16SMauro Carvalho Chehab 		break;
609*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_MPEG4_ENC:
610*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 2; i++) {
611*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETA(buf_addr1),
612*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
613*43ecec16SMauro Carvalho Chehab 			buf_addr1 += enc_ref_y_size;
614*43ecec16SMauro Carvalho Chehab 			buf_size1 -= enc_ref_y_size;
615*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
616*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
617*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_y_size;
618*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_y_size;
619*43ecec16SMauro Carvalho Chehab 		}
620*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 4; i++) {
621*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
622*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
623*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_c_size;
624*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_c_size;
625*43ecec16SMauro Carvalho Chehab 		}
626*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
627*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
628*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
629*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
630*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
631*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
632*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
633*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1),
634*43ecec16SMauro Carvalho Chehab 						S5P_FIMV_MPEG4_ACDC_COEF_ADR);
635*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
636*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
637*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
638*43ecec16SMauro Carvalho Chehab 			buf_size1, buf_size2);
639*43ecec16SMauro Carvalho Chehab 		break;
640*43ecec16SMauro Carvalho Chehab 	case S5P_MFC_CODEC_H263_ENC:
641*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 2; i++) {
642*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETA(buf_addr1),
643*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
644*43ecec16SMauro Carvalho Chehab 			buf_addr1 += enc_ref_y_size;
645*43ecec16SMauro Carvalho Chehab 			buf_size1 -= enc_ref_y_size;
646*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
647*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
648*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_y_size;
649*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_y_size;
650*43ecec16SMauro Carvalho Chehab 		}
651*43ecec16SMauro Carvalho Chehab 		for (i = 0; i < 4; i++) {
652*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, OFFSETB(buf_addr2),
653*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
654*43ecec16SMauro Carvalho Chehab 			buf_addr2 += enc_ref_c_size;
655*43ecec16SMauro Carvalho Chehab 			buf_size2 -= enc_ref_c_size;
656*43ecec16SMauro Carvalho Chehab 		}
657*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
658*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
659*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
660*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
661*43ecec16SMauro Carvalho Chehab 		buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
662*43ecec16SMauro Carvalho Chehab 		buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
663*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
664*43ecec16SMauro Carvalho Chehab 			buf_size1, buf_size2);
665*43ecec16SMauro Carvalho Chehab 		break;
666*43ecec16SMauro Carvalho Chehab 	default:
667*43ecec16SMauro Carvalho Chehab 		mfc_err("Unknown codec set for encoding: %d\n",
668*43ecec16SMauro Carvalho Chehab 			ctx->codec_mode);
669*43ecec16SMauro Carvalho Chehab 		return -EINVAL;
670*43ecec16SMauro Carvalho Chehab 	}
671*43ecec16SMauro Carvalho Chehab 	return 0;
672*43ecec16SMauro Carvalho Chehab }
673*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_enc_params(struct s5p_mfc_ctx * ctx)674*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
675*43ecec16SMauro Carvalho Chehab {
676*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
677*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_enc_params *p = &ctx->enc_params;
678*43ecec16SMauro Carvalho Chehab 	unsigned int reg;
679*43ecec16SMauro Carvalho Chehab 	unsigned int shm;
680*43ecec16SMauro Carvalho Chehab 
681*43ecec16SMauro Carvalho Chehab 	/* width */
682*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
683*43ecec16SMauro Carvalho Chehab 	/* height */
684*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
685*43ecec16SMauro Carvalho Chehab 	/* pictype : enable, IDR period */
686*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
687*43ecec16SMauro Carvalho Chehab 	reg |= (1 << 18);
688*43ecec16SMauro Carvalho Chehab 	reg &= ~(0xFFFF);
689*43ecec16SMauro Carvalho Chehab 	reg |= p->gop_size;
690*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
691*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
692*43ecec16SMauro Carvalho Chehab 	/* multi-slice control */
693*43ecec16SMauro Carvalho Chehab 	/* multi-slice MB number or bit size */
694*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
695*43ecec16SMauro Carvalho Chehab 	if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
696*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
697*43ecec16SMauro Carvalho Chehab 	} else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
698*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
699*43ecec16SMauro Carvalho Chehab 	} else {
700*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
701*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
702*43ecec16SMauro Carvalho Chehab 	}
703*43ecec16SMauro Carvalho Chehab 	/* cyclic intra refresh */
704*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
705*43ecec16SMauro Carvalho Chehab 	/* memory structure cur. frame */
706*43ecec16SMauro Carvalho Chehab 	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
707*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
708*43ecec16SMauro Carvalho Chehab 	else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
709*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
710*43ecec16SMauro Carvalho Chehab 	/* padding control & value */
711*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
712*43ecec16SMauro Carvalho Chehab 	if (p->pad) {
713*43ecec16SMauro Carvalho Chehab 		/** enable */
714*43ecec16SMauro Carvalho Chehab 		reg |= (1UL << 31);
715*43ecec16SMauro Carvalho Chehab 		/** cr value */
716*43ecec16SMauro Carvalho Chehab 		reg &= ~(0xFF << 16);
717*43ecec16SMauro Carvalho Chehab 		reg |= (p->pad_cr << 16);
718*43ecec16SMauro Carvalho Chehab 		/** cb value */
719*43ecec16SMauro Carvalho Chehab 		reg &= ~(0xFF << 8);
720*43ecec16SMauro Carvalho Chehab 		reg |= (p->pad_cb << 8);
721*43ecec16SMauro Carvalho Chehab 		/** y value */
722*43ecec16SMauro Carvalho Chehab 		reg &= ~(0xFF);
723*43ecec16SMauro Carvalho Chehab 		reg |= (p->pad_luma);
724*43ecec16SMauro Carvalho Chehab 	} else {
725*43ecec16SMauro Carvalho Chehab 		/** disable & all value clear */
726*43ecec16SMauro Carvalho Chehab 		reg = 0;
727*43ecec16SMauro Carvalho Chehab 	}
728*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
729*43ecec16SMauro Carvalho Chehab 	/* rate control config. */
730*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
731*43ecec16SMauro Carvalho Chehab 	/** frame-level rate control */
732*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x1 << 9);
733*43ecec16SMauro Carvalho Chehab 	reg |= (p->rc_frame << 9);
734*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
735*43ecec16SMauro Carvalho Chehab 	/* bit rate */
736*43ecec16SMauro Carvalho Chehab 	if (p->rc_frame)
737*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->rc_bitrate,
738*43ecec16SMauro Carvalho Chehab 			S5P_FIMV_ENC_RC_BIT_RATE);
739*43ecec16SMauro Carvalho Chehab 	else
740*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
741*43ecec16SMauro Carvalho Chehab 	/* reaction coefficient */
742*43ecec16SMauro Carvalho Chehab 	if (p->rc_frame)
743*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
744*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
745*43ecec16SMauro Carvalho Chehab 	/* seq header ctrl */
746*43ecec16SMauro Carvalho Chehab 	shm &= ~(0x1 << 3);
747*43ecec16SMauro Carvalho Chehab 	shm |= (p->seq_hdr_mode << 3);
748*43ecec16SMauro Carvalho Chehab 	/* frame skip mode */
749*43ecec16SMauro Carvalho Chehab 	shm &= ~(0x3 << 1);
750*43ecec16SMauro Carvalho Chehab 	shm |= (p->frame_skip_mode << 1);
751*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
752*43ecec16SMauro Carvalho Chehab 	/* fixed target bit */
753*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
754*43ecec16SMauro Carvalho Chehab 	return 0;
755*43ecec16SMauro Carvalho Chehab }
756*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx * ctx)757*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
758*43ecec16SMauro Carvalho Chehab {
759*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
760*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_enc_params *p = &ctx->enc_params;
761*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
762*43ecec16SMauro Carvalho Chehab 	unsigned int reg;
763*43ecec16SMauro Carvalho Chehab 	unsigned int shm;
764*43ecec16SMauro Carvalho Chehab 
765*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_params(ctx);
766*43ecec16SMauro Carvalho Chehab 	/* pictype : number of B */
767*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
768*43ecec16SMauro Carvalho Chehab 	/* num_b_frame - 0 ~ 2 */
769*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3 << 16);
770*43ecec16SMauro Carvalho Chehab 	reg |= (p->num_b_frame << 16);
771*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
772*43ecec16SMauro Carvalho Chehab 	/* profile & level */
773*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
774*43ecec16SMauro Carvalho Chehab 	/* level */
775*43ecec16SMauro Carvalho Chehab 	reg &= ~(0xFF << 8);
776*43ecec16SMauro Carvalho Chehab 	reg |= (p_264->level << 8);
777*43ecec16SMauro Carvalho Chehab 	/* profile - 0 ~ 2 */
778*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
779*43ecec16SMauro Carvalho Chehab 	reg |= p_264->profile;
780*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
781*43ecec16SMauro Carvalho Chehab 	/* interlace  */
782*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
783*43ecec16SMauro Carvalho Chehab 	/* height */
784*43ecec16SMauro Carvalho Chehab 	if (p_264->interlace)
785*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
786*43ecec16SMauro Carvalho Chehab 	/* loopfilter ctrl */
787*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
788*43ecec16SMauro Carvalho Chehab 	/* loopfilter alpha offset */
789*43ecec16SMauro Carvalho Chehab 	if (p_264->loop_filter_alpha < 0) {
790*43ecec16SMauro Carvalho Chehab 		reg = 0x10;
791*43ecec16SMauro Carvalho Chehab 		reg |= (0xFF - p_264->loop_filter_alpha) + 1;
792*43ecec16SMauro Carvalho Chehab 	} else {
793*43ecec16SMauro Carvalho Chehab 		reg = 0x00;
794*43ecec16SMauro Carvalho Chehab 		reg |= (p_264->loop_filter_alpha & 0xF);
795*43ecec16SMauro Carvalho Chehab 	}
796*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
797*43ecec16SMauro Carvalho Chehab 	/* loopfilter beta offset */
798*43ecec16SMauro Carvalho Chehab 	if (p_264->loop_filter_beta < 0) {
799*43ecec16SMauro Carvalho Chehab 		reg = 0x10;
800*43ecec16SMauro Carvalho Chehab 		reg |= (0xFF - p_264->loop_filter_beta) + 1;
801*43ecec16SMauro Carvalho Chehab 	} else {
802*43ecec16SMauro Carvalho Chehab 		reg = 0x00;
803*43ecec16SMauro Carvalho Chehab 		reg |= (p_264->loop_filter_beta & 0xF);
804*43ecec16SMauro Carvalho Chehab 	}
805*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
806*43ecec16SMauro Carvalho Chehab 	/* entropy coding mode */
807*43ecec16SMauro Carvalho Chehab 	if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
808*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
809*43ecec16SMauro Carvalho Chehab 	else
810*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
811*43ecec16SMauro Carvalho Chehab 	/* number of ref. picture */
812*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
813*43ecec16SMauro Carvalho Chehab 	/* num of ref. pictures of P */
814*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3 << 5);
815*43ecec16SMauro Carvalho Chehab 	reg |= (p_264->num_ref_pic_4p << 5);
816*43ecec16SMauro Carvalho Chehab 	/* max number of ref. pictures */
817*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x1F);
818*43ecec16SMauro Carvalho Chehab 	reg |= p_264->max_ref_pic;
819*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
820*43ecec16SMauro Carvalho Chehab 	/* 8x8 transform enable */
821*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
822*43ecec16SMauro Carvalho Chehab 	/* rate control config. */
823*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
824*43ecec16SMauro Carvalho Chehab 	/* macroblock level rate control */
825*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x1 << 8);
826*43ecec16SMauro Carvalho Chehab 	reg |= (p->rc_mb << 8);
827*43ecec16SMauro Carvalho Chehab 	/* frame QP */
828*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
829*43ecec16SMauro Carvalho Chehab 	reg |= p_264->rc_frame_qp;
830*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
831*43ecec16SMauro Carvalho Chehab 	/* frame rate */
832*43ecec16SMauro Carvalho Chehab 	if (p->rc_frame && p->rc_framerate_denom)
833*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->rc_framerate_num * 1000
834*43ecec16SMauro Carvalho Chehab 			/ p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
835*43ecec16SMauro Carvalho Chehab 	else
836*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
837*43ecec16SMauro Carvalho Chehab 	/* max & min value of QP */
838*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
839*43ecec16SMauro Carvalho Chehab 	/* max QP */
840*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F << 8);
841*43ecec16SMauro Carvalho Chehab 	reg |= (p_264->rc_max_qp << 8);
842*43ecec16SMauro Carvalho Chehab 	/* min QP */
843*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
844*43ecec16SMauro Carvalho Chehab 	reg |= p_264->rc_min_qp;
845*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
846*43ecec16SMauro Carvalho Chehab 	/* macroblock adaptive scaling features */
847*43ecec16SMauro Carvalho Chehab 	if (p->rc_mb) {
848*43ecec16SMauro Carvalho Chehab 		reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
849*43ecec16SMauro Carvalho Chehab 		/* dark region */
850*43ecec16SMauro Carvalho Chehab 		reg &= ~(0x1 << 3);
851*43ecec16SMauro Carvalho Chehab 		reg |= (p_264->rc_mb_dark << 3);
852*43ecec16SMauro Carvalho Chehab 		/* smooth region */
853*43ecec16SMauro Carvalho Chehab 		reg &= ~(0x1 << 2);
854*43ecec16SMauro Carvalho Chehab 		reg |= (p_264->rc_mb_smooth << 2);
855*43ecec16SMauro Carvalho Chehab 		/* static region */
856*43ecec16SMauro Carvalho Chehab 		reg &= ~(0x1 << 1);
857*43ecec16SMauro Carvalho Chehab 		reg |= (p_264->rc_mb_static << 1);
858*43ecec16SMauro Carvalho Chehab 		/* high activity region */
859*43ecec16SMauro Carvalho Chehab 		reg &= ~(0x1);
860*43ecec16SMauro Carvalho Chehab 		reg |= p_264->rc_mb_activity;
861*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
862*43ecec16SMauro Carvalho Chehab 	}
863*43ecec16SMauro Carvalho Chehab 	if (!p->rc_frame && !p->rc_mb) {
864*43ecec16SMauro Carvalho Chehab 		shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
865*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFF);
866*43ecec16SMauro Carvalho Chehab 		shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
867*43ecec16SMauro Carvalho Chehab 		shm |= (p_264->rc_p_frame_qp & 0x3F);
868*43ecec16SMauro Carvalho Chehab 		s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
869*43ecec16SMauro Carvalho Chehab 	}
870*43ecec16SMauro Carvalho Chehab 	/* extended encoder ctrl */
871*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
872*43ecec16SMauro Carvalho Chehab 	/* AR VUI control */
873*43ecec16SMauro Carvalho Chehab 	shm &= ~(0x1 << 15);
874*43ecec16SMauro Carvalho Chehab 	shm |= (p_264->vui_sar << 1);
875*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
876*43ecec16SMauro Carvalho Chehab 	if (p_264->vui_sar) {
877*43ecec16SMauro Carvalho Chehab 		/* aspect ration IDC */
878*43ecec16SMauro Carvalho Chehab 		shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
879*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFF);
880*43ecec16SMauro Carvalho Chehab 		shm |= p_264->vui_sar_idc;
881*43ecec16SMauro Carvalho Chehab 		s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
882*43ecec16SMauro Carvalho Chehab 		if (p_264->vui_sar_idc == 0xFF) {
883*43ecec16SMauro Carvalho Chehab 			/* sample  AR info */
884*43ecec16SMauro Carvalho Chehab 			shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
885*43ecec16SMauro Carvalho Chehab 			shm &= ~(0xFFFFFFFF);
886*43ecec16SMauro Carvalho Chehab 			shm |= p_264->vui_ext_sar_width << 16;
887*43ecec16SMauro Carvalho Chehab 			shm |= p_264->vui_ext_sar_height;
888*43ecec16SMauro Carvalho Chehab 			s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
889*43ecec16SMauro Carvalho Chehab 		}
890*43ecec16SMauro Carvalho Chehab 	}
891*43ecec16SMauro Carvalho Chehab 	/* intra picture period for H.264 */
892*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
893*43ecec16SMauro Carvalho Chehab 	/* control */
894*43ecec16SMauro Carvalho Chehab 	shm &= ~(0x1 << 16);
895*43ecec16SMauro Carvalho Chehab 	shm |= (p_264->open_gop << 16);
896*43ecec16SMauro Carvalho Chehab 	/* value */
897*43ecec16SMauro Carvalho Chehab 	if (p_264->open_gop) {
898*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFFF);
899*43ecec16SMauro Carvalho Chehab 		shm |= p_264->open_gop_size;
900*43ecec16SMauro Carvalho Chehab 	}
901*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
902*43ecec16SMauro Carvalho Chehab 	/* extended encoder ctrl */
903*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
904*43ecec16SMauro Carvalho Chehab 	/* vbv buffer size */
905*43ecec16SMauro Carvalho Chehab 	if (p->frame_skip_mode ==
906*43ecec16SMauro Carvalho Chehab 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
907*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFFF << 16);
908*43ecec16SMauro Carvalho Chehab 		shm |= (p_264->cpb_size << 16);
909*43ecec16SMauro Carvalho Chehab 	}
910*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
911*43ecec16SMauro Carvalho Chehab 	return 0;
912*43ecec16SMauro Carvalho Chehab }
913*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx * ctx)914*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
915*43ecec16SMauro Carvalho Chehab {
916*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
917*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_enc_params *p = &ctx->enc_params;
918*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
919*43ecec16SMauro Carvalho Chehab 	unsigned int reg;
920*43ecec16SMauro Carvalho Chehab 	unsigned int shm;
921*43ecec16SMauro Carvalho Chehab 	unsigned int framerate;
922*43ecec16SMauro Carvalho Chehab 
923*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_params(ctx);
924*43ecec16SMauro Carvalho Chehab 	/* pictype : number of B */
925*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
926*43ecec16SMauro Carvalho Chehab 	/* num_b_frame - 0 ~ 2 */
927*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3 << 16);
928*43ecec16SMauro Carvalho Chehab 	reg |= (p->num_b_frame << 16);
929*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
930*43ecec16SMauro Carvalho Chehab 	/* profile & level */
931*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
932*43ecec16SMauro Carvalho Chehab 	/* level */
933*43ecec16SMauro Carvalho Chehab 	reg &= ~(0xFF << 8);
934*43ecec16SMauro Carvalho Chehab 	reg |= (p_mpeg4->level << 8);
935*43ecec16SMauro Carvalho Chehab 	/* profile - 0 ~ 2 */
936*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
937*43ecec16SMauro Carvalho Chehab 	reg |= p_mpeg4->profile;
938*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
939*43ecec16SMauro Carvalho Chehab 	/* quarter_pixel */
940*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
941*43ecec16SMauro Carvalho Chehab 	/* qp */
942*43ecec16SMauro Carvalho Chehab 	if (!p->rc_frame) {
943*43ecec16SMauro Carvalho Chehab 		shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
944*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFF);
945*43ecec16SMauro Carvalho Chehab 		shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
946*43ecec16SMauro Carvalho Chehab 		shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
947*43ecec16SMauro Carvalho Chehab 		s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
948*43ecec16SMauro Carvalho Chehab 	}
949*43ecec16SMauro Carvalho Chehab 	/* frame rate */
950*43ecec16SMauro Carvalho Chehab 	if (p->rc_frame) {
951*43ecec16SMauro Carvalho Chehab 		if (p->rc_framerate_denom > 0) {
952*43ecec16SMauro Carvalho Chehab 			framerate = p->rc_framerate_num * 1000 /
953*43ecec16SMauro Carvalho Chehab 						p->rc_framerate_denom;
954*43ecec16SMauro Carvalho Chehab 			mfc_write(dev, framerate,
955*43ecec16SMauro Carvalho Chehab 				S5P_FIMV_ENC_RC_FRAME_RATE);
956*43ecec16SMauro Carvalho Chehab 			shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
957*43ecec16SMauro Carvalho Chehab 			shm &= ~(0xFFFFFFFF);
958*43ecec16SMauro Carvalho Chehab 			shm |= (1UL << 31);
959*43ecec16SMauro Carvalho Chehab 			shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
960*43ecec16SMauro Carvalho Chehab 			shm |= (p->rc_framerate_denom & 0xFFFF);
961*43ecec16SMauro Carvalho Chehab 			s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
962*43ecec16SMauro Carvalho Chehab 		}
963*43ecec16SMauro Carvalho Chehab 	} else {
964*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
965*43ecec16SMauro Carvalho Chehab 	}
966*43ecec16SMauro Carvalho Chehab 	/* rate control config. */
967*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
968*43ecec16SMauro Carvalho Chehab 	/* frame QP */
969*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
970*43ecec16SMauro Carvalho Chehab 	reg |= p_mpeg4->rc_frame_qp;
971*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
972*43ecec16SMauro Carvalho Chehab 	/* max & min value of QP */
973*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
974*43ecec16SMauro Carvalho Chehab 	/* max QP */
975*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F << 8);
976*43ecec16SMauro Carvalho Chehab 	reg |= (p_mpeg4->rc_max_qp << 8);
977*43ecec16SMauro Carvalho Chehab 	/* min QP */
978*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
979*43ecec16SMauro Carvalho Chehab 	reg |= p_mpeg4->rc_min_qp;
980*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
981*43ecec16SMauro Carvalho Chehab 	/* extended encoder ctrl */
982*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
983*43ecec16SMauro Carvalho Chehab 	/* vbv buffer size */
984*43ecec16SMauro Carvalho Chehab 	if (p->frame_skip_mode ==
985*43ecec16SMauro Carvalho Chehab 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
986*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFFF << 16);
987*43ecec16SMauro Carvalho Chehab 		shm |= (p->vbv_size << 16);
988*43ecec16SMauro Carvalho Chehab 	}
989*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
990*43ecec16SMauro Carvalho Chehab 	return 0;
991*43ecec16SMauro Carvalho Chehab }
992*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx * ctx)993*43ecec16SMauro Carvalho Chehab static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
994*43ecec16SMauro Carvalho Chehab {
995*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
996*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_enc_params *p = &ctx->enc_params;
997*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
998*43ecec16SMauro Carvalho Chehab 	unsigned int reg;
999*43ecec16SMauro Carvalho Chehab 	unsigned int shm;
1000*43ecec16SMauro Carvalho Chehab 
1001*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_params(ctx);
1002*43ecec16SMauro Carvalho Chehab 	/* qp */
1003*43ecec16SMauro Carvalho Chehab 	if (!p->rc_frame) {
1004*43ecec16SMauro Carvalho Chehab 		shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
1005*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFF);
1006*43ecec16SMauro Carvalho Chehab 		shm |= (p_h263->rc_p_frame_qp & 0x3F);
1007*43ecec16SMauro Carvalho Chehab 		s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
1008*43ecec16SMauro Carvalho Chehab 	}
1009*43ecec16SMauro Carvalho Chehab 	/* frame rate */
1010*43ecec16SMauro Carvalho Chehab 	if (p->rc_frame && p->rc_framerate_denom)
1011*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, p->rc_framerate_num * 1000
1012*43ecec16SMauro Carvalho Chehab 			/ p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
1013*43ecec16SMauro Carvalho Chehab 	else
1014*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
1015*43ecec16SMauro Carvalho Chehab 	/* rate control config. */
1016*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
1017*43ecec16SMauro Carvalho Chehab 	/* frame QP */
1018*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
1019*43ecec16SMauro Carvalho Chehab 	reg |= p_h263->rc_frame_qp;
1020*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
1021*43ecec16SMauro Carvalho Chehab 	/* max & min value of QP */
1022*43ecec16SMauro Carvalho Chehab 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
1023*43ecec16SMauro Carvalho Chehab 	/* max QP */
1024*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F << 8);
1025*43ecec16SMauro Carvalho Chehab 	reg |= (p_h263->rc_max_qp << 8);
1026*43ecec16SMauro Carvalho Chehab 	/* min QP */
1027*43ecec16SMauro Carvalho Chehab 	reg &= ~(0x3F);
1028*43ecec16SMauro Carvalho Chehab 	reg |= p_h263->rc_min_qp;
1029*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
1030*43ecec16SMauro Carvalho Chehab 	/* extended encoder ctrl */
1031*43ecec16SMauro Carvalho Chehab 	shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
1032*43ecec16SMauro Carvalho Chehab 	/* vbv buffer size */
1033*43ecec16SMauro Carvalho Chehab 	if (p->frame_skip_mode ==
1034*43ecec16SMauro Carvalho Chehab 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
1035*43ecec16SMauro Carvalho Chehab 		shm &= ~(0xFFFF << 16);
1036*43ecec16SMauro Carvalho Chehab 		shm |= (p->vbv_size << 16);
1037*43ecec16SMauro Carvalho Chehab 	}
1038*43ecec16SMauro Carvalho Chehab 	s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
1039*43ecec16SMauro Carvalho Chehab 	return 0;
1040*43ecec16SMauro Carvalho Chehab }
1041*43ecec16SMauro Carvalho Chehab 
1042*43ecec16SMauro Carvalho Chehab /* Initialize decoding */
s5p_mfc_init_decode_v5(struct s5p_mfc_ctx * ctx)1043*43ecec16SMauro Carvalho Chehab static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
1044*43ecec16SMauro Carvalho Chehab {
1045*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1046*43ecec16SMauro Carvalho Chehab 
1047*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_shared_buffer(ctx);
1048*43ecec16SMauro Carvalho Chehab 	/* Setup loop filter, for decoding this is only valid for MPEG4 */
1049*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
1050*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
1051*43ecec16SMauro Carvalho Chehab 	else
1052*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
1053*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
1054*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
1055*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
1056*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
1057*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
1058*43ecec16SMauro Carvalho Chehab 	mfc_write(dev,
1059*43ecec16SMauro Carvalho Chehab 	((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
1060*43ecec16SMauro Carvalho Chehab 				| (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1061*43ecec16SMauro Carvalho Chehab 	return 0;
1062*43ecec16SMauro Carvalho Chehab }
1063*43ecec16SMauro Carvalho Chehab 
s5p_mfc_set_flush(struct s5p_mfc_ctx * ctx,int flush)1064*43ecec16SMauro Carvalho Chehab static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
1065*43ecec16SMauro Carvalho Chehab {
1066*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1067*43ecec16SMauro Carvalho Chehab 	unsigned int dpb;
1068*43ecec16SMauro Carvalho Chehab 
1069*43ecec16SMauro Carvalho Chehab 	if (flush)
1070*43ecec16SMauro Carvalho Chehab 		dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
1071*43ecec16SMauro Carvalho Chehab 			S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
1072*43ecec16SMauro Carvalho Chehab 	else
1073*43ecec16SMauro Carvalho Chehab 		dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
1074*43ecec16SMauro Carvalho Chehab 			~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
1075*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
1076*43ecec16SMauro Carvalho Chehab }
1077*43ecec16SMauro Carvalho Chehab 
1078*43ecec16SMauro Carvalho Chehab /* Decode a single frame */
s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx * ctx,enum s5p_mfc_decode_arg last_frame)1079*43ecec16SMauro Carvalho Chehab static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
1080*43ecec16SMauro Carvalho Chehab 					enum s5p_mfc_decode_arg last_frame)
1081*43ecec16SMauro Carvalho Chehab {
1082*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1083*43ecec16SMauro Carvalho Chehab 
1084*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
1085*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_shared_buffer(ctx);
1086*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
1087*43ecec16SMauro Carvalho Chehab 	/* Issue different commands to instance basing on whether it
1088*43ecec16SMauro Carvalho Chehab 	 * is the last frame or not. */
1089*43ecec16SMauro Carvalho Chehab 	switch (last_frame) {
1090*43ecec16SMauro Carvalho Chehab 	case MFC_DEC_FRAME:
1091*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
1092*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1093*43ecec16SMauro Carvalho Chehab 		break;
1094*43ecec16SMauro Carvalho Chehab 	case MFC_DEC_LAST_FRAME:
1095*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
1096*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1097*43ecec16SMauro Carvalho Chehab 		break;
1098*43ecec16SMauro Carvalho Chehab 	case MFC_DEC_RES_CHANGE:
1099*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
1100*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
1101*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_SI_CH0_INST_ID);
1102*43ecec16SMauro Carvalho Chehab 		break;
1103*43ecec16SMauro Carvalho Chehab 	}
1104*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Decoding a usual frame\n");
1105*43ecec16SMauro Carvalho Chehab 	return 0;
1106*43ecec16SMauro Carvalho Chehab }
1107*43ecec16SMauro Carvalho Chehab 
s5p_mfc_init_encode_v5(struct s5p_mfc_ctx * ctx)1108*43ecec16SMauro Carvalho Chehab static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
1109*43ecec16SMauro Carvalho Chehab {
1110*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1111*43ecec16SMauro Carvalho Chehab 
1112*43ecec16SMauro Carvalho Chehab 	if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
1113*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_enc_params_h264(ctx);
1114*43ecec16SMauro Carvalho Chehab 	else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
1115*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_enc_params_mpeg4(ctx);
1116*43ecec16SMauro Carvalho Chehab 	else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
1117*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_enc_params_h263(ctx);
1118*43ecec16SMauro Carvalho Chehab 	else {
1119*43ecec16SMauro Carvalho Chehab 		mfc_err("Unknown codec for encoding (%x)\n",
1120*43ecec16SMauro Carvalho Chehab 			ctx->codec_mode);
1121*43ecec16SMauro Carvalho Chehab 		return -EINVAL;
1122*43ecec16SMauro Carvalho Chehab 	}
1123*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_shared_buffer(ctx);
1124*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
1125*43ecec16SMauro Carvalho Chehab 		(ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1126*43ecec16SMauro Carvalho Chehab 	return 0;
1127*43ecec16SMauro Carvalho Chehab }
1128*43ecec16SMauro Carvalho Chehab 
1129*43ecec16SMauro Carvalho Chehab /* Encode a single frame */
s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx * ctx)1130*43ecec16SMauro Carvalho Chehab static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
1131*43ecec16SMauro Carvalho Chehab {
1132*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1133*43ecec16SMauro Carvalho Chehab 	int cmd;
1134*43ecec16SMauro Carvalho Chehab 	/* memory structure cur. frame */
1135*43ecec16SMauro Carvalho Chehab 	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
1136*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
1137*43ecec16SMauro Carvalho Chehab 	else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
1138*43ecec16SMauro Carvalho Chehab 		mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
1139*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_shared_buffer(ctx);
1140*43ecec16SMauro Carvalho Chehab 
1141*43ecec16SMauro Carvalho Chehab 	if (ctx->state == MFCINST_FINISHING)
1142*43ecec16SMauro Carvalho Chehab 		cmd = S5P_FIMV_CH_LAST_FRAME;
1143*43ecec16SMauro Carvalho Chehab 	else
1144*43ecec16SMauro Carvalho Chehab 		cmd = S5P_FIMV_CH_FRAME_START;
1145*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
1146*43ecec16SMauro Carvalho Chehab 				| (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1147*43ecec16SMauro Carvalho Chehab 
1148*43ecec16SMauro Carvalho Chehab 	return 0;
1149*43ecec16SMauro Carvalho Chehab }
1150*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_res_change(struct s5p_mfc_ctx * ctx)1151*43ecec16SMauro Carvalho Chehab static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
1152*43ecec16SMauro Carvalho Chehab {
1153*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1154*43ecec16SMauro Carvalho Chehab 
1155*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
1156*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1157*43ecec16SMauro Carvalho Chehab 	s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
1158*43ecec16SMauro Carvalho Chehab }
1159*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_dec_frame(struct s5p_mfc_ctx * ctx,int last_frame)1160*43ecec16SMauro Carvalho Chehab static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
1161*43ecec16SMauro Carvalho Chehab {
1162*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1163*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *temp_vb;
1164*43ecec16SMauro Carvalho Chehab 
1165*43ecec16SMauro Carvalho Chehab 	if (ctx->state == MFCINST_FINISHING) {
1166*43ecec16SMauro Carvalho Chehab 		last_frame = MFC_DEC_LAST_FRAME;
1167*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
1168*43ecec16SMauro Carvalho Chehab 		dev->curr_ctx = ctx->num;
1169*43ecec16SMauro Carvalho Chehab 		s5p_mfc_decode_one_frame_v5(ctx, last_frame);
1170*43ecec16SMauro Carvalho Chehab 		return 0;
1171*43ecec16SMauro Carvalho Chehab 	}
1172*43ecec16SMauro Carvalho Chehab 
1173*43ecec16SMauro Carvalho Chehab 	/* Frames are being decoded */
1174*43ecec16SMauro Carvalho Chehab 	if (list_empty(&ctx->src_queue)) {
1175*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "No src buffers\n");
1176*43ecec16SMauro Carvalho Chehab 		return -EAGAIN;
1177*43ecec16SMauro Carvalho Chehab 	}
1178*43ecec16SMauro Carvalho Chehab 	/* Get the next source buffer */
1179*43ecec16SMauro Carvalho Chehab 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1180*43ecec16SMauro Carvalho Chehab 	temp_vb->flags |= MFC_BUF_FLAG_USED;
1181*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_dec_stream_buffer_v5(ctx,
1182*43ecec16SMauro Carvalho Chehab 		vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
1183*43ecec16SMauro Carvalho Chehab 		ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused);
1184*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1185*43ecec16SMauro Carvalho Chehab 	if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
1186*43ecec16SMauro Carvalho Chehab 		last_frame = MFC_DEC_LAST_FRAME;
1187*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "Setting ctx->state to FINISHING\n");
1188*43ecec16SMauro Carvalho Chehab 		ctx->state = MFCINST_FINISHING;
1189*43ecec16SMauro Carvalho Chehab 	}
1190*43ecec16SMauro Carvalho Chehab 	s5p_mfc_decode_one_frame_v5(ctx, last_frame);
1191*43ecec16SMauro Carvalho Chehab 	return 0;
1192*43ecec16SMauro Carvalho Chehab }
1193*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_enc_frame(struct s5p_mfc_ctx * ctx)1194*43ecec16SMauro Carvalho Chehab static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
1195*43ecec16SMauro Carvalho Chehab {
1196*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1197*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *dst_mb;
1198*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *src_mb;
1199*43ecec16SMauro Carvalho Chehab 	unsigned long src_y_addr, src_c_addr, dst_addr;
1200*43ecec16SMauro Carvalho Chehab 	unsigned int dst_size;
1201*43ecec16SMauro Carvalho Chehab 
1202*43ecec16SMauro Carvalho Chehab 	if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
1203*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "no src buffers\n");
1204*43ecec16SMauro Carvalho Chehab 		return -EAGAIN;
1205*43ecec16SMauro Carvalho Chehab 	}
1206*43ecec16SMauro Carvalho Chehab 	if (list_empty(&ctx->dst_queue)) {
1207*43ecec16SMauro Carvalho Chehab 		mfc_debug(2, "no dst buffers\n");
1208*43ecec16SMauro Carvalho Chehab 		return -EAGAIN;
1209*43ecec16SMauro Carvalho Chehab 	}
1210*43ecec16SMauro Carvalho Chehab 	if (list_empty(&ctx->src_queue)) {
1211*43ecec16SMauro Carvalho Chehab 		/* send null frame */
1212*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK_R_CTX],
1213*43ecec16SMauro Carvalho Chehab 						dev->dma_base[BANK_R_CTX]);
1214*43ecec16SMauro Carvalho Chehab 		src_mb = NULL;
1215*43ecec16SMauro Carvalho Chehab 	} else {
1216*43ecec16SMauro Carvalho Chehab 		src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
1217*43ecec16SMauro Carvalho Chehab 									list);
1218*43ecec16SMauro Carvalho Chehab 		src_mb->flags |= MFC_BUF_FLAG_USED;
1219*43ecec16SMauro Carvalho Chehab 		if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
1220*43ecec16SMauro Carvalho Chehab 			/* send null frame */
1221*43ecec16SMauro Carvalho Chehab 			s5p_mfc_set_enc_frame_buffer_v5(ctx,
1222*43ecec16SMauro Carvalho Chehab 						dev->dma_base[BANK_R_CTX],
1223*43ecec16SMauro Carvalho Chehab 						dev->dma_base[BANK_R_CTX]);
1224*43ecec16SMauro Carvalho Chehab 			ctx->state = MFCINST_FINISHING;
1225*43ecec16SMauro Carvalho Chehab 		} else {
1226*43ecec16SMauro Carvalho Chehab 			src_y_addr = vb2_dma_contig_plane_dma_addr(
1227*43ecec16SMauro Carvalho Chehab 					&src_mb->b->vb2_buf, 0);
1228*43ecec16SMauro Carvalho Chehab 			src_c_addr = vb2_dma_contig_plane_dma_addr(
1229*43ecec16SMauro Carvalho Chehab 					&src_mb->b->vb2_buf, 1);
1230*43ecec16SMauro Carvalho Chehab 			s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
1231*43ecec16SMauro Carvalho Chehab 								src_c_addr);
1232*43ecec16SMauro Carvalho Chehab 			if (src_mb->flags & MFC_BUF_FLAG_EOS)
1233*43ecec16SMauro Carvalho Chehab 				ctx->state = MFCINST_FINISHING;
1234*43ecec16SMauro Carvalho Chehab 		}
1235*43ecec16SMauro Carvalho Chehab 	}
1236*43ecec16SMauro Carvalho Chehab 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
1237*43ecec16SMauro Carvalho Chehab 	dst_mb->flags |= MFC_BUF_FLAG_USED;
1238*43ecec16SMauro Carvalho Chehab 	dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
1239*43ecec16SMauro Carvalho Chehab 	dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
1240*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
1241*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1242*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "encoding buffer with index=%d state=%d\n",
1243*43ecec16SMauro Carvalho Chehab 		  src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state);
1244*43ecec16SMauro Carvalho Chehab 	s5p_mfc_encode_one_frame_v5(ctx);
1245*43ecec16SMauro Carvalho Chehab 	return 0;
1246*43ecec16SMauro Carvalho Chehab }
1247*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_init_dec(struct s5p_mfc_ctx * ctx)1248*43ecec16SMauro Carvalho Chehab static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
1249*43ecec16SMauro Carvalho Chehab {
1250*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1251*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *temp_vb;
1252*43ecec16SMauro Carvalho Chehab 
1253*43ecec16SMauro Carvalho Chehab 	/* Initializing decoding - parsing header */
1254*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Preparing to init decoding\n");
1255*43ecec16SMauro Carvalho Chehab 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1256*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_dec_desc_buffer(ctx);
1257*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Header size: %d\n",
1258*43ecec16SMauro Carvalho Chehab 			temp_vb->b->vb2_buf.planes[0].bytesused);
1259*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_dec_stream_buffer_v5(ctx,
1260*43ecec16SMauro Carvalho Chehab 			vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
1261*43ecec16SMauro Carvalho Chehab 			0, temp_vb->b->vb2_buf.planes[0].bytesused);
1262*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1263*43ecec16SMauro Carvalho Chehab 	s5p_mfc_init_decode_v5(ctx);
1264*43ecec16SMauro Carvalho Chehab }
1265*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_init_enc(struct s5p_mfc_ctx * ctx)1266*43ecec16SMauro Carvalho Chehab static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
1267*43ecec16SMauro Carvalho Chehab {
1268*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1269*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *dst_mb;
1270*43ecec16SMauro Carvalho Chehab 	unsigned long dst_addr;
1271*43ecec16SMauro Carvalho Chehab 	unsigned int dst_size;
1272*43ecec16SMauro Carvalho Chehab 
1273*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_ref_buffer_v5(ctx);
1274*43ecec16SMauro Carvalho Chehab 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
1275*43ecec16SMauro Carvalho Chehab 	dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
1276*43ecec16SMauro Carvalho Chehab 	dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
1277*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
1278*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1279*43ecec16SMauro Carvalho Chehab 	s5p_mfc_init_encode_v5(ctx);
1280*43ecec16SMauro Carvalho Chehab }
1281*43ecec16SMauro Carvalho Chehab 
s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx * ctx)1282*43ecec16SMauro Carvalho Chehab static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
1283*43ecec16SMauro Carvalho Chehab {
1284*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_dev *dev = ctx->dev;
1285*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_buf *temp_vb;
1286*43ecec16SMauro Carvalho Chehab 	int ret;
1287*43ecec16SMauro Carvalho Chehab 
1288*43ecec16SMauro Carvalho Chehab 	/*
1289*43ecec16SMauro Carvalho Chehab 	 * Header was parsed now starting processing
1290*43ecec16SMauro Carvalho Chehab 	 * First set the output frame buffers
1291*43ecec16SMauro Carvalho Chehab 	 */
1292*43ecec16SMauro Carvalho Chehab 	if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
1293*43ecec16SMauro Carvalho Chehab 		mfc_err("It seems that not all destination buffers were mmapped\nMFC requires that all destination are mmapped before starting processing\n");
1294*43ecec16SMauro Carvalho Chehab 		return -EAGAIN;
1295*43ecec16SMauro Carvalho Chehab 	}
1296*43ecec16SMauro Carvalho Chehab 	if (list_empty(&ctx->src_queue)) {
1297*43ecec16SMauro Carvalho Chehab 		mfc_err("Header has been deallocated in the middle of initialization\n");
1298*43ecec16SMauro Carvalho Chehab 		return -EIO;
1299*43ecec16SMauro Carvalho Chehab 	}
1300*43ecec16SMauro Carvalho Chehab 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1301*43ecec16SMauro Carvalho Chehab 	mfc_debug(2, "Header size: %d\n",
1302*43ecec16SMauro Carvalho Chehab 			temp_vb->b->vb2_buf.planes[0].bytesused);
1303*43ecec16SMauro Carvalho Chehab 	s5p_mfc_set_dec_stream_buffer_v5(ctx,
1304*43ecec16SMauro Carvalho Chehab 			vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
1305*43ecec16SMauro Carvalho Chehab 			0, temp_vb->b->vb2_buf.planes[0].bytesused);
1306*43ecec16SMauro Carvalho Chehab 	dev->curr_ctx = ctx->num;
1307*43ecec16SMauro Carvalho Chehab 	ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
1308*43ecec16SMauro Carvalho Chehab 	if (ret) {
1309*43ecec16SMauro Carvalho Chehab 		mfc_err("Failed to alloc frame mem\n");
1310*43ecec16SMauro Carvalho Chehab 		ctx->state = MFCINST_ERROR;
1311*43ecec16SMauro Carvalho Chehab 	}
1312*43ecec16SMauro Carvalho Chehab 	return ret;
1313*43ecec16SMauro Carvalho Chehab }
1314*43ecec16SMauro Carvalho Chehab 
1315*43ecec16SMauro Carvalho Chehab /* Try running an operation on hardware */
s5p_mfc_try_run_v5(struct s5p_mfc_dev * dev)1316*43ecec16SMauro Carvalho Chehab static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
1317*43ecec16SMauro Carvalho Chehab {
1318*43ecec16SMauro Carvalho Chehab 	struct s5p_mfc_ctx *ctx;
1319*43ecec16SMauro Carvalho Chehab 	int new_ctx;
1320*43ecec16SMauro Carvalho Chehab 	unsigned int ret = 0;
1321*43ecec16SMauro Carvalho Chehab 
1322*43ecec16SMauro Carvalho Chehab 	if (test_bit(0, &dev->enter_suspend)) {
1323*43ecec16SMauro Carvalho Chehab 		mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
1324*43ecec16SMauro Carvalho Chehab 		return;
1325*43ecec16SMauro Carvalho Chehab 	}
1326*43ecec16SMauro Carvalho Chehab 	/* Check whether hardware is not running */
1327*43ecec16SMauro Carvalho Chehab 	if (test_and_set_bit(0, &dev->hw_lock) != 0) {
1328*43ecec16SMauro Carvalho Chehab 		/* This is perfectly ok, the scheduled ctx should wait */
1329*43ecec16SMauro Carvalho Chehab 		mfc_debug(1, "Couldn't lock HW\n");
1330*43ecec16SMauro Carvalho Chehab 		return;
1331*43ecec16SMauro Carvalho Chehab 	}
1332*43ecec16SMauro Carvalho Chehab 	/* Choose the context to run */
1333*43ecec16SMauro Carvalho Chehab 	new_ctx = s5p_mfc_get_new_ctx(dev);
1334*43ecec16SMauro Carvalho Chehab 	if (new_ctx < 0) {
1335*43ecec16SMauro Carvalho Chehab 		/* No contexts to run */
1336*43ecec16SMauro Carvalho Chehab 		if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
1337*43ecec16SMauro Carvalho Chehab 			mfc_err("Failed to unlock hardware\n");
1338*43ecec16SMauro Carvalho Chehab 			return;
1339*43ecec16SMauro Carvalho Chehab 		}
1340*43ecec16SMauro Carvalho Chehab 		mfc_debug(1, "No ctx is scheduled to be run\n");
1341*43ecec16SMauro Carvalho Chehab 		return;
1342*43ecec16SMauro Carvalho Chehab 	}
1343*43ecec16SMauro Carvalho Chehab 	ctx = dev->ctx[new_ctx];
1344*43ecec16SMauro Carvalho Chehab 	/* Got context to run in ctx */
1345*43ecec16SMauro Carvalho Chehab 	/*
1346*43ecec16SMauro Carvalho Chehab 	 * Last frame has already been sent to MFC.
1347*43ecec16SMauro Carvalho Chehab 	 * Now obtaining frames from MFC buffer
1348*43ecec16SMauro Carvalho Chehab 	 */
1349*43ecec16SMauro Carvalho Chehab 	s5p_mfc_clock_on();
1350*43ecec16SMauro Carvalho Chehab 	s5p_mfc_clean_ctx_int_flags(ctx);
1351*43ecec16SMauro Carvalho Chehab 
1352*43ecec16SMauro Carvalho Chehab 	if (ctx->type == MFCINST_DECODER) {
1353*43ecec16SMauro Carvalho Chehab 		s5p_mfc_set_dec_desc_buffer(ctx);
1354*43ecec16SMauro Carvalho Chehab 		switch (ctx->state) {
1355*43ecec16SMauro Carvalho Chehab 		case MFCINST_FINISHING:
1356*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
1357*43ecec16SMauro Carvalho Chehab 			break;
1358*43ecec16SMauro Carvalho Chehab 		case MFCINST_RUNNING:
1359*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
1360*43ecec16SMauro Carvalho Chehab 			break;
1361*43ecec16SMauro Carvalho Chehab 		case MFCINST_INIT:
1362*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
1363*43ecec16SMauro Carvalho Chehab 					ctx);
1364*43ecec16SMauro Carvalho Chehab 			break;
1365*43ecec16SMauro Carvalho Chehab 		case MFCINST_RETURN_INST:
1366*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
1367*43ecec16SMauro Carvalho Chehab 					ctx);
1368*43ecec16SMauro Carvalho Chehab 			break;
1369*43ecec16SMauro Carvalho Chehab 		case MFCINST_GOT_INST:
1370*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_init_dec(ctx);
1371*43ecec16SMauro Carvalho Chehab 			break;
1372*43ecec16SMauro Carvalho Chehab 		case MFCINST_HEAD_PARSED:
1373*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_run_init_dec_buffers(ctx);
1374*43ecec16SMauro Carvalho Chehab 			mfc_debug(1, "head parsed\n");
1375*43ecec16SMauro Carvalho Chehab 			break;
1376*43ecec16SMauro Carvalho Chehab 		case MFCINST_RES_CHANGE_INIT:
1377*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_res_change(ctx);
1378*43ecec16SMauro Carvalho Chehab 			break;
1379*43ecec16SMauro Carvalho Chehab 		case MFCINST_RES_CHANGE_FLUSH:
1380*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
1381*43ecec16SMauro Carvalho Chehab 			break;
1382*43ecec16SMauro Carvalho Chehab 		case MFCINST_RES_CHANGE_END:
1383*43ecec16SMauro Carvalho Chehab 			mfc_debug(2, "Finished remaining frames after resolution change\n");
1384*43ecec16SMauro Carvalho Chehab 			ctx->capture_state = QUEUE_FREE;
1385*43ecec16SMauro Carvalho Chehab 			mfc_debug(2, "Will re-init the codec\n");
1386*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_init_dec(ctx);
1387*43ecec16SMauro Carvalho Chehab 			break;
1388*43ecec16SMauro Carvalho Chehab 		default:
1389*43ecec16SMauro Carvalho Chehab 			ret = -EAGAIN;
1390*43ecec16SMauro Carvalho Chehab 		}
1391*43ecec16SMauro Carvalho Chehab 	} else if (ctx->type == MFCINST_ENCODER) {
1392*43ecec16SMauro Carvalho Chehab 		switch (ctx->state) {
1393*43ecec16SMauro Carvalho Chehab 		case MFCINST_FINISHING:
1394*43ecec16SMauro Carvalho Chehab 		case MFCINST_RUNNING:
1395*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_run_enc_frame(ctx);
1396*43ecec16SMauro Carvalho Chehab 			break;
1397*43ecec16SMauro Carvalho Chehab 		case MFCINST_INIT:
1398*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
1399*43ecec16SMauro Carvalho Chehab 					ctx);
1400*43ecec16SMauro Carvalho Chehab 			break;
1401*43ecec16SMauro Carvalho Chehab 		case MFCINST_RETURN_INST:
1402*43ecec16SMauro Carvalho Chehab 			ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
1403*43ecec16SMauro Carvalho Chehab 					ctx);
1404*43ecec16SMauro Carvalho Chehab 			break;
1405*43ecec16SMauro Carvalho Chehab 		case MFCINST_GOT_INST:
1406*43ecec16SMauro Carvalho Chehab 			s5p_mfc_run_init_enc(ctx);
1407*43ecec16SMauro Carvalho Chehab 			break;
1408*43ecec16SMauro Carvalho Chehab 		default:
1409*43ecec16SMauro Carvalho Chehab 			ret = -EAGAIN;
1410*43ecec16SMauro Carvalho Chehab 		}
1411*43ecec16SMauro Carvalho Chehab 	} else {
1412*43ecec16SMauro Carvalho Chehab 		mfc_err("Invalid context type: %d\n", ctx->type);
1413*43ecec16SMauro Carvalho Chehab 		ret = -EAGAIN;
1414*43ecec16SMauro Carvalho Chehab 	}
1415*43ecec16SMauro Carvalho Chehab 
1416*43ecec16SMauro Carvalho Chehab 	if (ret) {
1417*43ecec16SMauro Carvalho Chehab 		/* Free hardware lock */
1418*43ecec16SMauro Carvalho Chehab 		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
1419*43ecec16SMauro Carvalho Chehab 			mfc_err("Failed to unlock hardware\n");
1420*43ecec16SMauro Carvalho Chehab 
1421*43ecec16SMauro Carvalho Chehab 		/* This is indeed important, as no operation has been
1422*43ecec16SMauro Carvalho Chehab 		 * scheduled, reduce the clock count as no one will
1423*43ecec16SMauro Carvalho Chehab 		 * ever do this, because no interrupt related to this try_run
1424*43ecec16SMauro Carvalho Chehab 		 * will ever come from hardware. */
1425*43ecec16SMauro Carvalho Chehab 		s5p_mfc_clock_off();
1426*43ecec16SMauro Carvalho Chehab 	}
1427*43ecec16SMauro Carvalho Chehab }
1428*43ecec16SMauro Carvalho Chehab 
s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev * dev)1429*43ecec16SMauro Carvalho Chehab static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
1430*43ecec16SMauro Carvalho Chehab {
1431*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
1432*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
1433*43ecec16SMauro Carvalho Chehab 	mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
1434*43ecec16SMauro Carvalho Chehab }
1435*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev * dev)1436*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
1437*43ecec16SMauro Carvalho Chehab {
1438*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
1439*43ecec16SMauro Carvalho Chehab }
1440*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev * dev)1441*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
1442*43ecec16SMauro Carvalho Chehab {
1443*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
1444*43ecec16SMauro Carvalho Chehab }
1445*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev * dev)1446*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
1447*43ecec16SMauro Carvalho Chehab {
1448*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
1449*43ecec16SMauro Carvalho Chehab }
1450*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev * dev)1451*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
1452*43ecec16SMauro Carvalho Chehab {
1453*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
1454*43ecec16SMauro Carvalho Chehab }
1455*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev * dev)1456*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
1457*43ecec16SMauro Carvalho Chehab {
1458*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
1459*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_DECODE_FRAME_MASK;
1460*43ecec16SMauro Carvalho Chehab }
1461*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx * ctx)1462*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
1463*43ecec16SMauro Carvalho Chehab {
1464*43ecec16SMauro Carvalho Chehab 	return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
1465*43ecec16SMauro Carvalho Chehab 			S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
1466*43ecec16SMauro Carvalho Chehab 			S5P_FIMV_DECODE_FRAME_MASK;
1467*43ecec16SMauro Carvalho Chehab }
1468*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev * dev)1469*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
1470*43ecec16SMauro Carvalho Chehab {
1471*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
1472*43ecec16SMauro Carvalho Chehab }
1473*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev * dev)1474*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
1475*43ecec16SMauro Carvalho Chehab {
1476*43ecec16SMauro Carvalho Chehab 	int reason;
1477*43ecec16SMauro Carvalho Chehab 	reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
1478*43ecec16SMauro Carvalho Chehab 		S5P_FIMV_RISC2HOST_CMD_MASK;
1479*43ecec16SMauro Carvalho Chehab 	switch (reason) {
1480*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
1481*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
1482*43ecec16SMauro Carvalho Chehab 		break;
1483*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
1484*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
1485*43ecec16SMauro Carvalho Chehab 		break;
1486*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
1487*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
1488*43ecec16SMauro Carvalho Chehab 		break;
1489*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
1490*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
1491*43ecec16SMauro Carvalho Chehab 		break;
1492*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
1493*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
1494*43ecec16SMauro Carvalho Chehab 		break;
1495*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
1496*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
1497*43ecec16SMauro Carvalho Chehab 		break;
1498*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
1499*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
1500*43ecec16SMauro Carvalho Chehab 		break;
1501*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_SLEEP_RET:
1502*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_SLEEP_RET;
1503*43ecec16SMauro Carvalho Chehab 		break;
1504*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_WAKEUP_RET:
1505*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
1506*43ecec16SMauro Carvalho Chehab 		break;
1507*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
1508*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
1509*43ecec16SMauro Carvalho Chehab 		break;
1510*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
1511*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;
1512*43ecec16SMauro Carvalho Chehab 		break;
1513*43ecec16SMauro Carvalho Chehab 	case S5P_FIMV_R2H_CMD_ERR_RET:
1514*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_ERR_RET;
1515*43ecec16SMauro Carvalho Chehab 		break;
1516*43ecec16SMauro Carvalho Chehab 	default:
1517*43ecec16SMauro Carvalho Chehab 		reason = S5P_MFC_R2H_CMD_EMPTY;
1518*43ecec16SMauro Carvalho Chehab 	}
1519*43ecec16SMauro Carvalho Chehab 	return reason;
1520*43ecec16SMauro Carvalho Chehab }
1521*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_int_err_v5(struct s5p_mfc_dev * dev)1522*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
1523*43ecec16SMauro Carvalho Chehab {
1524*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
1525*43ecec16SMauro Carvalho Chehab }
1526*43ecec16SMauro Carvalho Chehab 
s5p_mfc_err_dec_v5(unsigned int err)1527*43ecec16SMauro Carvalho Chehab static int s5p_mfc_err_dec_v5(unsigned int err)
1528*43ecec16SMauro Carvalho Chehab {
1529*43ecec16SMauro Carvalho Chehab 	return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
1530*43ecec16SMauro Carvalho Chehab }
1531*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_img_width_v5(struct s5p_mfc_dev * dev)1532*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
1533*43ecec16SMauro Carvalho Chehab {
1534*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_HRESOL);
1535*43ecec16SMauro Carvalho Chehab }
1536*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_img_height_v5(struct s5p_mfc_dev * dev)1537*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
1538*43ecec16SMauro Carvalho Chehab {
1539*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_VRESOL);
1540*43ecec16SMauro Carvalho Chehab }
1541*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev * dev)1542*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
1543*43ecec16SMauro Carvalho Chehab {
1544*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
1545*43ecec16SMauro Carvalho Chehab }
1546*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev * dev)1547*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
1548*43ecec16SMauro Carvalho Chehab {
1549*43ecec16SMauro Carvalho Chehab 	/* NOP */
1550*43ecec16SMauro Carvalho Chehab 	return -1;
1551*43ecec16SMauro Carvalho Chehab }
1552*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev * dev)1553*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
1554*43ecec16SMauro Carvalho Chehab {
1555*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
1556*43ecec16SMauro Carvalho Chehab }
1557*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev * dev)1558*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
1559*43ecec16SMauro Carvalho Chehab {
1560*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
1561*43ecec16SMauro Carvalho Chehab }
1562*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev * dev)1563*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
1564*43ecec16SMauro Carvalho Chehab {
1565*43ecec16SMauro Carvalho Chehab 	return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
1566*43ecec16SMauro Carvalho Chehab }
1567*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev * dev)1568*43ecec16SMauro Carvalho Chehab static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
1569*43ecec16SMauro Carvalho Chehab {
1570*43ecec16SMauro Carvalho Chehab 	return -1;
1571*43ecec16SMauro Carvalho Chehab }
1572*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx * ctx)1573*43ecec16SMauro Carvalho Chehab static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
1574*43ecec16SMauro Carvalho Chehab {
1575*43ecec16SMauro Carvalho Chehab 	return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
1576*43ecec16SMauro Carvalho Chehab }
1577*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx * ctx)1578*43ecec16SMauro Carvalho Chehab static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
1579*43ecec16SMauro Carvalho Chehab {
1580*43ecec16SMauro Carvalho Chehab 	return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
1581*43ecec16SMauro Carvalho Chehab }
1582*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx * ctx)1583*43ecec16SMauro Carvalho Chehab static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
1584*43ecec16SMauro Carvalho Chehab {
1585*43ecec16SMauro Carvalho Chehab 	return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
1586*43ecec16SMauro Carvalho Chehab }
1587*43ecec16SMauro Carvalho Chehab 
s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx * ctx)1588*43ecec16SMauro Carvalho Chehab static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
1589*43ecec16SMauro Carvalho Chehab {
1590*43ecec16SMauro Carvalho Chehab 	return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
1591*43ecec16SMauro Carvalho Chehab }
1592*43ecec16SMauro Carvalho Chehab 
1593*43ecec16SMauro Carvalho Chehab /* Initialize opr function pointers for MFC v5 */
1594*43ecec16SMauro Carvalho Chehab static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
1595*43ecec16SMauro Carvalho Chehab 	.alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
1596*43ecec16SMauro Carvalho Chehab 	.release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
1597*43ecec16SMauro Carvalho Chehab 	.alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
1598*43ecec16SMauro Carvalho Chehab 	.release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
1599*43ecec16SMauro Carvalho Chehab 	.alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
1600*43ecec16SMauro Carvalho Chehab 	.release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
1601*43ecec16SMauro Carvalho Chehab 	.alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
1602*43ecec16SMauro Carvalho Chehab 	.release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
1603*43ecec16SMauro Carvalho Chehab 	.dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
1604*43ecec16SMauro Carvalho Chehab 	.enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
1605*43ecec16SMauro Carvalho Chehab 	.set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
1606*43ecec16SMauro Carvalho Chehab 	.set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
1607*43ecec16SMauro Carvalho Chehab 	.get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
1608*43ecec16SMauro Carvalho Chehab 	.try_run = s5p_mfc_try_run_v5,
1609*43ecec16SMauro Carvalho Chehab 	.clear_int_flags = s5p_mfc_clear_int_flags_v5,
1610*43ecec16SMauro Carvalho Chehab 	.get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
1611*43ecec16SMauro Carvalho Chehab 	.get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
1612*43ecec16SMauro Carvalho Chehab 	.get_dspl_status = s5p_mfc_get_dspl_status_v5,
1613*43ecec16SMauro Carvalho Chehab 	.get_dec_status = s5p_mfc_get_dec_status_v5,
1614*43ecec16SMauro Carvalho Chehab 	.get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
1615*43ecec16SMauro Carvalho Chehab 	.get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
1616*43ecec16SMauro Carvalho Chehab 	.get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
1617*43ecec16SMauro Carvalho Chehab 	.get_int_reason = s5p_mfc_get_int_reason_v5,
1618*43ecec16SMauro Carvalho Chehab 	.get_int_err = s5p_mfc_get_int_err_v5,
1619*43ecec16SMauro Carvalho Chehab 	.err_dec = s5p_mfc_err_dec_v5,
1620*43ecec16SMauro Carvalho Chehab 	.get_img_width = s5p_mfc_get_img_width_v5,
1621*43ecec16SMauro Carvalho Chehab 	.get_img_height = s5p_mfc_get_img_height_v5,
1622*43ecec16SMauro Carvalho Chehab 	.get_dpb_count = s5p_mfc_get_dpb_count_v5,
1623*43ecec16SMauro Carvalho Chehab 	.get_mv_count = s5p_mfc_get_mv_count_v5,
1624*43ecec16SMauro Carvalho Chehab 	.get_inst_no = s5p_mfc_get_inst_no_v5,
1625*43ecec16SMauro Carvalho Chehab 	.get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
1626*43ecec16SMauro Carvalho Chehab 	.get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
1627*43ecec16SMauro Carvalho Chehab 	.get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
1628*43ecec16SMauro Carvalho Chehab 	.get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
1629*43ecec16SMauro Carvalho Chehab 	.get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
1630*43ecec16SMauro Carvalho Chehab 	.get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
1631*43ecec16SMauro Carvalho Chehab 	.get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
1632*43ecec16SMauro Carvalho Chehab };
1633*43ecec16SMauro Carvalho Chehab 
s5p_mfc_init_hw_ops_v5(void)1634*43ecec16SMauro Carvalho Chehab struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
1635*43ecec16SMauro Carvalho Chehab {
1636*43ecec16SMauro Carvalho Chehab 	return &s5p_mfc_ops_v5;
1637*43ecec16SMauro Carvalho Chehab }
1638