]>
Commit | Line | Data |
---|---|---|
f96f3cfa JP |
1 | /* |
2 | * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |
3 | * | |
4 | * Samsung MFC (Multi Function Codec - FIMV) driver | |
5 | * This file contains hw related functions. | |
6 | * | |
7 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | |
8 | * http://www.samsung.com/ | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
14 | ||
15 | #undef DEBUG | |
16 | ||
17 | #include <linux/delay.h> | |
18 | #include <linux/mm.h> | |
19 | #include <linux/io.h> | |
20 | #include <linux/jiffies.h> | |
21 | #include <linux/firmware.h> | |
22 | #include <linux/err.h> | |
23 | #include <linux/sched.h> | |
24 | #include <linux/dma-mapping.h> | |
25 | ||
26 | #include <asm/cacheflush.h> | |
27 | ||
28 | #include "s5p_mfc_common.h" | |
29 | #include "s5p_mfc_cmd.h" | |
30 | #include "s5p_mfc_intr.h" | |
31 | #include "s5p_mfc_pm.h" | |
32 | #include "s5p_mfc_debug.h" | |
33 | #include "s5p_mfc_opr.h" | |
34 | #include "s5p_mfc_opr_v6.h" | |
35 | ||
36 | /* #define S5P_MFC_DEBUG_REGWRITE */ | |
37 | #ifdef S5P_MFC_DEBUG_REGWRITE | |
38 | #undef writel | |
39 | #define writel(v, r) \ | |
40 | do { \ | |
41 | pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v); \ | |
42 | __raw_writel(v, r); \ | |
43 | } while (0) | |
44 | #endif /* S5P_MFC_DEBUG_REGWRITE */ | |
45 | ||
6a9c6f68 KA |
46 | #define READL(reg) \ |
47 | (WARN_ON_ONCE(!(reg)) ? 0 : readl(reg)) | |
48 | #define WRITEL(data, reg) \ | |
49 | (WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg))) | |
f96f3cfa JP |
50 | |
51 | /* Allocate temporary buffers for decoding */ | |
b9571a57 | 52 | static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
53 | { |
54 | /* NOP */ | |
55 | ||
56 | return 0; | |
57 | } | |
58 | ||
59 | /* Release temproary buffers for decoding */ | |
b9571a57 | 60 | static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
61 | { |
62 | /* NOP */ | |
63 | } | |
64 | ||
f96f3cfa | 65 | /* Allocate codec buffers */ |
b9571a57 | 66 | static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
67 | { |
68 | struct s5p_mfc_dev *dev = ctx->dev; | |
69 | unsigned int mb_width, mb_height; | |
317b4ca4 | 70 | int ret; |
f96f3cfa JP |
71 | |
72 | mb_width = MB_WIDTH(ctx->img_width); | |
73 | mb_height = MB_HEIGHT(ctx->img_height); | |
74 | ||
75 | if (ctx->type == MFCINST_DECODER) { | |
76 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", | |
77 | ctx->luma_size, ctx->chroma_size, ctx->mv_size); | |
78 | mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count); | |
79 | } else if (ctx->type == MFCINST_ENCODER) { | |
80 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | |
81 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), | |
82 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); | |
debe6267 | 83 | |
f96f3cfa JP |
84 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * |
85 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, | |
86 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); | |
87 | ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * | |
88 | S5P_FIMV_CHROMA_MB_TO_PIXEL_V6, | |
89 | S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6); | |
90 | ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( | |
91 | ctx->img_width, ctx->img_height, | |
92 | mb_width, mb_height), | |
93 | S5P_FIMV_ME_BUFFER_ALIGN_V6); | |
94 | ||
95 | mfc_debug(2, "recon luma size: %d chroma size: %d\n", | |
96 | ctx->luma_dpb_size, ctx->chroma_dpb_size); | |
97 | } else { | |
98 | return -EINVAL; | |
99 | } | |
100 | ||
101 | /* Codecs have different memory requirements */ | |
102 | switch (ctx->codec_mode) { | |
103 | case S5P_MFC_CODEC_H264_DEC: | |
104 | case S5P_MFC_CODEC_H264_MVC_DEC: | |
105 | ctx->scratch_buf_size = | |
106 | S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( | |
107 | mb_width, | |
108 | mb_height); | |
109 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
110 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 111 | ctx->bank1.size = |
f96f3cfa JP |
112 | ctx->scratch_buf_size + |
113 | (ctx->mv_count * ctx->mv_size); | |
114 | break; | |
115 | case S5P_MFC_CODEC_MPEG4_DEC: | |
109b794c | 116 | if (IS_MFCV7_PLUS(dev)) { |
debe6267 AK |
117 | ctx->scratch_buf_size = |
118 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7( | |
119 | mb_width, | |
120 | mb_height); | |
121 | } else { | |
122 | ctx->scratch_buf_size = | |
123 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | |
124 | mb_width, | |
125 | mb_height); | |
126 | } | |
127 | ||
f96f3cfa JP |
128 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
129 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 130 | ctx->bank1.size = ctx->scratch_buf_size; |
f96f3cfa JP |
131 | break; |
132 | case S5P_MFC_CODEC_VC1RCV_DEC: | |
133 | case S5P_MFC_CODEC_VC1_DEC: | |
134 | ctx->scratch_buf_size = | |
135 | S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6( | |
136 | mb_width, | |
137 | mb_height); | |
138 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
139 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 140 | ctx->bank1.size = ctx->scratch_buf_size; |
f96f3cfa JP |
141 | break; |
142 | case S5P_MFC_CODEC_MPEG2_DEC: | |
317b4ca4 KD |
143 | ctx->bank1.size = 0; |
144 | ctx->bank2.size = 0; | |
f96f3cfa JP |
145 | break; |
146 | case S5P_MFC_CODEC_H263_DEC: | |
147 | ctx->scratch_buf_size = | |
148 | S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6( | |
149 | mb_width, | |
150 | mb_height); | |
151 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
152 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 153 | ctx->bank1.size = ctx->scratch_buf_size; |
f96f3cfa JP |
154 | break; |
155 | case S5P_MFC_CODEC_VP8_DEC: | |
156 | ctx->scratch_buf_size = | |
157 | S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( | |
158 | mb_width, | |
159 | mb_height); | |
160 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
161 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 162 | ctx->bank1.size = ctx->scratch_buf_size; |
f96f3cfa JP |
163 | break; |
164 | case S5P_MFC_CODEC_H264_ENC: | |
165 | ctx->scratch_buf_size = | |
166 | S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( | |
167 | mb_width, | |
168 | mb_height); | |
169 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
170 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 171 | ctx->bank1.size = |
f96f3cfa | 172 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
e9d98ddc | 173 | (ctx->pb_count * (ctx->luma_dpb_size + |
f96f3cfa | 174 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
317b4ca4 | 175 | ctx->bank2.size = 0; |
f96f3cfa JP |
176 | break; |
177 | case S5P_MFC_CODEC_MPEG4_ENC: | |
178 | case S5P_MFC_CODEC_H263_ENC: | |
179 | ctx->scratch_buf_size = | |
180 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6( | |
181 | mb_width, | |
182 | mb_height); | |
183 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
184 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
317b4ca4 | 185 | ctx->bank1.size = |
f96f3cfa | 186 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
e9d98ddc | 187 | (ctx->pb_count * (ctx->luma_dpb_size + |
f96f3cfa | 188 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
317b4ca4 | 189 | ctx->bank2.size = 0; |
f96f3cfa | 190 | break; |
3a967706 AK |
191 | case S5P_MFC_CODEC_VP8_ENC: |
192 | ctx->scratch_buf_size = | |
193 | S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( | |
194 | mb_width, | |
195 | mb_height); | |
196 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | |
197 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | |
198 | ctx->bank1.size = | |
199 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | |
200 | (ctx->pb_count * (ctx->luma_dpb_size + | |
201 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | |
202 | ctx->bank2.size = 0; | |
203 | break; | |
f96f3cfa JP |
204 | default: |
205 | break; | |
206 | } | |
207 | ||
208 | /* Allocate only if memory from bank 1 is necessary */ | |
317b4ca4 KD |
209 | if (ctx->bank1.size > 0) { |
210 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->bank1); | |
211 | if (ret) { | |
212 | mfc_err("Failed to allocate Bank1 memory\n"); | |
213 | return ret; | |
f96f3cfa | 214 | } |
317b4ca4 | 215 | BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
f96f3cfa | 216 | } |
f96f3cfa JP |
217 | return 0; |
218 | } | |
219 | ||
220 | /* Release buffers allocated for codec */ | |
b9571a57 | 221 | static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 222 | { |
317b4ca4 | 223 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); |
f96f3cfa JP |
224 | } |
225 | ||
226 | /* Allocate memory for instance data buffer */ | |
b9571a57 | 227 | static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
228 | { |
229 | struct s5p_mfc_dev *dev = ctx->dev; | |
230 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | |
317b4ca4 | 231 | int ret; |
f96f3cfa JP |
232 | |
233 | mfc_debug_enter(); | |
234 | ||
235 | switch (ctx->codec_mode) { | |
236 | case S5P_MFC_CODEC_H264_DEC: | |
237 | case S5P_MFC_CODEC_H264_MVC_DEC: | |
238 | ctx->ctx.size = buf_size->h264_dec_ctx; | |
239 | break; | |
240 | case S5P_MFC_CODEC_MPEG4_DEC: | |
241 | case S5P_MFC_CODEC_H263_DEC: | |
242 | case S5P_MFC_CODEC_VC1RCV_DEC: | |
243 | case S5P_MFC_CODEC_VC1_DEC: | |
244 | case S5P_MFC_CODEC_MPEG2_DEC: | |
245 | case S5P_MFC_CODEC_VP8_DEC: | |
246 | ctx->ctx.size = buf_size->other_dec_ctx; | |
247 | break; | |
248 | case S5P_MFC_CODEC_H264_ENC: | |
249 | ctx->ctx.size = buf_size->h264_enc_ctx; | |
250 | break; | |
251 | case S5P_MFC_CODEC_MPEG4_ENC: | |
252 | case S5P_MFC_CODEC_H263_ENC: | |
3a967706 | 253 | case S5P_MFC_CODEC_VP8_ENC: |
f96f3cfa JP |
254 | ctx->ctx.size = buf_size->other_enc_ctx; |
255 | break; | |
256 | default: | |
257 | ctx->ctx.size = 0; | |
258 | mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode); | |
259 | break; | |
260 | } | |
261 | ||
317b4ca4 KD |
262 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &ctx->ctx); |
263 | if (ret) { | |
264 | mfc_err("Failed to allocate instance buffer\n"); | |
265 | return ret; | |
f96f3cfa JP |
266 | } |
267 | ||
268 | memset(ctx->ctx.virt, 0, ctx->ctx.size); | |
269 | wmb(); | |
270 | ||
271 | mfc_debug_leave(); | |
272 | ||
273 | return 0; | |
274 | } | |
275 | ||
276 | /* Release instance buffer */ | |
b9571a57 | 277 | static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 278 | { |
317b4ca4 | 279 | s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); |
f96f3cfa JP |
280 | } |
281 | ||
282 | /* Allocate context buffers for SYS_INIT */ | |
b9571a57 | 283 | static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) |
f96f3cfa JP |
284 | { |
285 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | |
317b4ca4 | 286 | int ret; |
f96f3cfa JP |
287 | |
288 | mfc_debug_enter(); | |
289 | ||
317b4ca4 KD |
290 | dev->ctx_buf.size = buf_size->dev_ctx; |
291 | ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, &dev->ctx_buf); | |
292 | if (ret) { | |
293 | mfc_err("Failed to allocate device context buffer\n"); | |
294 | return ret; | |
f96f3cfa JP |
295 | } |
296 | ||
297 | memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx); | |
298 | wmb(); | |
299 | ||
300 | mfc_debug_leave(); | |
301 | ||
302 | return 0; | |
303 | } | |
304 | ||
305 | /* Release context buffers for SYS_INIT */ | |
b9571a57 | 306 | static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 307 | { |
317b4ca4 | 308 | s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf); |
f96f3cfa JP |
309 | } |
310 | ||
311 | static int calc_plane(int width, int height) | |
312 | { | |
313 | int mbX, mbY; | |
314 | ||
315 | mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6); | |
316 | mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6); | |
317 | ||
318 | if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6) | |
319 | mbY = (mbY + 1) / 2 * 2; | |
320 | ||
321 | return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) * | |
322 | (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6); | |
323 | } | |
324 | ||
b9571a57 | 325 | static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
326 | { |
327 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6); | |
328 | ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6); | |
329 | mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n" | |
330 | "buffer dimensions: %dx%d\n", ctx->img_width, | |
331 | ctx->img_height, ctx->buf_width, ctx->buf_height); | |
332 | ||
333 | ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height); | |
334 | ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1)); | |
335 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | |
336 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { | |
337 | ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width, | |
338 | ctx->img_height); | |
339 | ctx->mv_size = ALIGN(ctx->mv_size, 16); | |
340 | } else { | |
341 | ctx->mv_size = 0; | |
342 | } | |
343 | } | |
344 | ||
b9571a57 | 345 | static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
346 | { |
347 | unsigned int mb_width, mb_height; | |
348 | ||
349 | mb_width = MB_WIDTH(ctx->img_width); | |
350 | mb_height = MB_HEIGHT(ctx->img_height); | |
351 | ||
352 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); | |
353 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); | |
354 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); | |
debe6267 AK |
355 | |
356 | /* MFCv7 needs pad bytes for Luma and Chroma */ | |
109b794c | 357 | if (IS_MFCV7_PLUS(ctx->dev)) { |
debe6267 AK |
358 | ctx->luma_size += MFC_LUMA_PAD_BYTES_V7; |
359 | ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7; | |
360 | } | |
f96f3cfa JP |
361 | } |
362 | ||
363 | /* Set registers for decoding stream buffer */ | |
b9571a57 SK |
364 | static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, |
365 | int buf_addr, unsigned int start_num_byte, | |
366 | unsigned int strm_size) | |
f96f3cfa JP |
367 | { |
368 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 369 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
370 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; |
371 | ||
372 | mfc_debug_enter(); | |
373 | mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n" | |
374 | "buf_size: 0x%08x (%d)\n", | |
375 | ctx->inst_no, buf_addr, strm_size, strm_size); | |
6a9c6f68 KA |
376 | WRITEL(strm_size, mfc_regs->d_stream_data_size); |
377 | WRITEL(buf_addr, mfc_regs->d_cpb_buffer_addr); | |
378 | WRITEL(buf_size->cpb, mfc_regs->d_cpb_buffer_size); | |
379 | WRITEL(start_num_byte, mfc_regs->d_cpb_buffer_offset); | |
f96f3cfa JP |
380 | |
381 | mfc_debug_leave(); | |
382 | return 0; | |
383 | } | |
384 | ||
385 | /* Set decoding frame buffer */ | |
b9571a57 | 386 | static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
387 | { |
388 | unsigned int frame_size, i; | |
389 | unsigned int frame_size_ch, frame_size_mv; | |
390 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 391 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
392 | size_t buf_addr1; |
393 | int buf_size1; | |
394 | int align_gap; | |
395 | ||
317b4ca4 KD |
396 | buf_addr1 = ctx->bank1.dma; |
397 | buf_size1 = ctx->bank1.size; | |
f96f3cfa JP |
398 | |
399 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | |
400 | mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count); | |
401 | mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay); | |
402 | ||
6a9c6f68 KA |
403 | WRITEL(ctx->total_dpb_count, mfc_regs->d_num_dpb); |
404 | WRITEL(ctx->luma_size, mfc_regs->d_first_plane_dpb_size); | |
405 | WRITEL(ctx->chroma_size, mfc_regs->d_second_plane_dpb_size); | |
f96f3cfa | 406 | |
6a9c6f68 KA |
407 | WRITEL(buf_addr1, mfc_regs->d_scratch_buffer_addr); |
408 | WRITEL(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size); | |
f96f3cfa JP |
409 | buf_addr1 += ctx->scratch_buf_size; |
410 | buf_size1 -= ctx->scratch_buf_size; | |
411 | ||
412 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC || | |
413 | ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){ | |
6a9c6f68 KA |
414 | WRITEL(ctx->mv_size, mfc_regs->d_mv_buffer_size); |
415 | WRITEL(ctx->mv_count, mfc_regs->d_num_mv); | |
f96f3cfa JP |
416 | } |
417 | ||
418 | frame_size = ctx->luma_size; | |
419 | frame_size_ch = ctx->chroma_size; | |
420 | frame_size_mv = ctx->mv_size; | |
421 | mfc_debug(2, "Frame size: %d ch: %d mv: %d\n", | |
422 | frame_size, frame_size_ch, frame_size_mv); | |
423 | ||
424 | for (i = 0; i < ctx->total_dpb_count; i++) { | |
425 | /* Bank2 */ | |
426 | mfc_debug(2, "Luma %d: %x\n", i, | |
427 | ctx->dst_bufs[i].cookie.raw.luma); | |
428 | WRITEL(ctx->dst_bufs[i].cookie.raw.luma, | |
6a9c6f68 | 429 | mfc_regs->d_first_plane_dpb + i * 4); |
f96f3cfa JP |
430 | mfc_debug(2, "\tChroma %d: %x\n", i, |
431 | ctx->dst_bufs[i].cookie.raw.chroma); | |
432 | WRITEL(ctx->dst_bufs[i].cookie.raw.chroma, | |
6a9c6f68 | 433 | mfc_regs->d_second_plane_dpb + i * 4); |
f96f3cfa JP |
434 | } |
435 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | |
436 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { | |
437 | for (i = 0; i < ctx->mv_count; i++) { | |
438 | /* To test alignment */ | |
439 | align_gap = buf_addr1; | |
440 | buf_addr1 = ALIGN(buf_addr1, 16); | |
441 | align_gap = buf_addr1 - align_gap; | |
442 | buf_size1 -= align_gap; | |
443 | ||
444 | mfc_debug(2, "\tBuf1: %x, size: %d\n", | |
445 | buf_addr1, buf_size1); | |
6a9c6f68 | 446 | WRITEL(buf_addr1, mfc_regs->d_mv_buffer + i * 4); |
f96f3cfa JP |
447 | buf_addr1 += frame_size_mv; |
448 | buf_size1 -= frame_size_mv; | |
449 | } | |
450 | } | |
451 | ||
452 | mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n", | |
453 | buf_addr1, buf_size1, ctx->total_dpb_count); | |
454 | if (buf_size1 < 0) { | |
455 | mfc_debug(2, "Not enough memory has been allocated.\n"); | |
456 | return -ENOMEM; | |
457 | } | |
458 | ||
6a9c6f68 | 459 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
460 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
461 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); | |
462 | ||
463 | mfc_debug(2, "After setting buffers.\n"); | |
464 | return 0; | |
465 | } | |
466 | ||
467 | /* Set registers for encoding stream buffer */ | |
b9571a57 | 468 | static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, |
f96f3cfa JP |
469 | unsigned long addr, unsigned int size) |
470 | { | |
471 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 472 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa | 473 | |
6a9c6f68 KA |
474 | WRITEL(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */ |
475 | WRITEL(size, mfc_regs->e_stream_buffer_size); | |
f96f3cfa | 476 | |
4130eabc AH |
477 | mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n", |
478 | addr, size); | |
f96f3cfa JP |
479 | |
480 | return 0; | |
481 | } | |
482 | ||
b9571a57 | 483 | static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, |
f96f3cfa JP |
484 | unsigned long y_addr, unsigned long c_addr) |
485 | { | |
486 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 487 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa | 488 | |
6a9c6f68 KA |
489 | WRITEL(y_addr, mfc_regs->e_source_first_plane_addr); |
490 | WRITEL(c_addr, mfc_regs->e_source_second_plane_addr); | |
f96f3cfa | 491 | |
4130eabc AH |
492 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); |
493 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); | |
f96f3cfa JP |
494 | } |
495 | ||
b9571a57 | 496 | static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, |
f96f3cfa JP |
497 | unsigned long *y_addr, unsigned long *c_addr) |
498 | { | |
499 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 500 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
501 | unsigned long enc_recon_y_addr, enc_recon_c_addr; |
502 | ||
6a9c6f68 KA |
503 | *y_addr = READL(mfc_regs->e_encoded_source_first_plane_addr); |
504 | *c_addr = READL(mfc_regs->e_encoded_source_second_plane_addr); | |
f96f3cfa | 505 | |
6a9c6f68 KA |
506 | enc_recon_y_addr = READL(mfc_regs->e_recon_luma_dpb_addr); |
507 | enc_recon_c_addr = READL(mfc_regs->e_recon_chroma_dpb_addr); | |
f96f3cfa | 508 | |
4130eabc AH |
509 | mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr); |
510 | mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr); | |
f96f3cfa JP |
511 | } |
512 | ||
513 | /* Set encoding ref & codec buffer */ | |
b9571a57 | 514 | static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
515 | { |
516 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 517 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
4a9c85aa SK |
518 | size_t buf_addr1; |
519 | int i, buf_size1; | |
f96f3cfa JP |
520 | |
521 | mfc_debug_enter(); | |
522 | ||
317b4ca4 KD |
523 | buf_addr1 = ctx->bank1.dma; |
524 | buf_size1 = ctx->bank1.size; | |
f96f3cfa JP |
525 | |
526 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | |
527 | ||
e9d98ddc | 528 | for (i = 0; i < ctx->pb_count; i++) { |
6a9c6f68 | 529 | WRITEL(buf_addr1, mfc_regs->e_luma_dpb + (4 * i)); |
f96f3cfa | 530 | buf_addr1 += ctx->luma_dpb_size; |
6a9c6f68 | 531 | WRITEL(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i)); |
f96f3cfa | 532 | buf_addr1 += ctx->chroma_dpb_size; |
6a9c6f68 | 533 | WRITEL(buf_addr1, mfc_regs->e_me_buffer + (4 * i)); |
f96f3cfa JP |
534 | buf_addr1 += ctx->me_buffer_size; |
535 | buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size + | |
536 | ctx->me_buffer_size); | |
537 | } | |
538 | ||
6a9c6f68 KA |
539 | WRITEL(buf_addr1, mfc_regs->e_scratch_buffer_addr); |
540 | WRITEL(ctx->scratch_buf_size, mfc_regs->e_scratch_buffer_size); | |
f96f3cfa JP |
541 | buf_addr1 += ctx->scratch_buf_size; |
542 | buf_size1 -= ctx->scratch_buf_size; | |
543 | ||
6a9c6f68 | 544 | WRITEL(buf_addr1, mfc_regs->e_tmv_buffer0); |
f96f3cfa | 545 | buf_addr1 += ctx->tmv_buffer_size >> 1; |
6a9c6f68 | 546 | WRITEL(buf_addr1, mfc_regs->e_tmv_buffer1); |
f96f3cfa JP |
547 | buf_addr1 += ctx->tmv_buffer_size >> 1; |
548 | buf_size1 -= ctx->tmv_buffer_size; | |
549 | ||
550 | mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n", | |
e9d98ddc | 551 | buf_addr1, buf_size1, ctx->pb_count); |
f96f3cfa JP |
552 | if (buf_size1 < 0) { |
553 | mfc_debug(2, "Not enough memory has been allocated.\n"); | |
554 | return -ENOMEM; | |
555 | } | |
556 | ||
6a9c6f68 | 557 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
558 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
559 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); | |
560 | ||
561 | mfc_debug_leave(); | |
562 | ||
563 | return 0; | |
564 | } | |
565 | ||
566 | static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) | |
567 | { | |
568 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 569 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
570 | |
571 | /* multi-slice control */ | |
572 | /* multi-slice MB number or bit size */ | |
6a9c6f68 | 573 | WRITEL(ctx->slice_mode, mfc_regs->e_mslice_mode); |
f96f3cfa | 574 | if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { |
6a9c6f68 | 575 | WRITEL(ctx->slice_size.mb, mfc_regs->e_mslice_size_mb); |
f96f3cfa JP |
576 | } else if (ctx->slice_mode == |
577 | V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | |
6a9c6f68 | 578 | WRITEL(ctx->slice_size.bits, mfc_regs->e_mslice_size_bits); |
f96f3cfa | 579 | } else { |
6a9c6f68 KA |
580 | WRITEL(0x0, mfc_regs->e_mslice_size_mb); |
581 | WRITEL(0x0, mfc_regs->e_mslice_size_bits); | |
f96f3cfa JP |
582 | } |
583 | ||
584 | return 0; | |
585 | } | |
586 | ||
587 | static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) | |
588 | { | |
589 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 590 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
591 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
592 | unsigned int reg = 0; | |
593 | ||
594 | mfc_debug_enter(); | |
595 | ||
596 | /* width */ | |
6a9c6f68 | 597 | WRITEL(ctx->img_width, mfc_regs->e_frame_width); /* 16 align */ |
f96f3cfa | 598 | /* height */ |
6a9c6f68 | 599 | WRITEL(ctx->img_height, mfc_regs->e_frame_height); /* 16 align */ |
f96f3cfa JP |
600 | |
601 | /* cropped width */ | |
6a9c6f68 | 602 | WRITEL(ctx->img_width, mfc_regs->e_cropped_frame_width); |
f96f3cfa | 603 | /* cropped height */ |
6a9c6f68 | 604 | WRITEL(ctx->img_height, mfc_regs->e_cropped_frame_height); |
f96f3cfa | 605 | /* cropped offset */ |
6a9c6f68 | 606 | WRITEL(0x0, mfc_regs->e_frame_crop_offset); |
f96f3cfa JP |
607 | |
608 | /* pictype : IDR period */ | |
609 | reg = 0; | |
610 | reg |= p->gop_size & 0xFFFF; | |
6a9c6f68 | 611 | WRITEL(reg, mfc_regs->e_gop_config); |
f96f3cfa JP |
612 | |
613 | /* multi-slice control */ | |
614 | /* multi-slice MB number or bit size */ | |
615 | ctx->slice_mode = p->slice_mode; | |
616 | reg = 0; | |
617 | if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { | |
618 | reg |= (0x1 << 3); | |
6a9c6f68 | 619 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
620 | ctx->slice_size.mb = p->slice_mb; |
621 | } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | |
622 | reg |= (0x1 << 3); | |
6a9c6f68 | 623 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
624 | ctx->slice_size.bits = p->slice_bit; |
625 | } else { | |
626 | reg &= ~(0x1 << 3); | |
6a9c6f68 | 627 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
628 | } |
629 | ||
630 | s5p_mfc_set_slice_mode(ctx); | |
631 | ||
632 | /* cyclic intra refresh */ | |
6a9c6f68 KA |
633 | WRITEL(p->intra_refresh_mb, mfc_regs->e_ir_size); |
634 | reg = READL(mfc_regs->e_enc_options); | |
f96f3cfa JP |
635 | if (p->intra_refresh_mb == 0) |
636 | reg &= ~(0x1 << 4); | |
637 | else | |
638 | reg |= (0x1 << 4); | |
6a9c6f68 | 639 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
640 | |
641 | /* 'NON_REFERENCE_STORE_ENABLE' for debugging */ | |
6a9c6f68 | 642 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa | 643 | reg &= ~(0x1 << 9); |
6a9c6f68 | 644 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
645 | |
646 | /* memory structure cur. frame */ | |
647 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) { | |
648 | /* 0: Linear, 1: 2D tiled*/ | |
6a9c6f68 | 649 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa | 650 | reg &= ~(0x1 << 7); |
6a9c6f68 | 651 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa | 652 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
6a9c6f68 | 653 | WRITEL(0x0, mfc_regs->pixel_format); |
f96f3cfa JP |
654 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) { |
655 | /* 0: Linear, 1: 2D tiled*/ | |
6a9c6f68 | 656 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa | 657 | reg &= ~(0x1 << 7); |
6a9c6f68 | 658 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa | 659 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
6a9c6f68 | 660 | WRITEL(0x1, mfc_regs->pixel_format); |
f96f3cfa JP |
661 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { |
662 | /* 0: Linear, 1: 2D tiled*/ | |
6a9c6f68 | 663 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa | 664 | reg |= (0x1 << 7); |
6a9c6f68 | 665 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa | 666 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
6a9c6f68 | 667 | WRITEL(0x0, mfc_regs->pixel_format); |
f96f3cfa JP |
668 | } |
669 | ||
670 | /* memory structure recon. frame */ | |
671 | /* 0: Linear, 1: 2D tiled */ | |
6a9c6f68 | 672 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa | 673 | reg |= (0x1 << 8); |
6a9c6f68 | 674 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
675 | |
676 | /* padding control & value */ | |
6a9c6f68 | 677 | WRITEL(0x0, mfc_regs->e_padding_ctrl); |
f96f3cfa JP |
678 | if (p->pad) { |
679 | reg = 0; | |
680 | /** enable */ | |
681 | reg |= (1 << 31); | |
682 | /** cr value */ | |
683 | reg |= ((p->pad_cr & 0xFF) << 16); | |
684 | /** cb value */ | |
685 | reg |= ((p->pad_cb & 0xFF) << 8); | |
686 | /** y value */ | |
687 | reg |= p->pad_luma & 0xFF; | |
6a9c6f68 | 688 | WRITEL(reg, mfc_regs->e_padding_ctrl); |
f96f3cfa JP |
689 | } |
690 | ||
691 | /* rate control config. */ | |
692 | reg = 0; | |
693 | /* frame-level rate control */ | |
694 | reg |= ((p->rc_frame & 0x1) << 9); | |
6a9c6f68 | 695 | WRITEL(reg, mfc_regs->e_rc_config); |
f96f3cfa JP |
696 | |
697 | /* bit rate */ | |
698 | if (p->rc_frame) | |
699 | WRITEL(p->rc_bitrate, | |
6a9c6f68 | 700 | mfc_regs->e_rc_bit_rate); |
f96f3cfa | 701 | else |
6a9c6f68 | 702 | WRITEL(1, mfc_regs->e_rc_bit_rate); |
f96f3cfa JP |
703 | |
704 | /* reaction coefficient */ | |
705 | if (p->rc_frame) { | |
706 | if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */ | |
6a9c6f68 | 707 | WRITEL(1, mfc_regs->e_rc_mode); |
f96f3cfa | 708 | else /* loose CBR */ |
6a9c6f68 | 709 | WRITEL(2, mfc_regs->e_rc_mode); |
f96f3cfa JP |
710 | } |
711 | ||
712 | /* seq header ctrl */ | |
6a9c6f68 | 713 | reg = READL(mfc_regs->e_enc_options); |
f96f3cfa JP |
714 | reg &= ~(0x1 << 2); |
715 | reg |= ((p->seq_hdr_mode & 0x1) << 2); | |
716 | ||
717 | /* frame skip mode */ | |
718 | reg &= ~(0x3); | |
719 | reg |= (p->frame_skip_mode & 0x3); | |
6a9c6f68 | 720 | WRITEL(reg, mfc_regs->e_enc_options); |
f96f3cfa JP |
721 | |
722 | /* 'DROP_CONTROL_ENABLE', disable */ | |
6a9c6f68 | 723 | reg = READL(mfc_regs->e_rc_config); |
f96f3cfa | 724 | reg &= ~(0x1 << 10); |
6a9c6f68 | 725 | WRITEL(reg, mfc_regs->e_rc_config); |
f96f3cfa JP |
726 | |
727 | /* setting for MV range [16, 256] */ | |
a378a320 | 728 | reg = (p->mv_h_range & S5P_FIMV_E_MV_RANGE_V6_MASK); |
6a9c6f68 | 729 | WRITEL(reg, mfc_regs->e_mv_hor_range); |
f96f3cfa | 730 | |
a378a320 | 731 | reg = (p->mv_v_range & S5P_FIMV_E_MV_RANGE_V6_MASK); |
6a9c6f68 | 732 | WRITEL(reg, mfc_regs->e_mv_ver_range); |
f96f3cfa | 733 | |
6a9c6f68 KA |
734 | WRITEL(0x0, mfc_regs->e_frame_insertion); |
735 | WRITEL(0x0, mfc_regs->e_roi_buffer_addr); | |
736 | WRITEL(0x0, mfc_regs->e_param_change); | |
737 | WRITEL(0x0, mfc_regs->e_rc_roi_ctrl); | |
738 | WRITEL(0x0, mfc_regs->e_picture_tag); | |
f96f3cfa | 739 | |
6a9c6f68 KA |
740 | WRITEL(0x0, mfc_regs->e_bit_count_enable); |
741 | WRITEL(0x0, mfc_regs->e_max_bit_count); | |
742 | WRITEL(0x0, mfc_regs->e_min_bit_count); | |
f96f3cfa | 743 | |
6a9c6f68 KA |
744 | WRITEL(0x0, mfc_regs->e_metadata_buffer_addr); |
745 | WRITEL(0x0, mfc_regs->e_metadata_buffer_size); | |
f96f3cfa JP |
746 | |
747 | mfc_debug_leave(); | |
748 | ||
749 | return 0; | |
750 | } | |
751 | ||
752 | static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) | |
753 | { | |
754 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 755 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
756 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
757 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; | |
758 | unsigned int reg = 0; | |
759 | int i; | |
760 | ||
761 | mfc_debug_enter(); | |
762 | ||
763 | s5p_mfc_set_enc_params(ctx); | |
764 | ||
765 | /* pictype : number of B */ | |
6a9c6f68 | 766 | reg = READL(mfc_regs->e_gop_config); |
f96f3cfa JP |
767 | reg &= ~(0x3 << 16); |
768 | reg |= ((p->num_b_frame & 0x3) << 16); | |
6a9c6f68 | 769 | WRITEL(reg, mfc_regs->e_gop_config); |
f96f3cfa JP |
770 | |
771 | /* profile & level */ | |
772 | reg = 0; | |
773 | /** level */ | |
774 | reg |= ((p_h264->level & 0xFF) << 8); | |
775 | /** profile - 0 ~ 3 */ | |
776 | reg |= p_h264->profile & 0x3F; | |
6a9c6f68 | 777 | WRITEL(reg, mfc_regs->e_picture_profile); |
f96f3cfa JP |
778 | |
779 | /* rate control config. */ | |
6a9c6f68 | 780 | reg = READL(mfc_regs->e_rc_config); |
f96f3cfa JP |
781 | /** macroblock level rate control */ |
782 | reg &= ~(0x1 << 8); | |
783 | reg |= ((p->rc_mb & 0x1) << 8); | |
6a9c6f68 KA |
784 | WRITEL(reg, mfc_regs->e_rc_config); |
785 | ||
f96f3cfa JP |
786 | /** frame QP */ |
787 | reg &= ~(0x3F); | |
788 | reg |= p_h264->rc_frame_qp & 0x3F; | |
6a9c6f68 | 789 | WRITEL(reg, mfc_regs->e_rc_config); |
f96f3cfa JP |
790 | |
791 | /* max & min value of QP */ | |
792 | reg = 0; | |
793 | /** max QP */ | |
794 | reg |= ((p_h264->rc_max_qp & 0x3F) << 8); | |
795 | /** min QP */ | |
796 | reg |= p_h264->rc_min_qp & 0x3F; | |
6a9c6f68 | 797 | WRITEL(reg, mfc_regs->e_rc_qp_bound); |
f96f3cfa JP |
798 | |
799 | /* other QPs */ | |
6a9c6f68 | 800 | WRITEL(0x0, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
801 | if (!p->rc_frame && !p->rc_mb) { |
802 | reg = 0; | |
803 | reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16); | |
804 | reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8); | |
805 | reg |= p_h264->rc_frame_qp & 0x3F; | |
6a9c6f68 | 806 | WRITEL(reg, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
807 | } |
808 | ||
809 | /* frame rate */ | |
810 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | |
811 | reg = 0; | |
812 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | |
813 | reg |= p->rc_framerate_denom & 0xFFFF; | |
6a9c6f68 | 814 | WRITEL(reg, mfc_regs->e_rc_frame_rate); |
f96f3cfa JP |
815 | } |
816 | ||
817 | /* vbv buffer size */ | |
818 | if (p->frame_skip_mode == | |
819 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | |
820 | WRITEL(p_h264->cpb_size & 0xFFFF, | |
6a9c6f68 | 821 | mfc_regs->e_vbv_buffer_size); |
f96f3cfa JP |
822 | |
823 | if (p->rc_frame) | |
6a9c6f68 | 824 | WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); |
f96f3cfa JP |
825 | } |
826 | ||
827 | /* interlace */ | |
828 | reg = 0; | |
829 | reg |= ((p_h264->interlace & 0x1) << 3); | |
6a9c6f68 | 830 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
831 | |
832 | /* height */ | |
833 | if (p_h264->interlace) { | |
834 | WRITEL(ctx->img_height >> 1, | |
6a9c6f68 | 835 | mfc_regs->e_frame_height); /* 32 align */ |
f96f3cfa JP |
836 | /* cropped height */ |
837 | WRITEL(ctx->img_height >> 1, | |
6a9c6f68 | 838 | mfc_regs->e_cropped_frame_height); |
f96f3cfa JP |
839 | } |
840 | ||
841 | /* loop filter ctrl */ | |
6a9c6f68 | 842 | reg = READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
843 | reg &= ~(0x3 << 1); |
844 | reg |= ((p_h264->loop_filter_mode & 0x3) << 1); | |
6a9c6f68 | 845 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
846 | |
847 | /* loopfilter alpha offset */ | |
848 | if (p_h264->loop_filter_alpha < 0) { | |
849 | reg = 0x10; | |
850 | reg |= (0xFF - p_h264->loop_filter_alpha) + 1; | |
851 | } else { | |
852 | reg = 0x00; | |
853 | reg |= (p_h264->loop_filter_alpha & 0xF); | |
854 | } | |
6a9c6f68 | 855 | WRITEL(reg, mfc_regs->e_h264_lf_alpha_offset); |
f96f3cfa JP |
856 | |
857 | /* loopfilter beta offset */ | |
858 | if (p_h264->loop_filter_beta < 0) { | |
859 | reg = 0x10; | |
860 | reg |= (0xFF - p_h264->loop_filter_beta) + 1; | |
861 | } else { | |
862 | reg = 0x00; | |
863 | reg |= (p_h264->loop_filter_beta & 0xF); | |
864 | } | |
6a9c6f68 | 865 | WRITEL(reg, mfc_regs->e_h264_lf_beta_offset); |
f96f3cfa JP |
866 | |
867 | /* entropy coding mode */ | |
6a9c6f68 | 868 | reg = READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
869 | reg &= ~(0x1); |
870 | reg |= p_h264->entropy_mode & 0x1; | |
6a9c6f68 | 871 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
872 | |
873 | /* number of ref. picture */ | |
6a9c6f68 | 874 | reg = READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
875 | reg &= ~(0x1 << 7); |
876 | reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7); | |
6a9c6f68 | 877 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
878 | |
879 | /* 8x8 transform enable */ | |
6a9c6f68 | 880 | reg = READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
881 | reg &= ~(0x3 << 12); |
882 | reg |= ((p_h264->_8x8_transform & 0x3) << 12); | |
6a9c6f68 | 883 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
884 | |
885 | /* macroblock adaptive scaling features */ | |
6a9c6f68 | 886 | WRITEL(0x0, mfc_regs->e_mb_rc_config); |
f96f3cfa JP |
887 | if (p->rc_mb) { |
888 | reg = 0; | |
889 | /** dark region */ | |
890 | reg |= ((p_h264->rc_mb_dark & 0x1) << 3); | |
891 | /** smooth region */ | |
892 | reg |= ((p_h264->rc_mb_smooth & 0x1) << 2); | |
893 | /** static region */ | |
894 | reg |= ((p_h264->rc_mb_static & 0x1) << 1); | |
895 | /** high activity region */ | |
896 | reg |= p_h264->rc_mb_activity & 0x1; | |
6a9c6f68 | 897 | WRITEL(reg, mfc_regs->e_mb_rc_config); |
f96f3cfa JP |
898 | } |
899 | ||
900 | /* aspect ratio VUI */ | |
6a9c6f68 | 901 | READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
902 | reg &= ~(0x1 << 5); |
903 | reg |= ((p_h264->vui_sar & 0x1) << 5); | |
6a9c6f68 | 904 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa | 905 | |
6a9c6f68 KA |
906 | WRITEL(0x0, mfc_regs->e_aspect_ratio); |
907 | WRITEL(0x0, mfc_regs->e_extended_sar); | |
f96f3cfa JP |
908 | if (p_h264->vui_sar) { |
909 | /* aspect ration IDC */ | |
910 | reg = 0; | |
911 | reg |= p_h264->vui_sar_idc & 0xFF; | |
6a9c6f68 | 912 | WRITEL(reg, mfc_regs->e_aspect_ratio); |
f96f3cfa JP |
913 | if (p_h264->vui_sar_idc == 0xFF) { |
914 | /* extended SAR */ | |
915 | reg = 0; | |
916 | reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16; | |
917 | reg |= p_h264->vui_ext_sar_height & 0xFFFF; | |
6a9c6f68 | 918 | WRITEL(reg, mfc_regs->e_extended_sar); |
f96f3cfa JP |
919 | } |
920 | } | |
921 | ||
922 | /* intra picture period for H.264 open GOP */ | |
923 | /* control */ | |
6a9c6f68 | 924 | READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
925 | reg &= ~(0x1 << 4); |
926 | reg |= ((p_h264->open_gop & 0x1) << 4); | |
6a9c6f68 KA |
927 | WRITEL(reg, mfc_regs->e_h264_options); |
928 | ||
f96f3cfa | 929 | /* value */ |
6a9c6f68 | 930 | WRITEL(0x0, mfc_regs->e_h264_i_period); |
f96f3cfa JP |
931 | if (p_h264->open_gop) { |
932 | reg = 0; | |
933 | reg |= p_h264->open_gop_size & 0xFFFF; | |
6a9c6f68 | 934 | WRITEL(reg, mfc_regs->e_h264_i_period); |
f96f3cfa JP |
935 | } |
936 | ||
937 | /* 'WEIGHTED_BI_PREDICTION' for B is disable */ | |
6a9c6f68 | 938 | READL(mfc_regs->e_h264_options); |
f96f3cfa | 939 | reg &= ~(0x3 << 9); |
6a9c6f68 | 940 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
941 | |
942 | /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ | |
6a9c6f68 | 943 | READL(mfc_regs->e_h264_options); |
f96f3cfa | 944 | reg &= ~(0x1 << 14); |
6a9c6f68 | 945 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
946 | |
947 | /* ASO */ | |
6a9c6f68 | 948 | READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
949 | reg &= ~(0x1 << 6); |
950 | reg |= ((p_h264->aso & 0x1) << 6); | |
6a9c6f68 | 951 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
952 | |
953 | /* hier qp enable */ | |
6a9c6f68 | 954 | READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
955 | reg &= ~(0x1 << 8); |
956 | reg |= ((p_h264->open_gop & 0x1) << 8); | |
6a9c6f68 | 957 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
958 | reg = 0; |
959 | if (p_h264->hier_qp && p_h264->hier_qp_layer) { | |
960 | reg |= (p_h264->hier_qp_type & 0x1) << 0x3; | |
961 | reg |= p_h264->hier_qp_layer & 0x7; | |
6a9c6f68 | 962 | WRITEL(reg, mfc_regs->e_h264_num_t_layer); |
f96f3cfa | 963 | /* QP value for each layer */ |
6a9c6f68 KA |
964 | for (i = 0; i < p_h264->hier_qp_layer && |
965 | i < ARRAY_SIZE(p_h264->hier_qp_layer_qp); i++) { | |
f96f3cfa | 966 | WRITEL(p_h264->hier_qp_layer_qp[i], |
6a9c6f68 KA |
967 | mfc_regs->e_h264_hierarchical_qp_layer0 |
968 | + i * 4); | |
969 | } | |
f96f3cfa JP |
970 | } |
971 | /* number of coding layer should be zero when hierarchical is disable */ | |
6a9c6f68 | 972 | WRITEL(reg, mfc_regs->e_h264_num_t_layer); |
f96f3cfa JP |
973 | |
974 | /* frame packing SEI generation */ | |
6a9c6f68 | 975 | READL(mfc_regs->e_h264_options); |
f96f3cfa JP |
976 | reg &= ~(0x1 << 25); |
977 | reg |= ((p_h264->sei_frame_packing & 0x1) << 25); | |
6a9c6f68 | 978 | WRITEL(reg, mfc_regs->e_h264_options); |
f96f3cfa JP |
979 | if (p_h264->sei_frame_packing) { |
980 | reg = 0; | |
981 | /** current frame0 flag */ | |
982 | reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2); | |
983 | /** arrangement type */ | |
984 | reg |= p_h264->sei_fp_arrangement_type & 0x3; | |
6a9c6f68 | 985 | WRITEL(reg, mfc_regs->e_h264_frame_packing_sei_info); |
f96f3cfa JP |
986 | } |
987 | ||
988 | if (p_h264->fmo) { | |
989 | switch (p_h264->fmo_map_type) { | |
990 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES: | |
991 | if (p_h264->fmo_slice_grp > 4) | |
992 | p_h264->fmo_slice_grp = 4; | |
993 | for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++) | |
994 | WRITEL(p_h264->fmo_run_len[i] - 1, | |
6a9c6f68 KA |
995 | mfc_regs->e_h264_fmo_run_length_minus1_0 |
996 | + i * 4); | |
f96f3cfa JP |
997 | break; |
998 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES: | |
999 | if (p_h264->fmo_slice_grp > 4) | |
1000 | p_h264->fmo_slice_grp = 4; | |
1001 | break; | |
1002 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN: | |
1003 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN: | |
1004 | if (p_h264->fmo_slice_grp > 2) | |
1005 | p_h264->fmo_slice_grp = 2; | |
1006 | WRITEL(p_h264->fmo_chg_dir & 0x1, | |
6a9c6f68 | 1007 | mfc_regs->e_h264_fmo_slice_grp_change_dir); |
f96f3cfa JP |
1008 | /* the valid range is 0 ~ number of macroblocks -1 */ |
1009 | WRITEL(p_h264->fmo_chg_rate, | |
6a9c6f68 | 1010 | mfc_regs->e_h264_fmo_slice_grp_change_rate_minus1); |
f96f3cfa JP |
1011 | break; |
1012 | default: | |
1013 | mfc_err("Unsupported map type for FMO: %d\n", | |
1014 | p_h264->fmo_map_type); | |
1015 | p_h264->fmo_map_type = 0; | |
1016 | p_h264->fmo_slice_grp = 1; | |
1017 | break; | |
1018 | } | |
1019 | ||
1020 | WRITEL(p_h264->fmo_map_type, | |
6a9c6f68 | 1021 | mfc_regs->e_h264_fmo_slice_grp_map_type); |
f96f3cfa | 1022 | WRITEL(p_h264->fmo_slice_grp - 1, |
6a9c6f68 | 1023 | mfc_regs->e_h264_fmo_num_slice_grp_minus1); |
f96f3cfa | 1024 | } else { |
6a9c6f68 | 1025 | WRITEL(0, mfc_regs->e_h264_fmo_num_slice_grp_minus1); |
f96f3cfa JP |
1026 | } |
1027 | ||
1028 | mfc_debug_leave(); | |
1029 | ||
1030 | return 0; | |
1031 | } | |
1032 | ||
1033 | static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) | |
1034 | { | |
1035 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1036 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1037 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
1038 | struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; | |
1039 | unsigned int reg = 0; | |
1040 | ||
1041 | mfc_debug_enter(); | |
1042 | ||
1043 | s5p_mfc_set_enc_params(ctx); | |
1044 | ||
1045 | /* pictype : number of B */ | |
6a9c6f68 | 1046 | reg = READL(mfc_regs->e_gop_config); |
f96f3cfa JP |
1047 | reg &= ~(0x3 << 16); |
1048 | reg |= ((p->num_b_frame & 0x3) << 16); | |
6a9c6f68 | 1049 | WRITEL(reg, mfc_regs->e_gop_config); |
f96f3cfa JP |
1050 | |
1051 | /* profile & level */ | |
1052 | reg = 0; | |
1053 | /** level */ | |
1054 | reg |= ((p_mpeg4->level & 0xFF) << 8); | |
1055 | /** profile - 0 ~ 1 */ | |
1056 | reg |= p_mpeg4->profile & 0x3F; | |
6a9c6f68 | 1057 | WRITEL(reg, mfc_regs->e_picture_profile); |
f96f3cfa JP |
1058 | |
1059 | /* rate control config. */ | |
6a9c6f68 | 1060 | reg = READL(mfc_regs->e_rc_config); |
f96f3cfa JP |
1061 | /** macroblock level rate control */ |
1062 | reg &= ~(0x1 << 8); | |
1063 | reg |= ((p->rc_mb & 0x1) << 8); | |
6a9c6f68 KA |
1064 | WRITEL(reg, mfc_regs->e_rc_config); |
1065 | ||
f96f3cfa JP |
1066 | /** frame QP */ |
1067 | reg &= ~(0x3F); | |
1068 | reg |= p_mpeg4->rc_frame_qp & 0x3F; | |
6a9c6f68 | 1069 | WRITEL(reg, mfc_regs->e_rc_config); |
f96f3cfa JP |
1070 | |
1071 | /* max & min value of QP */ | |
1072 | reg = 0; | |
1073 | /** max QP */ | |
1074 | reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8); | |
1075 | /** min QP */ | |
1076 | reg |= p_mpeg4->rc_min_qp & 0x3F; | |
6a9c6f68 | 1077 | WRITEL(reg, mfc_regs->e_rc_qp_bound); |
f96f3cfa JP |
1078 | |
1079 | /* other QPs */ | |
6a9c6f68 | 1080 | WRITEL(0x0, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
1081 | if (!p->rc_frame && !p->rc_mb) { |
1082 | reg = 0; | |
1083 | reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16); | |
1084 | reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8); | |
1085 | reg |= p_mpeg4->rc_frame_qp & 0x3F; | |
6a9c6f68 | 1086 | WRITEL(reg, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
1087 | } |
1088 | ||
1089 | /* frame rate */ | |
1090 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | |
1091 | reg = 0; | |
1092 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | |
1093 | reg |= p->rc_framerate_denom & 0xFFFF; | |
6a9c6f68 | 1094 | WRITEL(reg, mfc_regs->e_rc_frame_rate); |
f96f3cfa JP |
1095 | } |
1096 | ||
1097 | /* vbv buffer size */ | |
1098 | if (p->frame_skip_mode == | |
1099 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | |
6a9c6f68 | 1100 | WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); |
f96f3cfa JP |
1101 | |
1102 | if (p->rc_frame) | |
6a9c6f68 | 1103 | WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); |
f96f3cfa JP |
1104 | } |
1105 | ||
1106 | /* Disable HEC */ | |
6a9c6f68 KA |
1107 | WRITEL(0x0, mfc_regs->e_mpeg4_options); |
1108 | WRITEL(0x0, mfc_regs->e_mpeg4_hec_period); | |
f96f3cfa JP |
1109 | |
1110 | mfc_debug_leave(); | |
1111 | ||
1112 | return 0; | |
1113 | } | |
1114 | ||
1115 | static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | |
1116 | { | |
1117 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1118 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1119 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
1120 | struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; | |
1121 | unsigned int reg = 0; | |
1122 | ||
1123 | mfc_debug_enter(); | |
1124 | ||
1125 | s5p_mfc_set_enc_params(ctx); | |
1126 | ||
1127 | /* profile & level */ | |
1128 | reg = 0; | |
1129 | /** profile */ | |
1130 | reg |= (0x1 << 4); | |
6a9c6f68 | 1131 | WRITEL(reg, mfc_regs->e_picture_profile); |
f96f3cfa JP |
1132 | |
1133 | /* rate control config. */ | |
6a9c6f68 | 1134 | reg = READL(mfc_regs->e_rc_config); |
f96f3cfa JP |
1135 | /** macroblock level rate control */ |
1136 | reg &= ~(0x1 << 8); | |
1137 | reg |= ((p->rc_mb & 0x1) << 8); | |
6a9c6f68 KA |
1138 | WRITEL(reg, mfc_regs->e_rc_config); |
1139 | ||
f96f3cfa JP |
1140 | /** frame QP */ |
1141 | reg &= ~(0x3F); | |
1142 | reg |= p_h263->rc_frame_qp & 0x3F; | |
6a9c6f68 | 1143 | WRITEL(reg, mfc_regs->e_rc_config); |
f96f3cfa JP |
1144 | |
1145 | /* max & min value of QP */ | |
1146 | reg = 0; | |
1147 | /** max QP */ | |
1148 | reg |= ((p_h263->rc_max_qp & 0x3F) << 8); | |
1149 | /** min QP */ | |
1150 | reg |= p_h263->rc_min_qp & 0x3F; | |
6a9c6f68 | 1151 | WRITEL(reg, mfc_regs->e_rc_qp_bound); |
f96f3cfa JP |
1152 | |
1153 | /* other QPs */ | |
6a9c6f68 | 1154 | WRITEL(0x0, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
1155 | if (!p->rc_frame && !p->rc_mb) { |
1156 | reg = 0; | |
1157 | reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16); | |
1158 | reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8); | |
1159 | reg |= p_h263->rc_frame_qp & 0x3F; | |
6a9c6f68 | 1160 | WRITEL(reg, mfc_regs->e_fixed_picture_qp); |
f96f3cfa JP |
1161 | } |
1162 | ||
1163 | /* frame rate */ | |
1164 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | |
1165 | reg = 0; | |
1166 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | |
1167 | reg |= p->rc_framerate_denom & 0xFFFF; | |
6a9c6f68 | 1168 | WRITEL(reg, mfc_regs->e_rc_frame_rate); |
f96f3cfa JP |
1169 | } |
1170 | ||
1171 | /* vbv buffer size */ | |
1172 | if (p->frame_skip_mode == | |
1173 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | |
6a9c6f68 | 1174 | WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); |
f96f3cfa JP |
1175 | |
1176 | if (p->rc_frame) | |
6a9c6f68 | 1177 | WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); |
f96f3cfa JP |
1178 | } |
1179 | ||
1180 | mfc_debug_leave(); | |
1181 | ||
1182 | return 0; | |
1183 | } | |
1184 | ||
3a967706 AK |
1185 | static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) |
1186 | { | |
1187 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1188 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
3a967706 AK |
1189 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
1190 | struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8; | |
1191 | unsigned int reg = 0; | |
1192 | unsigned int val = 0; | |
1193 | ||
1194 | mfc_debug_enter(); | |
1195 | ||
1196 | s5p_mfc_set_enc_params(ctx); | |
1197 | ||
1198 | /* pictype : number of B */ | |
6a9c6f68 | 1199 | reg = READL(mfc_regs->e_gop_config); |
3a967706 AK |
1200 | reg &= ~(0x3 << 16); |
1201 | reg |= ((p->num_b_frame & 0x3) << 16); | |
6a9c6f68 | 1202 | WRITEL(reg, mfc_regs->e_gop_config); |
3a967706 | 1203 | |
bbd8f3fe KA |
1204 | /* profile - 0 ~ 3 */ |
1205 | reg = p_vp8->profile & 0x3; | |
6a9c6f68 | 1206 | WRITEL(reg, mfc_regs->e_picture_profile); |
3a967706 AK |
1207 | |
1208 | /* rate control config. */ | |
6a9c6f68 | 1209 | reg = READL(mfc_regs->e_rc_config); |
3a967706 AK |
1210 | /** macroblock level rate control */ |
1211 | reg &= ~(0x1 << 8); | |
1212 | reg |= ((p->rc_mb & 0x1) << 8); | |
6a9c6f68 | 1213 | WRITEL(reg, mfc_regs->e_rc_config); |
3a967706 AK |
1214 | |
1215 | /* frame rate */ | |
1216 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | |
1217 | reg = 0; | |
1218 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | |
1219 | reg |= p->rc_framerate_denom & 0xFFFF; | |
6a9c6f68 | 1220 | WRITEL(reg, mfc_regs->e_rc_frame_rate); |
3a967706 AK |
1221 | } |
1222 | ||
4773ab99 AK |
1223 | /* frame QP */ |
1224 | reg &= ~(0x7F); | |
1225 | reg |= p_vp8->rc_frame_qp & 0x7F; | |
6a9c6f68 | 1226 | WRITEL(reg, mfc_regs->e_rc_config); |
4773ab99 AK |
1227 | |
1228 | /* other QPs */ | |
6a9c6f68 | 1229 | WRITEL(0x0, mfc_regs->e_fixed_picture_qp); |
4773ab99 AK |
1230 | if (!p->rc_frame && !p->rc_mb) { |
1231 | reg = 0; | |
1232 | reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8); | |
1233 | reg |= p_vp8->rc_frame_qp & 0x7F; | |
6a9c6f68 | 1234 | WRITEL(reg, mfc_regs->e_fixed_picture_qp); |
4773ab99 AK |
1235 | } |
1236 | ||
1237 | /* max QP */ | |
1238 | reg = ((p_vp8->rc_max_qp & 0x7F) << 8); | |
1239 | /* min QP */ | |
1240 | reg |= p_vp8->rc_min_qp & 0x7F; | |
6a9c6f68 | 1241 | WRITEL(reg, mfc_regs->e_rc_qp_bound); |
4773ab99 | 1242 | |
3a967706 AK |
1243 | /* vbv buffer size */ |
1244 | if (p->frame_skip_mode == | |
1245 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | |
6a9c6f68 | 1246 | WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); |
3a967706 AK |
1247 | |
1248 | if (p->rc_frame) | |
6a9c6f68 | 1249 | WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); |
3a967706 AK |
1250 | } |
1251 | ||
1252 | /* VP8 specific params */ | |
1253 | reg = 0; | |
1254 | reg |= (p_vp8->imd_4x4 & 0x1) << 10; | |
1255 | switch (p_vp8->num_partitions) { | |
1256 | case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION: | |
1257 | val = 0; | |
1258 | break; | |
1259 | case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS: | |
1260 | val = 2; | |
1261 | break; | |
1262 | case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS: | |
1263 | val = 4; | |
1264 | break; | |
1265 | case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS: | |
1266 | val = 8; | |
1267 | break; | |
1268 | } | |
1269 | reg |= (val & 0xF) << 3; | |
1270 | reg |= (p_vp8->num_ref & 0x2); | |
6a9c6f68 | 1271 | WRITEL(reg, mfc_regs->e_vp8_options); |
3a967706 AK |
1272 | |
1273 | mfc_debug_leave(); | |
1274 | ||
1275 | return 0; | |
1276 | } | |
1277 | ||
f96f3cfa | 1278 | /* Initialize decoding */ |
b9571a57 | 1279 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
1280 | { |
1281 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1282 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1283 | unsigned int reg = 0; |
1284 | int fmo_aso_ctrl = 0; | |
1285 | ||
1286 | mfc_debug_enter(); | |
1287 | mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, | |
1288 | S5P_FIMV_CH_SEQ_HEADER_V6); | |
1289 | mfc_debug(2, "BUFs: %08x %08x %08x\n", | |
6a9c6f68 KA |
1290 | READL(mfc_regs->d_cpb_buffer_addr), |
1291 | READL(mfc_regs->d_cpb_buffer_addr), | |
1292 | READL(mfc_regs->d_cpb_buffer_addr)); | |
f96f3cfa JP |
1293 | |
1294 | /* FMO_ASO_CTRL - 0: Enable, 1: Disable */ | |
1295 | reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6); | |
1296 | ||
1297 | /* When user sets desplay_delay to 0, | |
1298 | * It works as "display_delay enable" and delay set to 0. | |
1299 | * If user wants display_delay disable, It should be | |
1300 | * set to negative value. */ | |
1301 | if (ctx->display_delay >= 0) { | |
1302 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); | |
6a9c6f68 | 1303 | WRITEL(ctx->display_delay, mfc_regs->d_display_delay); |
f96f3cfa | 1304 | } |
debe6267 | 1305 | |
109b794c | 1306 | if (IS_MFCV7_PLUS(dev)) { |
6a9c6f68 | 1307 | WRITEL(reg, mfc_regs->d_dec_options); |
debe6267 AK |
1308 | reg = 0; |
1309 | } | |
1310 | ||
f96f3cfa JP |
1311 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ |
1312 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { | |
1313 | mfc_debug(2, "Set loop filter to: %d\n", | |
1314 | ctx->loop_filter_mpeg4); | |
1315 | reg |= (ctx->loop_filter_mpeg4 << | |
1316 | S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6); | |
1317 | } | |
1318 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) | |
1319 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); | |
1320 | ||
109b794c | 1321 | if (IS_MFCV7_PLUS(dev)) |
6a9c6f68 | 1322 | WRITEL(reg, mfc_regs->d_init_buffer_options); |
debe6267 | 1323 | else |
6a9c6f68 | 1324 | WRITEL(reg, mfc_regs->d_dec_options); |
f96f3cfa JP |
1325 | |
1326 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | |
1327 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) | |
6a9c6f68 | 1328 | WRITEL(0x1, mfc_regs->pixel_format); |
f96f3cfa | 1329 | else |
6a9c6f68 | 1330 | WRITEL(0x0, mfc_regs->pixel_format); |
f96f3cfa | 1331 | |
debe6267 | 1332 | |
f96f3cfa | 1333 | /* sei parse */ |
6a9c6f68 | 1334 | WRITEL(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable); |
f96f3cfa | 1335 | |
6a9c6f68 | 1336 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
1337 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1338 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | |
1339 | ||
1340 | mfc_debug_leave(); | |
1341 | return 0; | |
1342 | } | |
1343 | ||
1344 | static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) | |
1345 | { | |
1346 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1347 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
8f23cc02 AK |
1348 | |
1349 | if (flush) { | |
1350 | dev->curr_ctx = ctx->num; | |
1351 | s5p_mfc_clean_ctx_int_flags(ctx); | |
6a9c6f68 | 1352 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
8f23cc02 AK |
1353 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1354 | S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); | |
1355 | } | |
f96f3cfa JP |
1356 | } |
1357 | ||
1358 | /* Decode a single frame */ | |
b9571a57 | 1359 | static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, |
f96f3cfa JP |
1360 | enum s5p_mfc_decode_arg last_frame) |
1361 | { | |
1362 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1363 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa | 1364 | |
6a9c6f68 KA |
1365 | WRITEL(ctx->dec_dst_flag, mfc_regs->d_available_dpb_flag_lower); |
1366 | WRITEL(ctx->slice_interface & 0x1, mfc_regs->d_slice_if_enable); | |
f96f3cfa | 1367 | |
6a9c6f68 | 1368 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
1369 | /* Issue different commands to instance basing on whether it |
1370 | * is the last frame or not. */ | |
1371 | switch (last_frame) { | |
1372 | case 0: | |
1373 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | |
1374 | S5P_FIMV_CH_FRAME_START_V6, NULL); | |
1375 | break; | |
1376 | case 1: | |
1377 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | |
1378 | S5P_FIMV_CH_LAST_FRAME_V6, NULL); | |
1379 | break; | |
1380 | default: | |
1381 | mfc_err("Unsupported last frame arg.\n"); | |
1382 | return -EINVAL; | |
1383 | } | |
1384 | ||
1385 | mfc_debug(2, "Decoding a usual frame.\n"); | |
1386 | return 0; | |
1387 | } | |
1388 | ||
b9571a57 | 1389 | static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
1390 | { |
1391 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1392 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1393 | |
1394 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | |
1395 | s5p_mfc_set_enc_params_h264(ctx); | |
1396 | else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC) | |
1397 | s5p_mfc_set_enc_params_mpeg4(ctx); | |
1398 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) | |
1399 | s5p_mfc_set_enc_params_h263(ctx); | |
3a967706 AK |
1400 | else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC) |
1401 | s5p_mfc_set_enc_params_vp8(ctx); | |
f96f3cfa JP |
1402 | else { |
1403 | mfc_err("Unknown codec for encoding (%x).\n", | |
1404 | ctx->codec_mode); | |
1405 | return -EINVAL; | |
1406 | } | |
1407 | ||
6a9c6f68 | 1408 | /* Set stride lengths for v7 & above */ |
109b794c | 1409 | if (IS_MFCV7_PLUS(dev)) { |
6a9c6f68 KA |
1410 | WRITEL(ctx->img_width, mfc_regs->e_source_first_plane_stride); |
1411 | WRITEL(ctx->img_width, mfc_regs->e_source_second_plane_stride); | |
debe6267 AK |
1412 | } |
1413 | ||
6a9c6f68 | 1414 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
1415 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1416 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | |
1417 | ||
1418 | return 0; | |
1419 | } | |
1420 | ||
b9571a57 | 1421 | static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
1422 | { |
1423 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1424 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1425 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
1426 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; | |
1427 | int i; | |
1428 | ||
1429 | if (p_h264->aso) { | |
6a9c6f68 | 1430 | for (i = 0; i < ARRAY_SIZE(p_h264->aso_slice_order); i++) { |
f96f3cfa | 1431 | WRITEL(p_h264->aso_slice_order[i], |
6a9c6f68 KA |
1432 | mfc_regs->e_h264_aso_slice_order_0 + i * 4); |
1433 | } | |
f96f3cfa JP |
1434 | } |
1435 | return 0; | |
1436 | } | |
1437 | ||
1438 | /* Encode a single frame */ | |
b9571a57 | 1439 | static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa JP |
1440 | { |
1441 | struct s5p_mfc_dev *dev = ctx->dev; | |
6a9c6f68 | 1442 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
f96f3cfa JP |
1443 | |
1444 | mfc_debug(2, "++\n"); | |
1445 | ||
1446 | /* memory structure cur. frame */ | |
1447 | ||
1448 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | |
1449 | s5p_mfc_h264_set_aso_slice_order_v6(ctx); | |
1450 | ||
1451 | s5p_mfc_set_slice_mode(ctx); | |
1452 | ||
6a9c6f68 | 1453 | WRITEL(ctx->inst_no, mfc_regs->instance_id); |
f96f3cfa JP |
1454 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1455 | S5P_FIMV_CH_FRAME_START_V6, NULL); | |
1456 | ||
1457 | mfc_debug(2, "--\n"); | |
1458 | ||
1459 | return 0; | |
1460 | } | |
1461 | ||
1462 | static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) | |
1463 | { | |
1464 | unsigned long flags; | |
1465 | int new_ctx; | |
1466 | int cnt; | |
1467 | ||
1468 | spin_lock_irqsave(&dev->condlock, flags); | |
1051e9b3 | 1469 | mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx, |
f96f3cfa JP |
1470 | dev->ctx_work_bits); |
1471 | new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; | |
1472 | cnt = 0; | |
1473 | while (!test_bit(new_ctx, &dev->ctx_work_bits)) { | |
1474 | new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; | |
1475 | cnt++; | |
1476 | if (cnt > MFC_NUM_CONTEXTS) { | |
1477 | /* No contexts to run */ | |
1478 | spin_unlock_irqrestore(&dev->condlock, flags); | |
1479 | return -EAGAIN; | |
1480 | } | |
1481 | } | |
1482 | spin_unlock_irqrestore(&dev->condlock, flags); | |
1483 | return new_ctx; | |
1484 | } | |
1485 | ||
1486 | static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx) | |
1487 | { | |
1488 | struct s5p_mfc_dev *dev = ctx->dev; | |
1489 | struct s5p_mfc_buf *temp_vb; | |
1490 | unsigned long flags; | |
1491 | ||
1492 | spin_lock_irqsave(&dev->irqlock, flags); | |
1493 | ||
1494 | /* Frames are being decoded */ | |
1495 | if (list_empty(&ctx->src_queue)) { | |
1496 | mfc_debug(2, "No src buffers.\n"); | |
1497 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1498 | return; | |
1499 | } | |
1500 | /* Get the next source buffer */ | |
1501 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | |
1502 | temp_vb->flags |= MFC_BUF_FLAG_USED; | |
1503 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | |
1504 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0); | |
1505 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1506 | ||
1507 | dev->curr_ctx = ctx->num; | |
1508 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1509 | s5p_mfc_decode_one_frame_v6(ctx, 1); | |
1510 | } | |
1511 | ||
1512 | static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) | |
1513 | { | |
1514 | struct s5p_mfc_dev *dev = ctx->dev; | |
1515 | struct s5p_mfc_buf *temp_vb; | |
1516 | unsigned long flags; | |
1517 | int last_frame = 0; | |
f96f3cfa | 1518 | |
a34026e7 KD |
1519 | if (ctx->state == MFCINST_FINISHING) { |
1520 | last_frame = MFC_DEC_LAST_FRAME; | |
1521 | s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0); | |
1522 | dev->curr_ctx = ctx->num; | |
1523 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1524 | s5p_mfc_decode_one_frame_v6(ctx, last_frame); | |
1525 | return 0; | |
1526 | } | |
f96f3cfa | 1527 | |
a34026e7 | 1528 | spin_lock_irqsave(&dev->irqlock, flags); |
f96f3cfa JP |
1529 | /* Frames are being decoded */ |
1530 | if (list_empty(&ctx->src_queue)) { | |
1531 | mfc_debug(2, "No src buffers.\n"); | |
1532 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1533 | return -EAGAIN; | |
1534 | } | |
1535 | /* Get the next source buffer */ | |
1536 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | |
1537 | temp_vb->flags |= MFC_BUF_FLAG_USED; | |
1538 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | |
1539 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | |
1540 | ctx->consumed_stream, | |
1541 | temp_vb->b->v4l2_planes[0].bytesused); | |
1542 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1543 | ||
f96f3cfa JP |
1544 | dev->curr_ctx = ctx->num; |
1545 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1546 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { | |
1547 | last_frame = 1; | |
1548 | mfc_debug(2, "Setting ctx->state to FINISHING\n"); | |
1549 | ctx->state = MFCINST_FINISHING; | |
1550 | } | |
1551 | s5p_mfc_decode_one_frame_v6(ctx, last_frame); | |
1552 | ||
1553 | return 0; | |
1554 | } | |
1555 | ||
1556 | static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | |
1557 | { | |
1558 | struct s5p_mfc_dev *dev = ctx->dev; | |
1559 | unsigned long flags; | |
1560 | struct s5p_mfc_buf *dst_mb; | |
1561 | struct s5p_mfc_buf *src_mb; | |
1562 | unsigned long src_y_addr, src_c_addr, dst_addr; | |
1563 | /* | |
1564 | unsigned int src_y_size, src_c_size; | |
1565 | */ | |
1566 | unsigned int dst_size; | |
f96f3cfa JP |
1567 | |
1568 | spin_lock_irqsave(&dev->irqlock, flags); | |
1569 | ||
1570 | if (list_empty(&ctx->src_queue)) { | |
1571 | mfc_debug(2, "no src buffers.\n"); | |
1572 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1573 | return -EAGAIN; | |
1574 | } | |
1575 | ||
1576 | if (list_empty(&ctx->dst_queue)) { | |
1577 | mfc_debug(2, "no dst buffers.\n"); | |
1578 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1579 | return -EAGAIN; | |
1580 | } | |
1581 | ||
1582 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | |
1583 | src_mb->flags |= MFC_BUF_FLAG_USED; | |
1584 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); | |
1585 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); | |
1586 | ||
4130eabc AH |
1587 | mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr); |
1588 | mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr); | |
f96f3cfa JP |
1589 | |
1590 | s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); | |
1591 | ||
1592 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | |
1593 | dst_mb->flags |= MFC_BUF_FLAG_USED; | |
1594 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | |
1595 | dst_size = vb2_plane_size(dst_mb->b, 0); | |
1596 | ||
1597 | s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); | |
1598 | ||
1599 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1600 | ||
f96f3cfa JP |
1601 | dev->curr_ctx = ctx->num; |
1602 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1603 | s5p_mfc_encode_one_frame_v6(ctx); | |
1604 | ||
1605 | return 0; | |
1606 | } | |
1607 | ||
1608 | static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) | |
1609 | { | |
1610 | struct s5p_mfc_dev *dev = ctx->dev; | |
1611 | unsigned long flags; | |
1612 | struct s5p_mfc_buf *temp_vb; | |
1613 | ||
1614 | /* Initializing decoding - parsing header */ | |
1615 | spin_lock_irqsave(&dev->irqlock, flags); | |
1616 | mfc_debug(2, "Preparing to init decoding.\n"); | |
1617 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | |
1618 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | |
1619 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | |
1620 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, | |
1621 | temp_vb->b->v4l2_planes[0].bytesused); | |
1622 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1623 | dev->curr_ctx = ctx->num; | |
1624 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1625 | s5p_mfc_init_decode_v6(ctx); | |
1626 | } | |
1627 | ||
1628 | static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) | |
1629 | { | |
1630 | struct s5p_mfc_dev *dev = ctx->dev; | |
1631 | unsigned long flags; | |
1632 | struct s5p_mfc_buf *dst_mb; | |
1633 | unsigned long dst_addr; | |
1634 | unsigned int dst_size; | |
1635 | ||
1636 | spin_lock_irqsave(&dev->irqlock, flags); | |
1637 | ||
1638 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | |
1639 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | |
1640 | dst_size = vb2_plane_size(dst_mb->b, 0); | |
1641 | s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); | |
1642 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1643 | dev->curr_ctx = ctx->num; | |
1644 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1645 | s5p_mfc_init_encode_v6(ctx); | |
1646 | } | |
1647 | ||
1648 | static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) | |
1649 | { | |
1650 | struct s5p_mfc_dev *dev = ctx->dev; | |
1651 | int ret; | |
1652 | /* Header was parsed now start processing | |
1653 | * First set the output frame buffers | |
1654 | * s5p_mfc_alloc_dec_buffers(ctx); */ | |
1655 | ||
1656 | if (ctx->capture_state != QUEUE_BUFS_MMAPED) { | |
1657 | mfc_err("It seems that not all destionation buffers were\n" | |
1658 | "mmaped.MFC requires that all destination are mmaped\n" | |
1659 | "before starting processing.\n"); | |
1660 | return -EAGAIN; | |
1661 | } | |
1662 | ||
1663 | dev->curr_ctx = ctx->num; | |
1664 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1665 | ret = s5p_mfc_set_dec_frame_buffer_v6(ctx); | |
1666 | if (ret) { | |
1667 | mfc_err("Failed to alloc frame mem.\n"); | |
1668 | ctx->state = MFCINST_ERROR; | |
1669 | } | |
1670 | return ret; | |
1671 | } | |
1672 | ||
1673 | static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx) | |
1674 | { | |
1675 | struct s5p_mfc_dev *dev = ctx->dev; | |
1676 | int ret; | |
1677 | ||
f96f3cfa JP |
1678 | dev->curr_ctx = ctx->num; |
1679 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1680 | ret = s5p_mfc_set_enc_ref_buffer_v6(ctx); | |
1681 | if (ret) { | |
1682 | mfc_err("Failed to alloc frame mem.\n"); | |
1683 | ctx->state = MFCINST_ERROR; | |
1684 | } | |
1685 | return ret; | |
1686 | } | |
1687 | ||
1688 | /* Try running an operation on hardware */ | |
b9571a57 | 1689 | static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) |
f96f3cfa JP |
1690 | { |
1691 | struct s5p_mfc_ctx *ctx; | |
1692 | int new_ctx; | |
1693 | unsigned int ret = 0; | |
1694 | ||
1695 | mfc_debug(1, "Try run dev: %p\n", dev); | |
1696 | ||
1697 | /* Check whether hardware is not running */ | |
1698 | if (test_and_set_bit(0, &dev->hw_lock) != 0) { | |
1699 | /* This is perfectly ok, the scheduled ctx should wait */ | |
1700 | mfc_debug(1, "Couldn't lock HW.\n"); | |
1701 | return; | |
1702 | } | |
1703 | ||
1704 | /* Choose the context to run */ | |
1705 | new_ctx = s5p_mfc_get_new_ctx(dev); | |
1706 | if (new_ctx < 0) { | |
1707 | /* No contexts to run */ | |
1708 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) { | |
1709 | mfc_err("Failed to unlock hardware.\n"); | |
1710 | return; | |
1711 | } | |
1712 | ||
1713 | mfc_debug(1, "No ctx is scheduled to be run.\n"); | |
1714 | return; | |
1715 | } | |
1716 | ||
1717 | mfc_debug(1, "New context: %d\n", new_ctx); | |
1718 | ctx = dev->ctx[new_ctx]; | |
1719 | mfc_debug(1, "Seting new context to %p\n", ctx); | |
1720 | /* Got context to run in ctx */ | |
1721 | mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n", | |
e9d98ddc | 1722 | ctx->dst_queue_cnt, ctx->pb_count, ctx->src_queue_cnt); |
f96f3cfa JP |
1723 | mfc_debug(1, "ctx->state=%d\n", ctx->state); |
1724 | /* Last frame has already been sent to MFC | |
1725 | * Now obtaining frames from MFC buffer */ | |
1726 | ||
1727 | s5p_mfc_clock_on(); | |
1728 | if (ctx->type == MFCINST_DECODER) { | |
1729 | switch (ctx->state) { | |
1730 | case MFCINST_FINISHING: | |
1731 | s5p_mfc_run_dec_last_frames(ctx); | |
1732 | break; | |
1733 | case MFCINST_RUNNING: | |
1734 | ret = s5p_mfc_run_dec_frame(ctx); | |
1735 | break; | |
1736 | case MFCINST_INIT: | |
1737 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1738 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | |
1739 | ctx); | |
1740 | break; | |
1741 | case MFCINST_RETURN_INST: | |
1742 | s5p_mfc_clean_ctx_int_flags(ctx); | |
1743 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | |
1744 | ctx); | |
1745 | break; | |
1746 | case MFCINST_GOT_INST: | |
1747 | s5p_mfc_run_init_dec(ctx); | |
1748 | break; | |
1749 | case MFCINST_HEAD_PARSED: | |
1750 | ret = s5p_mfc_run_init_dec_buffers(ctx); | |
1751 | break; | |
8f23cc02 AK |
1752 | case MFCINST_FLUSH: |
1753 | s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag); | |
1754 | break; | |
f96f3cfa JP |
1755 | case MFCINST_RES_CHANGE_INIT: |
1756 | s5p_mfc_run_dec_last_frames(ctx); | |
1757 | break; | |
1758 | case MFCINST_RES_CHANGE_FLUSH: | |
1759 | s5p_mfc_run_dec_last_frames(ctx); | |
1760 | break; | |
1761 | case MFCINST_RES_CHANGE_END: | |
1762 | mfc_debug(2, "Finished remaining frames after resolution change.\n"); | |
1763 | ctx->capture_state = QUEUE_FREE; | |
1764 | mfc_debug(2, "Will re-init the codec`.\n"); | |
1765 | s5p_mfc_run_init_dec(ctx); | |
1766 | break; | |
1767 | default: | |
1768 | ret = -EAGAIN; | |
1769 | } | |
1770 | } else if (ctx->type == MFCINST_ENCODER) { | |
1771 | switch (ctx->state) { | |
1772 | case MFCINST_FINISHING: | |
1773 | case MFCINST_RUNNING: | |
1774 | ret = s5p_mfc_run_enc_frame(ctx); | |
1775 | break; | |
1776 | case MFCINST_INIT: | |
1777 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | |
1778 | ctx); | |
1779 | break; | |
1780 | case MFCINST_RETURN_INST: | |
1781 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | |
1782 | ctx); | |
1783 | break; | |
1784 | case MFCINST_GOT_INST: | |
1785 | s5p_mfc_run_init_enc(ctx); | |
1786 | break; | |
e9d98ddc | 1787 | case MFCINST_HEAD_PRODUCED: |
f96f3cfa JP |
1788 | ret = s5p_mfc_run_init_enc_buffers(ctx); |
1789 | break; | |
1790 | default: | |
1791 | ret = -EAGAIN; | |
1792 | } | |
1793 | } else { | |
1794 | mfc_err("invalid context type: %d\n", ctx->type); | |
1795 | ret = -EAGAIN; | |
1796 | } | |
1797 | ||
1798 | if (ret) { | |
1799 | /* Free hardware lock */ | |
1800 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | |
1801 | mfc_err("Failed to unlock hardware.\n"); | |
1802 | ||
1803 | /* This is in deed imporant, as no operation has been | |
1804 | * scheduled, reduce the clock count as no one will | |
1805 | * ever do this, because no interrupt related to this try_run | |
1806 | * will ever come from hardware. */ | |
1807 | s5p_mfc_clock_off(); | |
1808 | } | |
1809 | } | |
1810 | ||
1811 | ||
b9571a57 | 1812 | static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) |
f96f3cfa JP |
1813 | { |
1814 | struct s5p_mfc_buf *b; | |
1815 | int i; | |
1816 | ||
1817 | while (!list_empty(lh)) { | |
1818 | b = list_entry(lh->next, struct s5p_mfc_buf, list); | |
1819 | for (i = 0; i < b->b->num_planes; i++) | |
1820 | vb2_set_plane_payload(b->b, i, 0); | |
1821 | vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); | |
1822 | list_del(&b->list); | |
1823 | } | |
1824 | } | |
1825 | ||
b9571a57 | 1826 | static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1827 | { |
6a9c6f68 KA |
1828 | const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; |
1829 | WRITEL(0, mfc_regs->risc2host_command); | |
1830 | WRITEL(0, mfc_regs->risc2host_int); | |
f96f3cfa JP |
1831 | } |
1832 | ||
b9571a57 | 1833 | static void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data, |
f96f3cfa JP |
1834 | unsigned int ofs) |
1835 | { | |
f96f3cfa | 1836 | s5p_mfc_clock_on(); |
6a9c6f68 | 1837 | WRITEL(data, (void *)ofs); |
f96f3cfa JP |
1838 | s5p_mfc_clock_off(); |
1839 | } | |
1840 | ||
b9571a57 SK |
1841 | static unsigned int |
1842 | s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) | |
f96f3cfa | 1843 | { |
f96f3cfa JP |
1844 | int ret; |
1845 | ||
1846 | s5p_mfc_clock_on(); | |
6a9c6f68 | 1847 | ret = READL((void *)ofs); |
f96f3cfa JP |
1848 | s5p_mfc_clock_off(); |
1849 | ||
1850 | return ret; | |
1851 | } | |
1852 | ||
b9571a57 | 1853 | static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1854 | { |
6a9c6f68 | 1855 | return READL(dev->mfc_regs->d_display_first_plane_addr); |
f96f3cfa JP |
1856 | } |
1857 | ||
b9571a57 | 1858 | static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1859 | { |
6a9c6f68 | 1860 | return READL(dev->mfc_regs->d_decoded_first_plane_addr); |
f96f3cfa JP |
1861 | } |
1862 | ||
b9571a57 | 1863 | static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1864 | { |
6a9c6f68 | 1865 | return READL(dev->mfc_regs->d_display_status); |
f96f3cfa JP |
1866 | } |
1867 | ||
644469ae | 1868 | static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1869 | { |
6a9c6f68 | 1870 | return READL(dev->mfc_regs->d_decoded_status); |
f96f3cfa JP |
1871 | } |
1872 | ||
b9571a57 | 1873 | static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1874 | { |
6a9c6f68 | 1875 | return READL(dev->mfc_regs->d_decoded_frame_type) & |
f96f3cfa JP |
1876 | S5P_FIMV_DECODE_FRAME_MASK_V6; |
1877 | } | |
1878 | ||
b9571a57 | 1879 | static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1880 | { |
6a9c6f68 KA |
1881 | struct s5p_mfc_dev *dev = ctx->dev; |
1882 | return READL(dev->mfc_regs->d_display_frame_type) & | |
f96f3cfa JP |
1883 | S5P_FIMV_DECODE_FRAME_MASK_V6; |
1884 | } | |
1885 | ||
b9571a57 | 1886 | static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1887 | { |
6a9c6f68 | 1888 | return READL(dev->mfc_regs->d_decoded_nal_size); |
f96f3cfa JP |
1889 | } |
1890 | ||
b9571a57 | 1891 | static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1892 | { |
6a9c6f68 | 1893 | return READL(dev->mfc_regs->risc2host_command) & |
f96f3cfa JP |
1894 | S5P_FIMV_RISC2HOST_CMD_MASK; |
1895 | } | |
1896 | ||
b9571a57 | 1897 | static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1898 | { |
6a9c6f68 | 1899 | return READL(dev->mfc_regs->error_code); |
f96f3cfa JP |
1900 | } |
1901 | ||
b9571a57 | 1902 | static int s5p_mfc_err_dec_v6(unsigned int err) |
f96f3cfa JP |
1903 | { |
1904 | return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6; | |
1905 | } | |
1906 | ||
b9571a57 | 1907 | static int s5p_mfc_err_dspl_v6(unsigned int err) |
f96f3cfa JP |
1908 | { |
1909 | return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6; | |
1910 | } | |
1911 | ||
b9571a57 | 1912 | static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1913 | { |
6a9c6f68 | 1914 | return READL(dev->mfc_regs->d_display_frame_width); |
f96f3cfa JP |
1915 | } |
1916 | ||
b9571a57 | 1917 | static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1918 | { |
6a9c6f68 | 1919 | return READL(dev->mfc_regs->d_display_frame_height); |
f96f3cfa JP |
1920 | } |
1921 | ||
b9571a57 | 1922 | static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1923 | { |
6a9c6f68 | 1924 | return READL(dev->mfc_regs->d_min_num_dpb); |
f96f3cfa JP |
1925 | } |
1926 | ||
b9571a57 | 1927 | static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1928 | { |
6a9c6f68 | 1929 | return READL(dev->mfc_regs->d_min_num_mv); |
f96f3cfa JP |
1930 | } |
1931 | ||
b9571a57 | 1932 | static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1933 | { |
6a9c6f68 | 1934 | return READL(dev->mfc_regs->ret_instance_id); |
f96f3cfa JP |
1935 | } |
1936 | ||
b9571a57 | 1937 | static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1938 | { |
6a9c6f68 | 1939 | return READL(dev->mfc_regs->e_num_dpb); |
f96f3cfa JP |
1940 | } |
1941 | ||
b9571a57 | 1942 | static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1943 | { |
6a9c6f68 | 1944 | return READL(dev->mfc_regs->e_stream_size); |
f96f3cfa JP |
1945 | } |
1946 | ||
b9571a57 | 1947 | static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1948 | { |
6a9c6f68 | 1949 | return READL(dev->mfc_regs->e_slice_type); |
f96f3cfa JP |
1950 | } |
1951 | ||
b9571a57 | 1952 | static int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1953 | { |
6a9c6f68 | 1954 | return READL(dev->mfc_regs->e_picture_count); |
f96f3cfa JP |
1955 | } |
1956 | ||
b9571a57 | 1957 | static int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1958 | { |
6a9c6f68 KA |
1959 | struct s5p_mfc_dev *dev = ctx->dev; |
1960 | return READL(dev->mfc_regs->d_frame_pack_sei_avail); | |
f96f3cfa JP |
1961 | } |
1962 | ||
b9571a57 | 1963 | static int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1964 | { |
6a9c6f68 | 1965 | return READL(dev->mfc_regs->d_mvc_num_views); |
f96f3cfa JP |
1966 | } |
1967 | ||
b9571a57 | 1968 | static int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) |
f96f3cfa | 1969 | { |
6a9c6f68 | 1970 | return READL(dev->mfc_regs->d_mvc_view_id); |
f96f3cfa JP |
1971 | } |
1972 | ||
b9571a57 | 1973 | static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1974 | { |
6a9c6f68 KA |
1975 | return s5p_mfc_read_info_v6(ctx, |
1976 | (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_top); | |
f96f3cfa JP |
1977 | } |
1978 | ||
b9571a57 | 1979 | static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1980 | { |
6a9c6f68 KA |
1981 | return s5p_mfc_read_info_v6(ctx, |
1982 | (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_bot); | |
f96f3cfa JP |
1983 | } |
1984 | ||
b9571a57 | 1985 | static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1986 | { |
6a9c6f68 KA |
1987 | return s5p_mfc_read_info_v6(ctx, |
1988 | (unsigned int) ctx->dev->mfc_regs->d_display_crop_info1); | |
f96f3cfa JP |
1989 | } |
1990 | ||
b9571a57 | 1991 | static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx) |
f96f3cfa | 1992 | { |
6a9c6f68 KA |
1993 | return s5p_mfc_read_info_v6(ctx, |
1994 | (unsigned int) ctx->dev->mfc_regs->d_display_crop_info2); | |
1995 | } | |
1996 | ||
1997 | static struct s5p_mfc_regs mfc_regs; | |
1998 | ||
1999 | /* Initialize registers for MFC v6 onwards */ | |
2000 | const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev) | |
2001 | { | |
2002 | memset(&mfc_regs, 0, sizeof(mfc_regs)); | |
2003 | ||
2004 | #define S5P_MFC_REG_ADDR(dev, reg) ((dev)->regs_base + (reg)) | |
2005 | #define R(m, r) mfc_regs.m = S5P_MFC_REG_ADDR(dev, r) | |
2006 | /* codec common registers */ | |
2007 | R(risc_on, S5P_FIMV_RISC_ON_V6); | |
2008 | R(risc2host_int, S5P_FIMV_RISC2HOST_INT_V6); | |
2009 | R(host2risc_int, S5P_FIMV_HOST2RISC_INT_V6); | |
2010 | R(risc_base_address, S5P_FIMV_RISC_BASE_ADDRESS_V6); | |
2011 | R(mfc_reset, S5P_FIMV_MFC_RESET_V6); | |
2012 | R(host2risc_command, S5P_FIMV_HOST2RISC_CMD_V6); | |
2013 | R(risc2host_command, S5P_FIMV_RISC2HOST_CMD_V6); | |
2014 | R(firmware_version, S5P_FIMV_FW_VERSION_V6); | |
2015 | R(instance_id, S5P_FIMV_INSTANCE_ID_V6); | |
2016 | R(codec_type, S5P_FIMV_CODEC_TYPE_V6); | |
2017 | R(context_mem_addr, S5P_FIMV_CONTEXT_MEM_ADDR_V6); | |
2018 | R(context_mem_size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); | |
2019 | R(pixel_format, S5P_FIMV_PIXEL_FORMAT_V6); | |
2020 | R(ret_instance_id, S5P_FIMV_RET_INSTANCE_ID_V6); | |
2021 | R(error_code, S5P_FIMV_ERROR_CODE_V6); | |
2022 | ||
2023 | /* decoder registers */ | |
2024 | R(d_crc_ctrl, S5P_FIMV_D_CRC_CTRL_V6); | |
2025 | R(d_dec_options, S5P_FIMV_D_DEC_OPTIONS_V6); | |
2026 | R(d_display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | |
2027 | R(d_sei_enable, S5P_FIMV_D_SEI_ENABLE_V6); | |
2028 | R(d_min_num_dpb, S5P_FIMV_D_MIN_NUM_DPB_V6); | |
2029 | R(d_min_num_mv, S5P_FIMV_D_MIN_NUM_MV_V6); | |
2030 | R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V6); | |
2031 | R(d_num_dpb, S5P_FIMV_D_NUM_DPB_V6); | |
2032 | R(d_num_mv, S5P_FIMV_D_NUM_MV_V6); | |
2033 | R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6); | |
2034 | R(d_first_plane_dpb_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); | |
2035 | R(d_second_plane_dpb_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); | |
2036 | R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6); | |
2037 | R(d_first_plane_dpb, S5P_FIMV_D_LUMA_DPB_V6); | |
2038 | R(d_second_plane_dpb, S5P_FIMV_D_CHROMA_DPB_V6); | |
2039 | R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V6); | |
2040 | R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); | |
2041 | R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); | |
2042 | R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); | |
2043 | R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); | |
2044 | R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); | |
2045 | R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); | |
2046 | R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V6); | |
2047 | R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6); | |
2048 | R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); | |
2049 | R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); | |
2050 | R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V6); | |
2051 | R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); | |
2052 | R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6); | |
2053 | R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6); | |
2054 | R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V6); | |
2055 | R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V6); | |
2056 | R(d_display_aspect_ratio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6); | |
2057 | R(d_display_extended_ar, S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6); | |
2058 | R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V6); | |
2059 | R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); | |
2060 | R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_CHROMA_ADDR_V6); | |
2061 | R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V6); | |
2062 | R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V6); | |
2063 | R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6); | |
2064 | R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6); | |
2065 | R(d_h264_info, S5P_FIMV_D_H264_INFO_V6); | |
2066 | R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V6); | |
2067 | R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); | |
2068 | ||
2069 | /* encoder registers */ | |
2070 | R(e_frame_width, S5P_FIMV_E_FRAME_WIDTH_V6); | |
2071 | R(e_frame_height, S5P_FIMV_E_FRAME_HEIGHT_V6); | |
2072 | R(e_cropped_frame_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); | |
2073 | R(e_cropped_frame_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | |
2074 | R(e_frame_crop_offset, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); | |
2075 | R(e_enc_options, S5P_FIMV_E_ENC_OPTIONS_V6); | |
2076 | R(e_picture_profile, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
2077 | R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
2078 | R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
2079 | R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
2080 | R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V6); | |
2081 | R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V6); | |
2082 | R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V6); | |
2083 | R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V6); | |
2084 | R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V6); | |
2085 | R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V6); | |
2086 | R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V6); | |
2087 | R(e_num_dpb, S5P_FIMV_E_NUM_DPB_V6); | |
2088 | R(e_luma_dpb, S5P_FIMV_E_LUMA_DPB_V6); | |
2089 | R(e_chroma_dpb, S5P_FIMV_E_CHROMA_DPB_V6); | |
2090 | R(e_me_buffer, S5P_FIMV_E_ME_BUFFER_V6); | |
2091 | R(e_scratch_buffer_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6); | |
2092 | R(e_scratch_buffer_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); | |
2093 | R(e_tmv_buffer0, S5P_FIMV_E_TMV_BUFFER0_V6); | |
2094 | R(e_tmv_buffer1, S5P_FIMV_E_TMV_BUFFER1_V6); | |
2095 | R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); | |
2096 | R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | |
2097 | R(e_stream_buffer_addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); | |
2098 | R(e_stream_buffer_size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); | |
2099 | R(e_roi_buffer_addr, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); | |
2100 | R(e_param_change, S5P_FIMV_E_PARAM_CHANGE_V6); | |
2101 | R(e_ir_size, S5P_FIMV_E_IR_SIZE_V6); | |
2102 | R(e_gop_config, S5P_FIMV_E_GOP_CONFIG_V6); | |
2103 | R(e_mslice_mode, S5P_FIMV_E_MSLICE_MODE_V6); | |
2104 | R(e_mslice_size_mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | |
2105 | R(e_mslice_size_bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | |
2106 | R(e_frame_insertion, S5P_FIMV_E_FRAME_INSERTION_V6); | |
2107 | R(e_rc_frame_rate, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
2108 | R(e_rc_bit_rate, S5P_FIMV_E_RC_BIT_RATE_V6); | |
2109 | R(e_rc_roi_ctrl, S5P_FIMV_E_RC_ROI_CTRL_V6); | |
2110 | R(e_picture_tag, S5P_FIMV_E_PICTURE_TAG_V6); | |
2111 | R(e_bit_count_enable, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); | |
2112 | R(e_max_bit_count, S5P_FIMV_E_MAX_BIT_COUNT_V6); | |
2113 | R(e_min_bit_count, S5P_FIMV_E_MIN_BIT_COUNT_V6); | |
2114 | R(e_metadata_buffer_addr, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); | |
2115 | R(e_metadata_buffer_size, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); | |
2116 | R(e_encoded_source_first_plane_addr, | |
2117 | S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | |
2118 | R(e_encoded_source_second_plane_addr, | |
2119 | S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | |
2120 | R(e_stream_size, S5P_FIMV_E_STREAM_SIZE_V6); | |
2121 | R(e_slice_type, S5P_FIMV_E_SLICE_TYPE_V6); | |
2122 | R(e_picture_count, S5P_FIMV_E_PICTURE_COUNT_V6); | |
2123 | R(e_ret_picture_tag, S5P_FIMV_E_RET_PICTURE_TAG_V6); | |
2124 | R(e_recon_luma_dpb_addr, S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | |
2125 | R(e_recon_chroma_dpb_addr, S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | |
2126 | R(e_mpeg4_options, S5P_FIMV_E_MPEG4_OPTIONS_V6); | |
2127 | R(e_mpeg4_hec_period, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); | |
2128 | R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V6); | |
2129 | R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V6); | |
2130 | R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V6); | |
2131 | R(e_h264_lf_alpha_offset, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); | |
2132 | R(e_h264_lf_beta_offset, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); | |
2133 | R(e_h264_i_period, S5P_FIMV_E_H264_I_PERIOD_V6); | |
2134 | R(e_h264_fmo_slice_grp_map_type, | |
2135 | S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); | |
2136 | R(e_h264_fmo_num_slice_grp_minus1, | |
2137 | S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | |
2138 | R(e_h264_fmo_slice_grp_change_dir, | |
2139 | S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6); | |
2140 | R(e_h264_fmo_slice_grp_change_rate_minus1, | |
2141 | S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6); | |
2142 | R(e_h264_fmo_run_length_minus1_0, | |
2143 | S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6); | |
2144 | R(e_h264_aso_slice_order_0, S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6); | |
2145 | R(e_h264_num_t_layer, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | |
2146 | R(e_h264_hierarchical_qp_layer0, | |
2147 | S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6); | |
2148 | R(e_h264_frame_packing_sei_info, | |
2149 | S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6); | |
2150 | ||
109b794c | 2151 | if (!IS_MFCV7_PLUS(dev)) |
6a9c6f68 KA |
2152 | goto done; |
2153 | ||
2154 | /* Initialize registers used in MFC v7 */ | |
2155 | R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); | |
2156 | R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); | |
2157 | R(e_source_third_plane_addr, S5P_FIMV_E_SOURCE_THIRD_ADDR_V7); | |
2158 | R(e_source_first_plane_stride, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); | |
2159 | R(e_source_second_plane_stride, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); | |
2160 | R(e_source_third_plane_stride, S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7); | |
2161 | R(e_encoded_source_first_plane_addr, | |
2162 | S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); | |
2163 | R(e_encoded_source_second_plane_addr, | |
2164 | S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); | |
2165 | R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7); | |
2166 | ||
2167 | done: | |
2168 | return &mfc_regs; | |
2169 | #undef S5P_MFC_REG_ADDR | |
2170 | #undef R | |
f96f3cfa JP |
2171 | } |
2172 | ||
2173 | /* Initialize opr function pointers for MFC v6 */ | |
2174 | static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = { | |
2175 | .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6, | |
2176 | .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6, | |
2177 | .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6, | |
2178 | .release_codec_buffers = s5p_mfc_release_codec_buffers_v6, | |
2179 | .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6, | |
2180 | .release_instance_buffer = s5p_mfc_release_instance_buffer_v6, | |
2181 | .alloc_dev_context_buffer = | |
2182 | s5p_mfc_alloc_dev_context_buffer_v6, | |
2183 | .release_dev_context_buffer = | |
2184 | s5p_mfc_release_dev_context_buffer_v6, | |
2185 | .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6, | |
2186 | .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6, | |
2187 | .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6, | |
2188 | .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6, | |
2189 | .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6, | |
2190 | .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6, | |
2191 | .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6, | |
2192 | .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6, | |
2193 | .init_decode = s5p_mfc_init_decode_v6, | |
2194 | .init_encode = s5p_mfc_init_encode_v6, | |
2195 | .encode_one_frame = s5p_mfc_encode_one_frame_v6, | |
2196 | .try_run = s5p_mfc_try_run_v6, | |
2197 | .cleanup_queue = s5p_mfc_cleanup_queue_v6, | |
2198 | .clear_int_flags = s5p_mfc_clear_int_flags_v6, | |
2199 | .write_info = s5p_mfc_write_info_v6, | |
2200 | .read_info = s5p_mfc_read_info_v6, | |
2201 | .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6, | |
2202 | .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6, | |
2203 | .get_dspl_status = s5p_mfc_get_dspl_status_v6, | |
2204 | .get_dec_status = s5p_mfc_get_dec_status_v6, | |
2205 | .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6, | |
2206 | .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6, | |
2207 | .get_consumed_stream = s5p_mfc_get_consumed_stream_v6, | |
2208 | .get_int_reason = s5p_mfc_get_int_reason_v6, | |
2209 | .get_int_err = s5p_mfc_get_int_err_v6, | |
2210 | .err_dec = s5p_mfc_err_dec_v6, | |
2211 | .err_dspl = s5p_mfc_err_dspl_v6, | |
2212 | .get_img_width = s5p_mfc_get_img_width_v6, | |
2213 | .get_img_height = s5p_mfc_get_img_height_v6, | |
2214 | .get_dpb_count = s5p_mfc_get_dpb_count_v6, | |
2215 | .get_mv_count = s5p_mfc_get_mv_count_v6, | |
2216 | .get_inst_no = s5p_mfc_get_inst_no_v6, | |
2217 | .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6, | |
2218 | .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6, | |
2219 | .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6, | |
2220 | .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6, | |
2221 | .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6, | |
2222 | .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6, | |
2223 | .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6, | |
2224 | .get_pic_type_top = s5p_mfc_get_pic_type_top_v6, | |
2225 | .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6, | |
2226 | .get_crop_info_h = s5p_mfc_get_crop_info_h_v6, | |
2227 | .get_crop_info_v = s5p_mfc_get_crop_info_v_v6, | |
2228 | }; | |
2229 | ||
2230 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void) | |
2231 | { | |
2232 | return &s5p_mfc_ops_v6; | |
2233 | } |