aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/Kconfig8
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/s5p-mfc/Makefile5
-rw-r--r--drivers/media/video/s5p-mfc/regs-mfc.h413
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc.c1274
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_cmd.c120
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_cmd.h30
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_common.h572
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c343
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h29
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_debug.h48
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.c1036
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.h23
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_enc.c1829
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_enc.h23
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_intr.c92
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_intr.h26
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_opr.c1397
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_opr.h91
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_pm.c117
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_pm.h24
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_shm.c47
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_shm.h91
23 files changed, 7639 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index b1f7e19640d5..509a5da8e814 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1066,4 +1066,12 @@ config VIDEO_MEM2MEM_TESTDEV
1066 framework. 1066 framework.
1067 1067
1068 1068
1069config VIDEO_SAMSUNG_S5P_MFC
1070 tristate "Samsung S5P MFC 5.1 Video Codec"
1071 depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
1072 select VIDEOBUF2_DMA_CONTIG
1073 default n
1074 help
1075 MFC 5.1 driver for V4L2.
1076
1069endif # V4L_MEM2MEM_DRIVERS 1077endif # V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 5138a65f5e10..12d2db7bd0e2 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -171,6 +171,7 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
171obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o 171obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o
172 172
173obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ 173obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/
174obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/
174 175
175obj-$(CONFIG_ARCH_DAVINCI) += davinci/ 176obj-$(CONFIG_ARCH_DAVINCI) += davinci/
176 177
diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/video/s5p-mfc/Makefile
new file mode 100644
index 000000000000..d0663409af00
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/Makefile
@@ -0,0 +1,5 @@
1obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
2s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
3s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
4s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
5s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/video/s5p-mfc/regs-mfc.h
new file mode 100644
index 000000000000..053a8a872fd7
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/regs-mfc.h
@@ -0,0 +1,413 @@
1/*
2 * Register definition file for Samsung MFC V5.1 Interface (FIMV) driver
3 *
4 * Kamil Debski, Copyright (c) 2010 Samsung Electronics
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#ifndef _REGS_FIMV_H
13#define _REGS_FIMV_H
14
15#define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
16#define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
17
18/* Number of bits that the buffer address should be shifted for particular
19 * MFC buffers. */
20#define S5P_FIMV_START_ADDR 0x0000
21#define S5P_FIMV_END_ADDR 0xe008
22
23#define S5P_FIMV_SW_RESET 0x0000
24#define S5P_FIMV_RISC_HOST_INT 0x0008
25
26/* Command from HOST to RISC */
27#define S5P_FIMV_HOST2RISC_CMD 0x0030
28#define S5P_FIMV_HOST2RISC_ARG1 0x0034
29#define S5P_FIMV_HOST2RISC_ARG2 0x0038
30#define S5P_FIMV_HOST2RISC_ARG3 0x003c
31#define S5P_FIMV_HOST2RISC_ARG4 0x0040
32
33/* Command from RISC to HOST */
34#define S5P_FIMV_RISC2HOST_CMD 0x0044
35#define S5P_FIMV_RISC2HOST_CMD_MASK 0x1FFFF
36#define S5P_FIMV_RISC2HOST_ARG1 0x0048
37#define S5P_FIMV_RISC2HOST_ARG2 0x004c
38#define S5P_FIMV_RISC2HOST_ARG3 0x0050
39#define S5P_FIMV_RISC2HOST_ARG4 0x0054
40
41#define S5P_FIMV_FW_VERSION 0x0058
42#define S5P_FIMV_SYS_MEM_SZ 0x005c
43#define S5P_FIMV_FW_STATUS 0x0080
44
45/* Memory controller register */
46#define S5P_FIMV_MC_DRAMBASE_ADR_A 0x0508
47#define S5P_FIMV_MC_DRAMBASE_ADR_B 0x050c
48#define S5P_FIMV_MC_STATUS 0x0510
49
50/* Common register */
51#define S5P_FIMV_COMMON_BASE_A 0x0600
52#define S5P_FIMV_COMMON_BASE_B 0x0700
53
54/* Decoder */
55#define S5P_FIMV_DEC_CHROMA_ADR (S5P_FIMV_COMMON_BASE_A)
56#define S5P_FIMV_DEC_LUMA_ADR (S5P_FIMV_COMMON_BASE_B)
57
58/* H.264 decoding */
59#define S5P_FIMV_H264_VERT_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
60 /* vertical neighbor motion vector */
61#define S5P_FIMV_H264_NB_IP_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
62 /* neighbor pixels for intra pred */
63#define S5P_FIMV_H264_MV_ADR (S5P_FIMV_COMMON_BASE_B + 0x80)
64 /* H264 motion vector */
65
66/* MPEG4 decoding */
67#define S5P_FIMV_MPEG4_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
68 /* neighbor AC/DC coeff. */
69#define S5P_FIMV_MPEG4_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
70 /* upper neighbor motion vector */
71#define S5P_FIMV_MPEG4_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94)
72 /* subseq. anchor motion vector */
73#define S5P_FIMV_MPEG4_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98)
74 /* overlap transform line */
75#define S5P_FIMV_MPEG4_SP_ADR (S5P_FIMV_COMMON_BASE_A + 0xa8)
76 /* syntax parser */
77
78/* H.263 decoding */
79#define S5P_FIMV_H263_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
80#define S5P_FIMV_H263_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
81#define S5P_FIMV_H263_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94)
82#define S5P_FIMV_H263_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98)
83
84/* VC-1 decoding */
85#define S5P_FIMV_VC1_NB_DCAC_ADR (S5P_FIMV_COMMON_BASE_A + 0x8c)
86#define S5P_FIMV_VC1_UP_NB_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x90)
87#define S5P_FIMV_VC1_SA_MV_ADR (S5P_FIMV_COMMON_BASE_A + 0x94)
88#define S5P_FIMV_VC1_OT_LINE_ADR (S5P_FIMV_COMMON_BASE_A + 0x98)
89#define S5P_FIMV_VC1_BITPLANE3_ADR (S5P_FIMV_COMMON_BASE_A + 0x9c)
90 /* bitplane3 */
91#define S5P_FIMV_VC1_BITPLANE2_ADR (S5P_FIMV_COMMON_BASE_A + 0xa0)
92 /* bitplane2 */
93#define S5P_FIMV_VC1_BITPLANE1_ADR (S5P_FIMV_COMMON_BASE_A + 0xa4)
94 /* bitplane1 */
95
96/* Encoder */
97#define S5P_FIMV_ENC_REF0_LUMA_ADR (S5P_FIMV_COMMON_BASE_A + 0x1c)
98#define S5P_FIMV_ENC_REF1_LUMA_ADR (S5P_FIMV_COMMON_BASE_A + 0x20)
99 /* reconstructed luma */
100#define S5P_FIMV_ENC_REF0_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B)
101#define S5P_FIMV_ENC_REF1_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x04)
102 /* reconstructed chroma */
103#define S5P_FIMV_ENC_REF2_LUMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x10)
104#define S5P_FIMV_ENC_REF2_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x08)
105#define S5P_FIMV_ENC_REF3_LUMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x14)
106#define S5P_FIMV_ENC_REF3_CHROMA_ADR (S5P_FIMV_COMMON_BASE_B + 0x0c)
107
108/* H.264 encoding */
109#define S5P_FIMV_H264_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A)
110 /* upper motion vector */
111#define S5P_FIMV_H264_NBOR_INFO_ADR (S5P_FIMV_COMMON_BASE_A + 0x04)
112 /* entropy engine's neighbor info. */
113#define S5P_FIMV_H264_UP_INTRA_MD_ADR (S5P_FIMV_COMMON_BASE_A + 0x08)
114 /* upper intra MD */
115#define S5P_FIMV_H264_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10)
116 /* direct cozero flag */
117#define S5P_FIMV_H264_UP_INTRA_PRED_ADR (S5P_FIMV_COMMON_BASE_B + 0x40)
118 /* upper intra PRED */
119
120/* H.263 encoding */
121#define S5P_FIMV_H263_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A)
122 /* upper motion vector */
123#define S5P_FIMV_H263_ACDC_COEF_ADR (S5P_FIMV_COMMON_BASE_A + 0x04)
124 /* upper Q coeff. */
125
126/* MPEG4 encoding */
127#define S5P_FIMV_MPEG4_UP_MV_ADR (S5P_FIMV_COMMON_BASE_A)
128 /* upper motion vector */
129#define S5P_FIMV_MPEG4_ACDC_COEF_ADR (S5P_FIMV_COMMON_BASE_A + 0x04)
130 /* upper Q coeff. */
131#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10)
132 /* direct cozero flag */
133
134#define S5P_FIMV_ENC_REF_B_LUMA_ADR 0x062c /* ref B Luma addr */
135#define S5P_FIMV_ENC_REF_B_CHROMA_ADR 0x0630 /* ref B Chroma addr */
136
137#define S5P_FIMV_ENC_CUR_LUMA_ADR 0x0718 /* current Luma addr */
138#define S5P_FIMV_ENC_CUR_CHROMA_ADR 0x071C /* current Chroma addr */
139
140/* Codec common register */
141#define S5P_FIMV_ENC_HSIZE_PX 0x0818 /* frame width at encoder */
142#define S5P_FIMV_ENC_VSIZE_PX 0x081c /* frame height at encoder */
143#define S5P_FIMV_ENC_PROFILE 0x0830 /* profile register */
144#define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
145#define S5P_FIMV_ENC_PROFILE_H264_HIGH 1
146#define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2
147#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
148#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
149#define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
150#define S5P_FIMV_ENC_LF_CTRL 0x0848 /* loop filter control */
151#define S5P_FIMV_ENC_ALPHA_OFF 0x084c /* loop filter alpha offset */
152#define S5P_FIMV_ENC_BETA_OFF 0x0850 /* loop filter beta offset */
153#define S5P_FIMV_MR_BUSIF_CTRL 0x0854 /* hidden, bus interface ctrl */
154#define S5P_FIMV_ENC_PXL_CACHE_CTRL 0x0a00 /* pixel cache control */
155
156/* Channel & stream interface register */
157#define S5P_FIMV_SI_RTN_CHID 0x2000 /* Return CH inst ID register */
158#define S5P_FIMV_SI_CH0_INST_ID 0x2040 /* codec instance ID */
159#define S5P_FIMV_SI_CH1_INST_ID 0x2080 /* codec instance ID */
160/* Decoder */
161#define S5P_FIMV_SI_VRESOL 0x2004 /* vertical res of decoder */
162#define S5P_FIMV_SI_HRESOL 0x2008 /* horizontal res of decoder */
163#define S5P_FIMV_SI_BUF_NUMBER 0x200c /* number of frames in the
164 decoded pic */
165#define S5P_FIMV_SI_DISPLAY_Y_ADR 0x2010 /* luma addr of displayed pic */
166#define S5P_FIMV_SI_DISPLAY_C_ADR 0x2014 /* chroma addrof displayed pic */
167#define S5P_FIMV_SI_CONSUMED_BYTES 0x2018 /* Consumed number of bytes to
168 decode a frame */
169#define S5P_FIMV_SI_DISPLAY_STATUS 0x201c /* status of decoded picture */
170
171#define S5P_FIMV_SI_CH0_SB_ST_ADR 0x2044 /* start addr of stream buf */
172#define S5P_FIMV_SI_CH0_SB_FRM_SIZE 0x2048 /* size of stream buf */
173#define S5P_FIMV_SI_CH0_DESC_ADR 0x204c /* addr of descriptor buf */
174#define S5P_FIMV_SI_CH0_CPB_SIZE 0x2058 /* max size of coded pic. buf */
175#define S5P_FIMV_SI_CH0_DESC_SIZE 0x205c /* max size of descriptor buf */
176
177#define S5P_FIMV_SI_CH1_SB_ST_ADR 0x2084 /* start addr of stream buf */
178#define S5P_FIMV_SI_CH1_SB_FRM_SIZE 0x2088 /* size of stream buf */
179#define S5P_FIMV_SI_CH1_DESC_ADR 0x208c /* addr of descriptor buf */
180#define S5P_FIMV_SI_CH1_CPB_SIZE 0x2098 /* max size of coded pic. buf */
181#define S5P_FIMV_SI_CH1_DESC_SIZE 0x209c /* max size of descriptor buf */
182
183#define S5P_FIMV_CRC_LUMA0 0x2030 /* luma crc data per frame
184 (top field) */
185#define S5P_FIMV_CRC_CHROMA0 0x2034 /* chroma crc data per frame
186 (top field) */
187#define S5P_FIMV_CRC_LUMA1 0x2038 /* luma crc data per bottom
188 field */
189#define S5P_FIMV_CRC_CHROMA1 0x203c /* chroma crc data per bottom
190 field */
191
192/* Display status */
193#define S5P_FIMV_DEC_STATUS_DECODING_ONLY 0
194#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY 1
195#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY 2
196#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY 3
197#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK 7
198#define S5P_FIMV_DEC_STATUS_PROGRESSIVE (0<<3)
199#define S5P_FIMV_DEC_STATUS_INTERLACE (1<<3)
200#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK (1<<3)
201#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_TWO (0<<4)
202#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_FOUR (1<<4)
203#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_MASK (1<<4)
204#define S5P_FIMV_DEC_STATUS_CRC_GENERATED (1<<5)
205#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED (0<<5)
206#define S5P_FIMV_DEC_STATUS_CRC_MASK (1<<5)
207
208#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
209#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
210#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
211
212/* Decode frame address */
213#define S5P_FIMV_DECODE_Y_ADR 0x2024
214#define S5P_FIMV_DECODE_C_ADR 0x2028
215
216/* Decoded frame tpe */
217#define S5P_FIMV_DECODE_FRAME_TYPE 0x2020
218#define S5P_FIMV_DECODE_FRAME_MASK 7
219
220#define S5P_FIMV_DECODE_FRAME_SKIPPED 0
221#define S5P_FIMV_DECODE_FRAME_I_FRAME 1
222#define S5P_FIMV_DECODE_FRAME_P_FRAME 2
223#define S5P_FIMV_DECODE_FRAME_B_FRAME 3
224#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME 4
225
226/* Sizes of buffers required for decoding */
227#define S5P_FIMV_DEC_NB_IP_SIZE (32 * 1024)
228#define S5P_FIMV_DEC_VERT_NB_MV_SIZE (16 * 1024)
229#define S5P_FIMV_DEC_NB_DCAC_SIZE (16 * 1024)
230#define S5P_FIMV_DEC_UPNB_MV_SIZE (68 * 1024)
231#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE (136 * 1024)
232#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE (32 * 1024)
233#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE (2 * 1024)
234#define S5P_FIMV_DEC_STX_PARSER_SIZE (68 * 1024)
235
236#define S5P_FIMV_DEC_BUF_ALIGN (8 * 1024)
237#define S5P_FIMV_ENC_BUF_ALIGN (8 * 1024)
238#define S5P_FIMV_NV12M_HALIGN 16
239#define S5P_FIMV_NV12M_LVALIGN 16
240#define S5P_FIMV_NV12M_CVALIGN 8
241#define S5P_FIMV_NV12MT_HALIGN 128
242#define S5P_FIMV_NV12MT_VALIGN 32
243#define S5P_FIMV_NV12M_SALIGN 2048
244#define S5P_FIMV_NV12MT_SALIGN 8192
245
246/* Sizes of buffers required for encoding */
247#define S5P_FIMV_ENC_UPMV_SIZE 0x10000
248#define S5P_FIMV_ENC_COLFLG_SIZE 0x10000
249#define S5P_FIMV_ENC_INTRAMD_SIZE 0x10000
250#define S5P_FIMV_ENC_INTRAPRED_SIZE 0x4000
251#define S5P_FIMV_ENC_NBORINFO_SIZE 0x10000
252#define S5P_FIMV_ENC_ACDCCOEF_SIZE 0x10000
253
254/* Encoder */
255#define S5P_FIMV_ENC_SI_STRM_SIZE 0x2004 /* stream size */
256#define S5P_FIMV_ENC_SI_PIC_CNT 0x2008 /* picture count */
257#define S5P_FIMV_ENC_SI_WRITE_PTR 0x200c /* write pointer */
258#define S5P_FIMV_ENC_SI_SLICE_TYPE 0x2010 /* slice type(I/P/B/IDR) */
259#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED 0
260#define S5P_FIMV_ENC_SI_SLICE_TYPE_I 1
261#define S5P_FIMV_ENC_SI_SLICE_TYPE_P 2
262#define S5P_FIMV_ENC_SI_SLICE_TYPE_B 3
263#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED 4
264#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS 5
265#define S5P_FIMV_ENCODED_Y_ADDR 0x2014 /* the addr of the encoded
266 luma pic */
267#define S5P_FIMV_ENCODED_C_ADDR 0x2018 /* the addr of the encoded
268 chroma pic */
269
270#define S5P_FIMV_ENC_SI_CH0_SB_ADR 0x2044 /* addr of stream buf */
271#define S5P_FIMV_ENC_SI_CH0_SB_SIZE 0x204c /* size of stream buf */
272#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR 0x2050 /* current Luma addr */
273#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR 0x2054 /* current Chroma addr */
274#define S5P_FIMV_ENC_SI_CH0_FRAME_INS 0x2058 /* frame insertion */
275
276#define S5P_FIMV_ENC_SI_CH1_SB_ADR 0x2084 /* addr of stream buf */
277#define S5P_FIMV_ENC_SI_CH1_SB_SIZE 0x208c /* size of stream buf */
278#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR 0x2090 /* current Luma addr */
279#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR 0x2094 /* current Chroma addr */
280#define S5P_FIMV_ENC_SI_CH1_FRAME_INS 0x2098 /* frame insertion */
281
282#define S5P_FIMV_ENC_PIC_TYPE_CTRL 0xc504 /* pic type level control */
283#define S5P_FIMV_ENC_B_RECON_WRITE_ON 0xc508 /* B frame recon write ctrl */
284#define S5P_FIMV_ENC_MSLICE_CTRL 0xc50c /* multi slice control */
285#define S5P_FIMV_ENC_MSLICE_MB 0xc510 /* MB number in the one slice */
286#define S5P_FIMV_ENC_MSLICE_BIT 0xc514 /* bit count for one slice */
287#define S5P_FIMV_ENC_CIR_CTRL 0xc518 /* number of intra refresh MB */
288#define S5P_FIMV_ENC_MAP_FOR_CUR 0xc51c /* linear or tiled mode */
289#define S5P_FIMV_ENC_PADDING_CTRL 0xc520 /* padding control */
290
291#define S5P_FIMV_ENC_RC_CONFIG 0xc5a0 /* RC config */
292#define S5P_FIMV_ENC_RC_BIT_RATE 0xc5a8 /* bit rate */
293#define S5P_FIMV_ENC_RC_QBOUND 0xc5ac /* max/min QP */
294#define S5P_FIMV_ENC_RC_RPARA 0xc5b0 /* rate control reaction coeff */
295#define S5P_FIMV_ENC_RC_MB_CTRL 0xc5b4 /* MB adaptive scaling */
296
297/* Encoder for H264 only */
298#define S5P_FIMV_ENC_H264_ENTROPY_MODE 0xd004 /* CAVLC or CABAC */
299#define S5P_FIMV_ENC_H264_ALPHA_OFF 0xd008 /* loop filter alpha offset */
300#define S5P_FIMV_ENC_H264_BETA_OFF 0xd00c /* loop filter beta offset */
301#define S5P_FIMV_ENC_H264_NUM_OF_REF 0xd010 /* number of reference for P/B */
302#define S5P_FIMV_ENC_H264_TRANS_FLAG 0xd034 /* 8x8 transform flag in PPS &
303 high profile */
304
305#define S5P_FIMV_ENC_RC_FRAME_RATE 0xd0d0 /* frame rate */
306
307/* Encoder for MPEG4 only */
308#define S5P_FIMV_ENC_MPEG4_QUART_PXL 0xe008 /* qpel interpolation ctrl */
309
310/* Additional */
311#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL 0x2068 /* DPB Config Control Register */
312#define S5P_FIMV_SLICE_INT_MASK 1
313#define S5P_FIMV_SLICE_INT_SHIFT 31
314#define S5P_FIMV_DDELAY_ENA_SHIFT 30
315#define S5P_FIMV_DDELAY_VAL_MASK 0xff
316#define S5P_FIMV_DDELAY_VAL_SHIFT 16
317#define S5P_FIMV_DPB_COUNT_MASK 0xffff
318#define S5P_FIMV_DPB_FLUSH_MASK 1
319#define S5P_FIMV_DPB_FLUSH_SHIFT 14
320
321
322#define S5P_FIMV_SI_CH0_RELEASE_BUF 0x2060 /* DPB release buffer register */
323#define S5P_FIMV_SI_CH0_HOST_WR_ADR 0x2064 /* address of shared memory */
324
325/* Codec numbers */
326#define S5P_FIMV_CODEC_NONE -1
327
328#define S5P_FIMV_CODEC_H264_DEC 0
329#define S5P_FIMV_CODEC_VC1_DEC 1
330#define S5P_FIMV_CODEC_MPEG4_DEC 2
331#define S5P_FIMV_CODEC_MPEG2_DEC 3
332#define S5P_FIMV_CODEC_H263_DEC 4
333#define S5P_FIMV_CODEC_VC1RCV_DEC 5
334
335#define S5P_FIMV_CODEC_H264_ENC 16
336#define S5P_FIMV_CODEC_MPEG4_ENC 17
337#define S5P_FIMV_CODEC_H263_ENC 18
338
339/* Channel Control Register */
340#define S5P_FIMV_CH_SEQ_HEADER 1
341#define S5P_FIMV_CH_FRAME_START 2
342#define S5P_FIMV_CH_LAST_FRAME 3
343#define S5P_FIMV_CH_INIT_BUFS 4
344#define S5P_FIMV_CH_FRAME_START_REALLOC 5
345#define S5P_FIMV_CH_MASK 7
346#define S5P_FIMV_CH_SHIFT 16
347
348
349/* Host to RISC command */
350#define S5P_FIMV_H2R_CMD_EMPTY 0
351#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE 1
352#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE 2
353#define S5P_FIMV_H2R_CMD_SYS_INIT 3
354#define S5P_FIMV_H2R_CMD_FLUSH 4
355#define S5P_FIMV_H2R_CMD_SLEEP 5
356#define S5P_FIMV_H2R_CMD_WAKEUP 6
357
358#define S5P_FIMV_R2H_CMD_EMPTY 0
359#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET 1
360#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET 2
361#define S5P_FIMV_R2H_CMD_RSV_RET 3
362#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET 4
363#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET 5
364#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET 6
365#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET 7
366#define S5P_FIMV_R2H_CMD_SYS_INIT_RET 8
367#define S5P_FIMV_R2H_CMD_FW_STATUS_RET 9
368#define S5P_FIMV_R2H_CMD_SLEEP_RET 10
369#define S5P_FIMV_R2H_CMD_WAKEUP_RET 11
370#define S5P_FIMV_R2H_CMD_FLUSH_RET 12
371#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET 15
372#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
373#define S5P_FIMV_R2H_CMD_ERR_RET 32
374
375/* Error handling defines */
376#define S5P_FIMV_ERR_WARNINGS_START 145
377#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
378#define S5P_FIMV_ERR_DEC_SHIFT 0
379#define S5P_FIMV_ERR_DSPL_MASK 0xFFFF0000
380#define S5P_FIMV_ERR_DSPL_SHIFT 16
381
382/* Shared memory registers' offsets */
383
384/* An offset of the start position in the stream when
385 * the start position is not aligned */
386#define S5P_FIMV_SHARED_CROP_INFO_H 0x0020
387#define S5P_FIMV_SHARED_CROP_LEFT_MASK 0xFFFF
388#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT 0
389#define S5P_FIMV_SHARED_CROP_RIGHT_MASK 0xFFFF0000
390#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT 16
391#define S5P_FIMV_SHARED_CROP_INFO_V 0x0024
392#define S5P_FIMV_SHARED_CROP_TOP_MASK 0xFFFF
393#define S5P_FIMV_SHARED_CROP_TOP_SHIFT 0
394#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK 0xFFFF0000
395#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT 16
396#define S5P_FIMV_SHARED_SET_FRAME_TAG 0x0004
397#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP 0x0008
398#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT 0x000C
399#define S5P_FIMV_SHARED_START_BYTE_NUM 0x0018
400#define S5P_FIMV_SHARED_RC_VOP_TIMING 0x0030
401#define S5P_FIMV_SHARED_LUMA_DPB_SIZE 0x0064
402#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE 0x0068
403#define S5P_FIMV_SHARED_MV_SIZE 0x006C
404#define S5P_FIMV_SHARED_PIC_TIME_TOP 0x0010
405#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM 0x0014
406#define S5P_FIMV_SHARED_EXT_ENC_CONTROL 0x0028
407#define S5P_FIMV_SHARED_P_B_FRAME_QP 0x0070
408#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC 0x0074
409#define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
410#define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
411#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
412
413#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
new file mode 100644
index 000000000000..7dc7eab58b38
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -0,0 +1,1274 @@
1/*
2 * Samsung S5P Multi Format Codec v 5.1
3 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * Kamil Debski, <k.debski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/version.h>
22#include <linux/videodev2.h>
23#include <linux/workqueue.h>
24#include <media/videobuf2-core.h>
25#include "regs-mfc.h"
26#include "s5p_mfc_ctrl.h"
27#include "s5p_mfc_debug.h"
28#include "s5p_mfc_dec.h"
29#include "s5p_mfc_enc.h"
30#include "s5p_mfc_intr.h"
31#include "s5p_mfc_opr.h"
32#include "s5p_mfc_pm.h"
33#include "s5p_mfc_shm.h"
34
35#define S5P_MFC_NAME "s5p-mfc"
36#define S5P_MFC_DEC_NAME "s5p-mfc-dec"
37#define S5P_MFC_ENC_NAME "s5p-mfc-enc"
38
39int debug;
40module_param(debug, int, S_IRUGO | S_IWUSR);
41MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");
42
43/* Helper functions for interrupt processing */
44/* Remove from hw execution round robin */
45static void clear_work_bit(struct s5p_mfc_ctx *ctx)
46{
47 struct s5p_mfc_dev *dev = ctx->dev;
48
49 spin_lock(&dev->condlock);
50 clear_bit(ctx->num, &dev->ctx_work_bits);
51 spin_unlock(&dev->condlock);
52}
53
54/* Wake up context wait_queue */
55static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
56 unsigned int err)
57{
58 ctx->int_cond = 1;
59 ctx->int_type = reason;
60 ctx->int_err = err;
61 wake_up(&ctx->queue);
62}
63
64/* Wake up device wait_queue */
65static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
66 unsigned int err)
67{
68 dev->int_cond = 1;
69 dev->int_type = reason;
70 dev->int_err = err;
71 wake_up(&dev->queue);
72}
73
74void s5p_mfc_watchdog(unsigned long arg)
75{
76 struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg;
77
78 if (test_bit(0, &dev->hw_lock))
79 atomic_inc(&dev->watchdog_cnt);
80 if (atomic_read(&dev->watchdog_cnt) >= MFC_WATCHDOG_CNT) {
81 /* This means that hw is busy and no interrupts were
82 * generated by hw for the Nth time of running this
83 * watchdog timer. This usually means a serious hw
84 * error. Now it is time to kill all instances and
85 * reset the MFC. */
86 mfc_err("Time out during waiting for HW\n");
87 queue_work(dev->watchdog_workqueue, &dev->watchdog_work);
88 }
89 dev->watchdog_timer.expires = jiffies +
90 msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
91 add_timer(&dev->watchdog_timer);
92}
93
94static void s5p_mfc_watchdog_worker(struct work_struct *work)
95{
96 struct s5p_mfc_dev *dev;
97 struct s5p_mfc_ctx *ctx;
98 unsigned long flags;
99 int mutex_locked;
100 int i, ret;
101
102 dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
103
104 mfc_err("Driver timeout error handling\n");
105 /* Lock the mutex that protects open and release.
106 * This is necessary as they may load and unload firmware. */
107 mutex_locked = mutex_trylock(&dev->mfc_mutex);
108 if (!mutex_locked)
109 mfc_err("Error: some instance may be closing/opening\n");
110 spin_lock_irqsave(&dev->irqlock, flags);
111
112 s5p_mfc_clock_off();
113
114 for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
115 ctx = dev->ctx[i];
116 if (!ctx)
117 continue;
118 ctx->state = MFCINST_ERROR;
119 s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
120 s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
121 clear_work_bit(ctx);
122 wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
123 }
124 clear_bit(0, &dev->hw_lock);
125 spin_unlock_irqrestore(&dev->irqlock, flags);
126 /* Double check if there is at least one instance running.
127 * If no instance is in memory than no firmware should be present */
128 if (dev->num_inst > 0) {
129 ret = s5p_mfc_reload_firmware(dev);
130 if (ret) {
131 mfc_err("Failed to reload FW\n");
132 goto unlock;
133 }
134 s5p_mfc_clock_on();
135 ret = s5p_mfc_init_hw(dev);
136 if (ret)
137 mfc_err("Failed to reinit FW\n");
138 }
139unlock:
140 if (mutex_locked)
141 mutex_unlock(&dev->mfc_mutex);
142}
143
144static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
145{
146 struct video_device *vdev = video_devdata(file);
147
148 if (!vdev) {
149 mfc_err("failed to get video_device");
150 return MFCNODE_INVALID;
151 }
152 if (vdev->index == 0)
153 return MFCNODE_DECODER;
154 else if (vdev->index == 1)
155 return MFCNODE_ENCODER;
156 return MFCNODE_INVALID;
157}
158
159static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
160{
161 mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
162 mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
163 mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
164}
165
166static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
167{
168 struct s5p_mfc_buf *dst_buf;
169
170 ctx->state = MFCINST_FINISHED;
171 ctx->sequence++;
172 while (!list_empty(&ctx->dst_queue)) {
173 dst_buf = list_entry(ctx->dst_queue.next,
174 struct s5p_mfc_buf, list);
175 mfc_debug(2, "Cleaning up buffer: %d\n",
176 dst_buf->b->v4l2_buf.index);
177 vb2_set_plane_payload(dst_buf->b, 0, 0);
178 vb2_set_plane_payload(dst_buf->b, 1, 0);
179 list_del(&dst_buf->list);
180 ctx->dst_queue_cnt--;
181 dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
182
183 if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
184 s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
185 dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
186 else
187 dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
188
189 ctx->dec_dst_flag &= ~(1 << dst_buf->b->v4l2_buf.index);
190 vb2_buffer_done(dst_buf->b, VB2_BUF_STATE_DONE);
191 }
192}
193
194static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
195{
196 struct s5p_mfc_dev *dev = ctx->dev;
197 struct s5p_mfc_buf *dst_buf, *src_buf;
198 size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
199 unsigned int frame_type = s5p_mfc_get_frame_type();
200
201 /* Copy timestamp / timecode from decoded src to dst and set
202 appropraite flags */
203 src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
204 list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
205 if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dec_y_addr) {
206 memcpy(&dst_buf->b->v4l2_buf.timecode,
207 &src_buf->b->v4l2_buf.timecode,
208 sizeof(struct v4l2_timecode));
209 memcpy(&dst_buf->b->v4l2_buf.timestamp,
210 &src_buf->b->v4l2_buf.timestamp,
211 sizeof(struct timeval));
212 switch (frame_type) {
213 case S5P_FIMV_DECODE_FRAME_I_FRAME:
214 dst_buf->b->v4l2_buf.flags |=
215 V4L2_BUF_FLAG_KEYFRAME;
216 break;
217 case S5P_FIMV_DECODE_FRAME_P_FRAME:
218 dst_buf->b->v4l2_buf.flags |=
219 V4L2_BUF_FLAG_PFRAME;
220 break;
221 case S5P_FIMV_DECODE_FRAME_B_FRAME:
222 dst_buf->b->v4l2_buf.flags |=
223 V4L2_BUF_FLAG_BFRAME;
224 break;
225 }
226 break;
227 }
228 }
229}
230
231static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
232{
233 struct s5p_mfc_dev *dev = ctx->dev;
234 struct s5p_mfc_buf *dst_buf;
235 size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
236 unsigned int frame_type = s5p_mfc_get_frame_type();
237 unsigned int index;
238
239 /* If frame is same as previous then skip and do not dequeue */
240 if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
241 if (!ctx->after_packed_pb)
242 ctx->sequence++;
243 ctx->after_packed_pb = 0;
244 return;
245 }
246 ctx->sequence++;
247 /* The MFC returns address of the buffer, now we have to
248 * check which videobuf does it correspond to */
249 list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
250 /* Check if this is the buffer we're looking for */
251 if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dspl_y_addr) {
252 list_del(&dst_buf->list);
253 ctx->dst_queue_cnt--;
254 dst_buf->b->v4l2_buf.sequence = ctx->sequence;
255 if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
256 s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
257 dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
258 else
259 dst_buf->b->v4l2_buf.field =
260 V4L2_FIELD_INTERLACED;
261 vb2_set_plane_payload(dst_buf->b, 0, ctx->luma_size);
262 vb2_set_plane_payload(dst_buf->b, 1, ctx->chroma_size);
263 clear_bit(dst_buf->b->v4l2_buf.index,
264 &ctx->dec_dst_flag);
265
266 vb2_buffer_done(dst_buf->b,
267 err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
268
269 index = dst_buf->b->v4l2_buf.index;
270 break;
271 }
272 }
273}
274
275/* Handle frame decoding interrupt */
276static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
277 unsigned int reason, unsigned int err)
278{
279 struct s5p_mfc_dev *dev = ctx->dev;
280 unsigned int dst_frame_status;
281 struct s5p_mfc_buf *src_buf;
282 unsigned long flags;
283 unsigned int res_change;
284
285 unsigned int index;
286
287 dst_frame_status = s5p_mfc_get_dspl_status()
288 & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
289 res_change = s5p_mfc_get_dspl_status()
290 & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
291 mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
292 if (ctx->state == MFCINST_RES_CHANGE_INIT)
293 ctx->state = MFCINST_RES_CHANGE_FLUSH;
294 if (res_change) {
295 ctx->state = MFCINST_RES_CHANGE_INIT;
296 s5p_mfc_clear_int_flags(dev);
297 wake_up_ctx(ctx, reason, err);
298 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
299 BUG();
300 s5p_mfc_clock_off();
301 s5p_mfc_try_run(dev);
302 return;
303 }
304 if (ctx->dpb_flush_flag)
305 ctx->dpb_flush_flag = 0;
306
307 spin_lock_irqsave(&dev->irqlock, flags);
308 /* All frames remaining in the buffer have been extracted */
309 if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) {
310 if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
311 s5p_mfc_handle_frame_all_extracted(ctx);
312 ctx->state = MFCINST_RES_CHANGE_END;
313 goto leave_handle_frame;
314 } else {
315 s5p_mfc_handle_frame_all_extracted(ctx);
316 }
317 }
318
319 if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY ||
320 dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY)
321 s5p_mfc_handle_frame_copy_time(ctx);
322
323 /* A frame has been decoded and is in the buffer */
324 if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
325 dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) {
326 s5p_mfc_handle_frame_new(ctx, err);
327 } else {
328 mfc_debug(2, "No frame decode\n");
329 }
330 /* Mark source buffer as complete */
331 if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY
332 && !list_empty(&ctx->src_queue)) {
333 src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
334 list);
335 ctx->consumed_stream += s5p_mfc_get_consumed_stream();
336 if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
337 s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
338 && ctx->consumed_stream + STUFF_BYTE <
339 src_buf->b->v4l2_planes[0].bytesused) {
340 /* Run MFC again on the same buffer */
341 mfc_debug(2, "Running again the same buffer\n");
342 ctx->after_packed_pb = 1;
343 } else {
344 index = src_buf->b->v4l2_buf.index;
345 mfc_debug(2, "MFC needs next buffer\n");
346 ctx->consumed_stream = 0;
347 list_del(&src_buf->list);
348 ctx->src_queue_cnt--;
349 if (s5p_mfc_err_dec(err) > 0)
350 vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
351 else
352 vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
353 }
354 }
355leave_handle_frame:
356 spin_unlock_irqrestore(&dev->irqlock, flags);
357 if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
358 || ctx->dst_queue_cnt < ctx->dpb_count)
359 clear_work_bit(ctx);
360 s5p_mfc_clear_int_flags(dev);
361 wake_up_ctx(ctx, reason, err);
362 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
363 BUG();
364 s5p_mfc_clock_off();
365 s5p_mfc_try_run(dev);
366}
367
368/* Error handling for interrupt */
369static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
370 unsigned int reason, unsigned int err)
371{
372 struct s5p_mfc_dev *dev;
373 unsigned long flags;
374
375 /* If no context is available then all necessary
376 * processing has been done. */
377 if (ctx == 0)
378 return;
379
380 dev = ctx->dev;
381 mfc_err("Interrupt Error: %08x\n", err);
382 s5p_mfc_clear_int_flags(dev);
383 wake_up_dev(dev, reason, err);
384
385 /* Error recovery is dependent on the state of context */
386 switch (ctx->state) {
387 case MFCINST_INIT:
388 /* This error had to happen while acquireing instance */
389 case MFCINST_GOT_INST:
390 /* This error had to happen while parsing the header */
391 case MFCINST_HEAD_PARSED:
392 /* This error had to happen while setting dst buffers */
393 case MFCINST_RETURN_INST:
394 /* This error had to happen while releasing instance */
395 clear_work_bit(ctx);
396 wake_up_ctx(ctx, reason, err);
397 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
398 BUG();
399 s5p_mfc_clock_off();
400 ctx->state = MFCINST_ERROR;
401 break;
402 case MFCINST_FINISHING:
403 case MFCINST_FINISHED:
404 case MFCINST_RUNNING:
405 /* It is higly probable that an error occured
406 * while decoding a frame */
407 clear_work_bit(ctx);
408 ctx->state = MFCINST_ERROR;
409 /* Mark all dst buffers as having an error */
410 spin_lock_irqsave(&dev->irqlock, flags);
411 s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
412 /* Mark all src buffers as having an error */
413 s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
414 spin_unlock_irqrestore(&dev->irqlock, flags);
415 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
416 BUG();
417 s5p_mfc_clock_off();
418 break;
419 default:
420 mfc_err("Encountered an error interrupt which had not been handled\n");
421 break;
422 }
423 return;
424}
425
426/* Header parsing interrupt handling */
427static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
428 unsigned int reason, unsigned int err)
429{
430 struct s5p_mfc_dev *dev;
431 unsigned int guard_width, guard_height;
432
433 if (ctx == 0)
434 return;
435 dev = ctx->dev;
436 if (ctx->c_ops->post_seq_start) {
437 if (ctx->c_ops->post_seq_start(ctx))
438 mfc_err("post_seq_start() failed\n");
439 } else {
440 ctx->img_width = s5p_mfc_get_img_width();
441 ctx->img_height = s5p_mfc_get_img_height();
442
443 ctx->buf_width = ALIGN(ctx->img_width,
444 S5P_FIMV_NV12MT_HALIGN);
445 ctx->buf_height = ALIGN(ctx->img_height,
446 S5P_FIMV_NV12MT_VALIGN);
447 mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
448 "buffer dimensions: %dx%d\n", ctx->img_width,
449 ctx->img_height, ctx->buf_width,
450 ctx->buf_height);
451 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
452 ctx->luma_size = ALIGN(ctx->buf_width *
453 ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
454 ctx->chroma_size = ALIGN(ctx->buf_width *
455 ALIGN((ctx->img_height >> 1),
456 S5P_FIMV_NV12MT_VALIGN),
457 S5P_FIMV_DEC_BUF_ALIGN);
458 ctx->mv_size = ALIGN(ctx->buf_width *
459 ALIGN((ctx->buf_height >> 2),
460 S5P_FIMV_NV12MT_VALIGN),
461 S5P_FIMV_DEC_BUF_ALIGN);
462 } else {
463 guard_width = ALIGN(ctx->img_width + 24,
464 S5P_FIMV_NV12MT_HALIGN);
465 guard_height = ALIGN(ctx->img_height + 16,
466 S5P_FIMV_NV12MT_VALIGN);
467 ctx->luma_size = ALIGN(guard_width *
468 guard_height, S5P_FIMV_DEC_BUF_ALIGN);
469 guard_width = ALIGN(ctx->img_width + 16,
470 S5P_FIMV_NV12MT_HALIGN);
471 guard_height = ALIGN((ctx->img_height >> 1) + 4,
472 S5P_FIMV_NV12MT_VALIGN);
473 ctx->chroma_size = ALIGN(guard_width *
474 guard_height, S5P_FIMV_DEC_BUF_ALIGN);
475 ctx->mv_size = 0;
476 }
477 ctx->dpb_count = s5p_mfc_get_dpb_count();
478 if (ctx->img_width == 0 || ctx->img_width == 0)
479 ctx->state = MFCINST_ERROR;
480 else
481 ctx->state = MFCINST_HEAD_PARSED;
482 }
483 s5p_mfc_clear_int_flags(dev);
484 clear_work_bit(ctx);
485 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
486 BUG();
487 s5p_mfc_clock_off();
488 s5p_mfc_try_run(dev);
489 wake_up_ctx(ctx, reason, err);
490}
491
492/* Header parsing interrupt handling */
493static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
494 unsigned int reason, unsigned int err)
495{
496 struct s5p_mfc_buf *src_buf;
497 struct s5p_mfc_dev *dev;
498 unsigned long flags;
499
500 if (ctx == 0)
501 return;
502 dev = ctx->dev;
503 s5p_mfc_clear_int_flags(dev);
504 ctx->int_type = reason;
505 ctx->int_err = err;
506 ctx->int_cond = 1;
507 spin_lock(&dev->condlock);
508 clear_bit(ctx->num, &dev->ctx_work_bits);
509 spin_unlock(&dev->condlock);
510 if (err == 0) {
511 ctx->state = MFCINST_RUNNING;
512 if (!ctx->dpb_flush_flag) {
513 spin_lock_irqsave(&dev->irqlock, flags);
514 if (!list_empty(&ctx->src_queue)) {
515 src_buf = list_entry(ctx->src_queue.next,
516 struct s5p_mfc_buf, list);
517 list_del(&src_buf->list);
518 ctx->src_queue_cnt--;
519 vb2_buffer_done(src_buf->b,
520 VB2_BUF_STATE_DONE);
521 }
522 spin_unlock_irqrestore(&dev->irqlock, flags);
523 } else {
524 ctx->dpb_flush_flag = 0;
525 }
526 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
527 BUG();
528
529 s5p_mfc_clock_off();
530
531 wake_up(&ctx->queue);
532 s5p_mfc_try_run(dev);
533 } else {
534 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
535 BUG();
536
537 s5p_mfc_clock_off();
538
539 wake_up(&ctx->queue);
540 }
541}
542
543/* Interrupt processing */
544static irqreturn_t s5p_mfc_irq(int irq, void *priv)
545{
546 struct s5p_mfc_dev *dev = priv;
547 struct s5p_mfc_ctx *ctx;
548 unsigned int reason;
549 unsigned int err;
550
551 mfc_debug_enter();
552 /* Reset the timeout watchdog */
553 atomic_set(&dev->watchdog_cnt, 0);
554 ctx = dev->ctx[dev->curr_ctx];
555 /* Get the reason of interrupt and the error code */
556 reason = s5p_mfc_get_int_reason();
557 err = s5p_mfc_get_int_err();
558 mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
559 switch (reason) {
560 case S5P_FIMV_R2H_CMD_ERR_RET:
561 /* An error has occured */
562 if (ctx->state == MFCINST_RUNNING &&
563 s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
564 s5p_mfc_handle_frame(ctx, reason, err);
565 else
566 s5p_mfc_handle_error(ctx, reason, err);
567 clear_bit(0, &dev->enter_suspend);
568 break;
569
570 case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
571 case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
572 if (ctx->c_ops->post_frame_start) {
573 if (ctx->c_ops->post_frame_start(ctx))
574 mfc_err("post_frame_start() failed\n");
575 s5p_mfc_clear_int_flags(dev);
576 wake_up_ctx(ctx, reason, err);
577 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
578 BUG();
579 s5p_mfc_clock_off();
580 s5p_mfc_try_run(dev);
581 } else {
582 s5p_mfc_handle_frame(ctx, reason, err);
583 }
584 break;
585
586 case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
587 s5p_mfc_handle_seq_done(ctx, reason, err);
588 break;
589
590 case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
591 ctx->inst_no = s5p_mfc_get_inst_no();
592 ctx->state = MFCINST_GOT_INST;
593 clear_work_bit(ctx);
594 wake_up(&ctx->queue);
595 goto irq_cleanup_hw;
596
597 case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
598 clear_work_bit(ctx);
599 ctx->state = MFCINST_FREE;
600 wake_up(&ctx->queue);
601 goto irq_cleanup_hw;
602
603 case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
604 case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
605 case S5P_FIMV_R2H_CMD_SLEEP_RET:
606 case S5P_FIMV_R2H_CMD_WAKEUP_RET:
607 if (ctx)
608 clear_work_bit(ctx);
609 s5p_mfc_clear_int_flags(dev);
610 wake_up_dev(dev, reason, err);
611 clear_bit(0, &dev->hw_lock);
612 clear_bit(0, &dev->enter_suspend);
613 break;
614
615 case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
616 s5p_mfc_handle_init_buffers(ctx, reason, err);
617 break;
618 default:
619 mfc_debug(2, "Unknown int reason\n");
620 s5p_mfc_clear_int_flags(dev);
621 }
622 mfc_debug_leave();
623 return IRQ_HANDLED;
624irq_cleanup_hw:
625 s5p_mfc_clear_int_flags(dev);
626 ctx->int_type = reason;
627 ctx->int_err = err;
628 ctx->int_cond = 1;
629 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
630 mfc_err("Failed to unlock hw\n");
631
632 s5p_mfc_clock_off();
633
634 s5p_mfc_try_run(dev);
635 mfc_debug(2, "Exit via irq_cleanup_hw\n");
636 return IRQ_HANDLED;
637}
638
639/* Open an MFC node */
640static int s5p_mfc_open(struct file *file)
641{
642 struct s5p_mfc_dev *dev = video_drvdata(file);
643 struct s5p_mfc_ctx *ctx = NULL;
644 struct vb2_queue *q;
645 unsigned long flags;
646 int ret = 0;
647
648 mfc_debug_enter();
649 dev->num_inst++; /* It is guarded by mfc_mutex in vfd */
650 /* Allocate memory for context */
651 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
652 if (!ctx) {
653 mfc_err("Not enough memory\n");
654 ret = -ENOMEM;
655 goto err_alloc;
656 }
657 v4l2_fh_init(&ctx->fh, video_devdata(file));
658 file->private_data = &ctx->fh;
659 v4l2_fh_add(&ctx->fh);
660 ctx->dev = dev;
661 INIT_LIST_HEAD(&ctx->src_queue);
662 INIT_LIST_HEAD(&ctx->dst_queue);
663 ctx->src_queue_cnt = 0;
664 ctx->dst_queue_cnt = 0;
665 /* Get context number */
666 ctx->num = 0;
667 while (dev->ctx[ctx->num]) {
668 ctx->num++;
669 if (ctx->num >= MFC_NUM_CONTEXTS) {
670 mfc_err("Too many open contexts\n");
671 ret = -EBUSY;
672 goto err_no_ctx;
673 }
674 }
675 /* Mark context as idle */
676 spin_lock_irqsave(&dev->condlock, flags);
677 clear_bit(ctx->num, &dev->ctx_work_bits);
678 spin_unlock_irqrestore(&dev->condlock, flags);
679 dev->ctx[ctx->num] = ctx;
680 if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
681 ctx->type = MFCINST_DECODER;
682 ctx->c_ops = get_dec_codec_ops();
683 /* Setup ctrl handler */
684 ret = s5p_mfc_dec_ctrls_setup(ctx);
685 if (ret) {
686 mfc_err("Failed to setup mfc controls\n");
687 goto err_ctrls_setup;
688 }
689 } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
690 ctx->type = MFCINST_ENCODER;
691 ctx->c_ops = get_enc_codec_ops();
692 /* only for encoder */
693 INIT_LIST_HEAD(&ctx->ref_queue);
694 ctx->ref_queue_cnt = 0;
695 /* Setup ctrl handler */
696 ret = s5p_mfc_enc_ctrls_setup(ctx);
697 if (ret) {
698 mfc_err("Failed to setup mfc controls\n");
699 goto err_ctrls_setup;
700 }
701 } else {
702 ret = -ENOENT;
703 goto err_bad_node;
704 }
705 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
706 ctx->inst_no = -1;
707 /* Load firmware if this is the first instance */
708 if (dev->num_inst == 1) {
709 dev->watchdog_timer.expires = jiffies +
710 msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
711 add_timer(&dev->watchdog_timer);
712 ret = s5p_mfc_power_on();
713 if (ret < 0) {
714 mfc_err("power on failed\n");
715 goto err_pwr_enable;
716 }
717 s5p_mfc_clock_on();
718 ret = s5p_mfc_alloc_and_load_firmware(dev);
719 if (ret)
720 goto err_alloc_fw;
721 /* Init the FW */
722 ret = s5p_mfc_init_hw(dev);
723 if (ret)
724 goto err_init_hw;
725 s5p_mfc_clock_off();
726 }
727 /* Init videobuf2 queue for CAPTURE */
728 q = &ctx->vq_dst;
729 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
730 q->drv_priv = &ctx->fh;
731 if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
732 q->io_modes = VB2_MMAP;
733 q->ops = get_dec_queue_ops();
734 } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
735 q->io_modes = VB2_MMAP | VB2_USERPTR;
736 q->ops = get_enc_queue_ops();
737 } else {
738 ret = -ENOENT;
739 goto err_queue_init;
740 }
741 q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
742 ret = vb2_queue_init(q);
743 if (ret) {
744 mfc_err("Failed to initialize videobuf2 queue(capture)\n");
745 goto err_queue_init;
746 }
747 /* Init videobuf2 queue for OUTPUT */
748 q = &ctx->vq_src;
749 q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
750 q->io_modes = VB2_MMAP;
751 q->drv_priv = &ctx->fh;
752 if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
753 q->io_modes = VB2_MMAP;
754 q->ops = get_dec_queue_ops();
755 } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) {
756 q->io_modes = VB2_MMAP | VB2_USERPTR;
757 q->ops = get_enc_queue_ops();
758 } else {
759 ret = -ENOENT;
760 goto err_queue_init;
761 }
762 q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
763 ret = vb2_queue_init(q);
764 if (ret) {
765 mfc_err("Failed to initialize videobuf2 queue(output)\n");
766 goto err_queue_init;
767 }
768 init_waitqueue_head(&ctx->queue);
769 mfc_debug_leave();
770 return ret;
771 /* Deinit when failure occured */
772err_queue_init:
773err_init_hw:
774 s5p_mfc_release_firmware(dev);
775err_alloc_fw:
776 dev->ctx[ctx->num] = 0;
777 del_timer_sync(&dev->watchdog_timer);
778 s5p_mfc_clock_off();
779err_pwr_enable:
780 if (dev->num_inst == 1) {
781 if (s5p_mfc_power_off() < 0)
782 mfc_err("power off failed\n");
783 s5p_mfc_release_firmware(dev);
784 }
785err_ctrls_setup:
786 s5p_mfc_dec_ctrls_delete(ctx);
787err_bad_node:
788err_no_ctx:
789 v4l2_fh_del(&ctx->fh);
790 v4l2_fh_exit(&ctx->fh);
791 kfree(ctx);
792err_alloc:
793 dev->num_inst--;
794 mfc_debug_leave();
795 return ret;
796}
797
798/* Release MFC context */
799static int s5p_mfc_release(struct file *file)
800{
801 struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
802 struct s5p_mfc_dev *dev = ctx->dev;
803 unsigned long flags;
804
805 mfc_debug_enter();
806 s5p_mfc_clock_on();
807 vb2_queue_release(&ctx->vq_src);
808 vb2_queue_release(&ctx->vq_dst);
809 /* Mark context as idle */
810 spin_lock_irqsave(&dev->condlock, flags);
811 clear_bit(ctx->num, &dev->ctx_work_bits);
812 spin_unlock_irqrestore(&dev->condlock, flags);
813 /* If instance was initialised then
814 * return instance and free reosurces */
815 if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
816 mfc_debug(2, "Has to free instance\n");
817 ctx->state = MFCINST_RETURN_INST;
818 spin_lock_irqsave(&dev->condlock, flags);
819 set_bit(ctx->num, &dev->ctx_work_bits);
820 spin_unlock_irqrestore(&dev->condlock, flags);
821 s5p_mfc_clean_ctx_int_flags(ctx);
822 s5p_mfc_try_run(dev);
823 /* Wait until instance is returned or timeout occured */
824 if (s5p_mfc_wait_for_done_ctx
825 (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
826 s5p_mfc_clock_off();
827 mfc_err("Err returning instance\n");
828 }
829 mfc_debug(2, "After free instance\n");
830 /* Free resources */
831 s5p_mfc_release_codec_buffers(ctx);
832 s5p_mfc_release_instance_buffer(ctx);
833 if (ctx->type == MFCINST_DECODER)
834 s5p_mfc_release_dec_desc_buffer(ctx);
835
836 ctx->inst_no = MFC_NO_INSTANCE_SET;
837 }
838 /* hardware locking scheme */
839 if (dev->curr_ctx == ctx->num)
840 clear_bit(0, &dev->hw_lock);
841 dev->num_inst--;
842 if (dev->num_inst == 0) {
843 mfc_debug(2, "Last instance - release firmware\n");
844 /* reset <-> F/W release */
845 s5p_mfc_reset(dev);
846 s5p_mfc_release_firmware(dev);
847 del_timer_sync(&dev->watchdog_timer);
848 if (s5p_mfc_power_off() < 0)
849 mfc_err("Power off failed\n");
850 }
851 mfc_debug(2, "Shutting down clock\n");
852 s5p_mfc_clock_off();
853 dev->ctx[ctx->num] = 0;
854 s5p_mfc_dec_ctrls_delete(ctx);
855 v4l2_fh_del(&ctx->fh);
856 v4l2_fh_exit(&ctx->fh);
857 kfree(ctx);
858 mfc_debug_leave();
859 return 0;
860}
861
862/* Poll */
863static unsigned int s5p_mfc_poll(struct file *file,
864 struct poll_table_struct *wait)
865{
866 struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
867 struct s5p_mfc_dev *dev = ctx->dev;
868 struct vb2_queue *src_q, *dst_q;
869 struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
870 unsigned int rc = 0;
871 unsigned long flags;
872
873 src_q = &ctx->vq_src;
874 dst_q = &ctx->vq_dst;
875 /*
876 * There has to be at least one buffer queued on each queued_list, which
877 * means either in driver already or waiting for driver to claim it
878 * and start processing.
879 */
880 if ((!src_q->streaming || list_empty(&src_q->queued_list))
881 && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
882 rc = POLLERR;
883 goto end;
884 }
885 mutex_unlock(&dev->mfc_mutex);
886 poll_wait(file, &src_q->done_wq, wait);
887 poll_wait(file, &dst_q->done_wq, wait);
888 mutex_lock(&dev->mfc_mutex);
889 spin_lock_irqsave(&src_q->done_lock, flags);
890 if (!list_empty(&src_q->done_list))
891 src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
892 done_entry);
893 if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
894 || src_vb->state == VB2_BUF_STATE_ERROR))
895 rc |= POLLOUT | POLLWRNORM;
896 spin_unlock_irqrestore(&src_q->done_lock, flags);
897 spin_lock_irqsave(&dst_q->done_lock, flags);
898 if (!list_empty(&dst_q->done_list))
899 dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
900 done_entry);
901 if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
902 || dst_vb->state == VB2_BUF_STATE_ERROR))
903 rc |= POLLIN | POLLRDNORM;
904 spin_unlock_irqrestore(&dst_q->done_lock, flags);
905end:
906 return rc;
907}
908
909/* Mmap */
910static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
911{
912 struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
913 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
914 int ret;
915 if (offset < DST_QUEUE_OFF_BASE) {
916 mfc_debug(2, "mmaping source\n");
917 ret = vb2_mmap(&ctx->vq_src, vma);
918 } else { /* capture */
919 mfc_debug(2, "mmaping destination\n");
920 vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
921 ret = vb2_mmap(&ctx->vq_dst, vma);
922 }
923 return ret;
924}
925
926/* v4l2 ops */
927static const struct v4l2_file_operations s5p_mfc_fops = {
928 .owner = THIS_MODULE,
929 .open = s5p_mfc_open,
930 .release = s5p_mfc_release,
931 .poll = s5p_mfc_poll,
932 .unlocked_ioctl = video_ioctl2,
933 .mmap = s5p_mfc_mmap,
934};
935
936static int match_child(struct device *dev, void *data)
937{
938 if (!dev_name(dev))
939 return 0;
940 return !strcmp(dev_name(dev), (char *)data);
941}
942
943
944/* MFC probe function */
945static int __devinit s5p_mfc_probe(struct platform_device *pdev)
946{
947 struct s5p_mfc_dev *dev;
948 struct video_device *vfd;
949 struct resource *res;
950 int ret;
951
952 pr_debug("%s++\n", __func__);
953 dev = kzalloc(sizeof *dev, GFP_KERNEL);
954 if (!dev) {
955 dev_err(&pdev->dev, "Not enough memory for MFC device\n");
956 return -ENOMEM;
957 }
958
959 spin_lock_init(&dev->irqlock);
960 spin_lock_init(&dev->condlock);
961 dev->plat_dev = pdev;
962 if (!dev->plat_dev) {
963 dev_err(&pdev->dev, "No platform data specified\n");
964 ret = -ENODEV;
965 goto err_dev;
966 }
967
968 ret = s5p_mfc_init_pm(dev);
969 if (ret < 0) {
970 dev_err(&pdev->dev, "failed to get mfc clock source\n");
971 goto err_clk;
972 }
973
974 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
975 if (res == NULL) {
976 dev_err(&pdev->dev, "failed to get memory region resource\n");
977 ret = -ENOENT;
978 goto err_res;
979 }
980
981 dev->mfc_mem = request_mem_region(res->start, resource_size(res),
982 pdev->name);
983 if (dev->mfc_mem == NULL) {
984 dev_err(&pdev->dev, "failed to get memory region\n");
985 ret = -ENOENT;
986 goto err_mem_reg;
987 }
988 dev->regs_base = ioremap(dev->mfc_mem->start, resource_size(dev->mfc_mem));
989 if (dev->regs_base == NULL) {
990 dev_err(&pdev->dev, "failed to ioremap address region\n");
991 ret = -ENOENT;
992 goto err_ioremap;
993 }
994
995 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
996 if (res == NULL) {
997 dev_err(&pdev->dev, "failed to get irq resource\n");
998 ret = -ENOENT;
999 goto err_get_res;
1000 }
1001 dev->irq = res->start;
1002 ret = request_irq(dev->irq, s5p_mfc_irq, IRQF_DISABLED, pdev->name,
1003 dev);
1004 if (ret) {
1005 dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
1006 goto err_req_irq;
1007 }
1008
1009 dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l",
1010 match_child);
1011 if (!dev->mem_dev_l) {
1012 mfc_err("Mem child (L) device get failed\n");
1013 ret = -ENODEV;
1014 goto err_find_child;
1015 }
1016 dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
1017 match_child);
1018 if (!dev->mem_dev_r) {
1019 mfc_err("Mem child (R) device get failed\n");
1020 ret = -ENODEV;
1021 goto err_find_child;
1022 }
1023
1024 dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
1025 if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
1026 ret = PTR_ERR(dev->alloc_ctx[0]);
1027 goto err_mem_init_ctx_0;
1028 }
1029 dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
1030 if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) {
1031 ret = PTR_ERR(dev->alloc_ctx[1]);
1032 goto err_mem_init_ctx_1;
1033 }
1034
1035 mutex_init(&dev->mfc_mutex);
1036
1037 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
1038 if (ret)
1039 goto err_v4l2_dev_reg;
1040 init_waitqueue_head(&dev->queue);
1041
1042 /* decoder */
1043 vfd = video_device_alloc();
1044 if (!vfd) {
1045 v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
1046 ret = -ENOMEM;
1047 goto err_dec_alloc;
1048 }
1049 vfd->fops = &s5p_mfc_fops,
1050 vfd->ioctl_ops = get_dec_v4l2_ioctl_ops();
1051 vfd->release = video_device_release,
1052 vfd->lock = &dev->mfc_mutex;
1053 vfd->v4l2_dev = &dev->v4l2_dev;
1054 snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
1055 dev->vfd_dec = vfd;
1056 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1057 if (ret) {
1058 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1059 video_device_release(vfd);
1060 goto err_dec_reg;
1061 }
1062 v4l2_info(&dev->v4l2_dev,
1063 "decoder registered as /dev/video%d\n", vfd->num);
1064 video_set_drvdata(vfd, dev);
1065
1066 /* encoder */
1067 vfd = video_device_alloc();
1068 if (!vfd) {
1069 v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
1070 ret = -ENOMEM;
1071 goto err_enc_alloc;
1072 }
1073 vfd->fops = &s5p_mfc_fops,
1074 vfd->ioctl_ops = get_enc_v4l2_ioctl_ops();
1075 vfd->release = video_device_release,
1076 vfd->lock = &dev->mfc_mutex;
1077 vfd->v4l2_dev = &dev->v4l2_dev;
1078 snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
1079 dev->vfd_enc = vfd;
1080 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1081 if (ret) {
1082 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1083 video_device_release(vfd);
1084 goto err_enc_reg;
1085 }
1086 v4l2_info(&dev->v4l2_dev,
1087 "encoder registered as /dev/video%d\n", vfd->num);
1088 video_set_drvdata(vfd, dev);
1089 platform_set_drvdata(pdev, dev);
1090
1091 dev->hw_lock = 0;
1092 dev->watchdog_workqueue = create_singlethread_workqueue(S5P_MFC_NAME);
1093 INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
1094 atomic_set(&dev->watchdog_cnt, 0);
1095 init_timer(&dev->watchdog_timer);
1096 dev->watchdog_timer.data = (unsigned long)dev;
1097 dev->watchdog_timer.function = s5p_mfc_watchdog;
1098
1099 pr_debug("%s--\n", __func__);
1100 return 0;
1101
1102/* Deinit MFC if probe had failed */
1103err_enc_reg:
1104 video_device_release(dev->vfd_enc);
1105err_enc_alloc:
1106 video_unregister_device(dev->vfd_dec);
1107err_dec_reg:
1108 video_device_release(dev->vfd_dec);
1109err_dec_alloc:
1110 v4l2_device_unregister(&dev->v4l2_dev);
1111err_v4l2_dev_reg:
1112 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
1113err_mem_init_ctx_1:
1114 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
1115err_mem_init_ctx_0:
1116err_find_child:
1117 free_irq(dev->irq, dev);
1118err_req_irq:
1119err_get_res:
1120 iounmap(dev->regs_base);
1121 dev->regs_base = NULL;
1122err_ioremap:
1123 release_resource(dev->mfc_mem);
1124 kfree(dev->mfc_mem);
1125err_mem_reg:
1126err_res:
1127 s5p_mfc_final_pm(dev);
1128err_clk:
1129err_dev:
1130 kfree(dev);
1131 pr_debug("%s-- with error\n", __func__);
1132 return ret;
1133
1134}
1135
1136/* Remove the driver */
1137static int __devexit s5p_mfc_remove(struct platform_device *pdev)
1138{
1139 struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
1140
1141 v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
1142
1143 del_timer_sync(&dev->watchdog_timer);
1144 flush_workqueue(dev->watchdog_workqueue);
1145 destroy_workqueue(dev->watchdog_workqueue);
1146
1147 video_unregister_device(dev->vfd_enc);
1148 video_unregister_device(dev->vfd_dec);
1149 v4l2_device_unregister(&dev->v4l2_dev);
1150 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
1151 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
1152
1153 free_irq(dev->irq, dev);
1154 iounmap(dev->regs_base);
1155 if (dev->mfc_mem) {
1156 release_resource(dev->mfc_mem);
1157 kfree(dev->mfc_mem);
1158 dev->mfc_mem = NULL;
1159 }
1160 s5p_mfc_final_pm(dev);
1161 kfree(dev);
1162 return 0;
1163}
1164
1165#ifdef CONFIG_PM_SLEEP
1166
1167static int s5p_mfc_suspend(struct device *dev)
1168{
1169 struct platform_device *pdev = to_platform_device(dev);
1170 struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
1171 int ret;
1172
1173 if (m_dev->num_inst == 0)
1174 return 0;
1175 return s5p_mfc_sleep(m_dev);
1176 if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) {
1177 mfc_err("Error: going to suspend for a second time\n");
1178 return -EIO;
1179 }
1180
1181 /* Check if we're processing then wait if it necessary. */
1182 while (test_and_set_bit(0, &m_dev->hw_lock) != 0) {
1183 /* Try and lock the HW */
1184 /* Wait on the interrupt waitqueue */
1185 ret = wait_event_interruptible_timeout(m_dev->queue,
1186 m_dev->int_cond || m_dev->ctx[m_dev->curr_ctx]->int_cond,
1187 msecs_to_jiffies(MFC_INT_TIMEOUT));
1188
1189 if (ret == 0) {
1190 mfc_err("Waiting for hardware to finish timed out\n");
1191 return -EIO;
1192 }
1193 }
1194 return 0;
1195}
1196
1197static int s5p_mfc_resume(struct device *dev)
1198{
1199 struct platform_device *pdev = to_platform_device(dev);
1200 struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
1201
1202 if (m_dev->num_inst == 0)
1203 return 0;
1204 return s5p_mfc_wakeup(m_dev);
1205}
1206#endif
1207
1208#ifdef CONFIG_PM_RUNTIME
1209static int s5p_mfc_runtime_suspend(struct device *dev)
1210{
1211 struct platform_device *pdev = to_platform_device(dev);
1212 struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
1213
1214 atomic_set(&m_dev->pm.power, 0);
1215 return 0;
1216}
1217
1218static int s5p_mfc_runtime_resume(struct device *dev)
1219{
1220 struct platform_device *pdev = to_platform_device(dev);
1221 struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
1222 int pre_power;
1223
1224 if (!m_dev->alloc_ctx)
1225 return 0;
1226 pre_power = atomic_read(&m_dev->pm.power);
1227 atomic_set(&m_dev->pm.power, 1);
1228 return 0;
1229}
1230#endif
1231
1232/* Power management */
1233static const struct dev_pm_ops s5p_mfc_pm_ops = {
1234 SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
1235 SET_RUNTIME_PM_OPS(s5p_mfc_runtime_suspend, s5p_mfc_runtime_resume,
1236 NULL)
1237};
1238
1239static struct platform_driver s5p_mfc_pdrv = {
1240 .probe = s5p_mfc_probe,
1241 .remove = __devexit_p(s5p_mfc_remove),
1242 .driver = {
1243 .name = S5P_MFC_NAME,
1244 .owner = THIS_MODULE,
1245 .pm = &s5p_mfc_pm_ops
1246 },
1247};
1248
1249static char banner[] __initdata =
1250 "S5P MFC V4L2 Driver, (C) 2011 Samsung Electronics\n";
1251
1252static int __init s5p_mfc_init(void)
1253{
1254 int ret;
1255
1256 pr_info("%s", banner);
1257 ret = platform_driver_register(&s5p_mfc_pdrv);
1258 if (ret)
1259 pr_err("Platform device registration failed.\n");
1260 return ret;
1261}
1262
1263static void __devexit s5p_mfc_exit(void)
1264{
1265 platform_driver_unregister(&s5p_mfc_pdrv);
1266}
1267
1268module_init(s5p_mfc_init);
1269module_exit(s5p_mfc_exit);
1270
1271MODULE_LICENSE("GPL");
1272MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
1273MODULE_DESCRIPTION("Samsung S5P Multi Format Codec V4L2 driver");
1274
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
new file mode 100644
index 000000000000..f0665ed1a529
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
@@ -0,0 +1,120 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include "regs-mfc.h"
14#include "s5p_mfc_cmd.h"
15#include "s5p_mfc_common.h"
16#include "s5p_mfc_debug.h"
17
18/* This function is used to send a command to the MFC */
19static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
20 struct s5p_mfc_cmd_args *args)
21{
22 int cur_cmd;
23 unsigned long timeout;
24
25 timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
26 /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
27 do {
28 if (time_after(jiffies, timeout)) {
29 mfc_err("Timeout while waiting for hardware\n");
30 return -EIO;
31 }
32 cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
33 } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
34 mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
35 mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
36 mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
37 mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
38 /* Issue the command */
39 mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
40 return 0;
41}
42
43/* Initialize the MFC */
44int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
45{
46 struct s5p_mfc_cmd_args h2r_args;
47
48 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
49 h2r_args.arg[0] = dev->fw_size;
50 return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
51}
52
53/* Suspend the MFC hardware */
54int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
55{
56 struct s5p_mfc_cmd_args h2r_args;
57
58 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
59 return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
60}
61
62/* Wake up the MFC hardware */
63int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
64{
65 struct s5p_mfc_cmd_args h2r_args;
66
67 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
68 return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
69}
70
71
72int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
73{
74 struct s5p_mfc_dev *dev = ctx->dev;
75 struct s5p_mfc_cmd_args h2r_args;
76 int ret;
77
78 /* Preparing decoding - getting instance number */
79 mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
80 dev->curr_ctx = ctx->num;
81 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
82 h2r_args.arg[0] = ctx->codec_mode;
83 h2r_args.arg[1] = 0; /* no crc & no pixelcache */
84 h2r_args.arg[2] = ctx->ctx_ofs;
85 h2r_args.arg[3] = ctx->ctx_size;
86 ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
87 &h2r_args);
88 if (ret) {
89 mfc_err("Failed to create a new instance\n");
90 ctx->state = MFCINST_ERROR;
91 }
92 return ret;
93}
94
95int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
96{
97 struct s5p_mfc_dev *dev = ctx->dev;
98 struct s5p_mfc_cmd_args h2r_args;
99 int ret;
100
101 if (ctx->state == MFCINST_FREE) {
102 mfc_err("Instance already returned\n");
103 ctx->state = MFCINST_ERROR;
104 return -EINVAL;
105 }
106 /* Closing decoding instance */
107 mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
108 dev->curr_ctx = ctx->num;
109 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
110 h2r_args.arg[0] = ctx->inst_no;
111 ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
112 &h2r_args);
113 if (ret) {
114 mfc_err("Failed to return an instance\n");
115 ctx->state = MFCINST_ERROR;
116 return -EINVAL;
117 }
118 return 0;
119}
120
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
new file mode 100644
index 000000000000..5ceebfe6131a
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
@@ -0,0 +1,30 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_CMD_H_
14#define S5P_MFC_CMD_H_
15
16#include "s5p_mfc_common.h"
17
18#define MAX_H2R_ARG 4
19
20struct s5p_mfc_cmd_args {
21 unsigned int arg[MAX_H2R_ARG];
22};
23
24int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
25int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
26int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
27int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
28int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
29
30#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
new file mode 100644
index 000000000000..91146fa622e4
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
@@ -0,0 +1,572 @@
1/*
2 * Samsung S5P Multi Format Codec v 5.0
3 *
4 * This file contains definitions of enums and structs used by the codec
5 * driver.
6 *
7 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
8 * Kamil Debski, <k.debski@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 as published by the
12 * Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version
14 */
15
16#ifndef S5P_MFC_COMMON_H_
17#define S5P_MFC_COMMON_H_
18
19#include "regs-mfc.h"
20#include <linux/platform_device.h>
21#include <linux/videodev2.h>
22#include <media/v4l2-ctrls.h>
23#include <media/v4l2-device.h>
24#include <media/v4l2-ioctl.h>
25#include <media/videobuf2-core.h>
26
27/* Definitions related to MFC memory */
28
29/* Offset base used to differentiate between CAPTURE and OUTPUT
30* while mmaping */
31#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2)
32
33/* Offset used by the hardware to store addresses */
34#define MFC_OFFSET_SHIFT 11
35
36#define FIRMWARE_ALIGN 0x20000 /* 128KB */
37#define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264 instance */
38#define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */
39#define DESC_BUF_SIZE 0x20000 /* 128KB for DESC buffer */
40#define SHARED_BUF_SIZE 0x2000 /* 8KB for shared buffer */
41
42#define DEF_CPB_SIZE 0x40000 /* 512KB */
43
44#define MFC_BANK1_ALLOC_CTX 0
45#define MFC_BANK2_ALLOC_CTX 1
46
47#define MFC_BANK1_ALIGN_ORDER 13
48#define MFC_BANK2_ALIGN_ORDER 13
49#define MFC_BASE_ALIGN_ORDER 17
50
51#include <media/videobuf2-dma-contig.h>
52
53static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
54{
55 /* Same functionality as the vb2_dma_contig_plane_paddr */
56 dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b);
57
58 return *paddr;
59}
60
61/* MFC definitions */
62#define MFC_MAX_EXTRA_DPB 5
63#define MFC_MAX_BUFFERS 32
64#define MFC_NUM_CONTEXTS 4
65/* Interrupt timeout */
66#define MFC_INT_TIMEOUT 2000
67/* Busy wait timeout */
68#define MFC_BW_TIMEOUT 500
69/* Watchdog interval */
70#define MFC_WATCHDOG_INTERVAL 1000
71/* After how many executions watchdog should assume lock up */
72#define MFC_WATCHDOG_CNT 10
73#define MFC_NO_INSTANCE_SET -1
74#define MFC_ENC_CAP_PLANE_COUNT 1
75#define MFC_ENC_OUT_PLANE_COUNT 2
76#define STUFF_BYTE 4
77#define MFC_MAX_CTRLS 64
78
79#define mfc_read(dev, offset) readl(dev->regs_base + (offset))
80#define mfc_write(dev, data, offset) writel((data), dev->regs_base + \
81 (offset))
82
83/**
84 * enum s5p_mfc_fmt_type - type of the pixelformat
85 */
86enum s5p_mfc_fmt_type {
87 MFC_FMT_DEC,
88 MFC_FMT_ENC,
89 MFC_FMT_RAW,
90};
91
92/**
93 * enum s5p_mfc_node_type - The type of an MFC device node.
94 */
95enum s5p_mfc_node_type {
96 MFCNODE_INVALID = -1,
97 MFCNODE_DECODER = 0,
98 MFCNODE_ENCODER = 1,
99};
100
101/**
102 * enum s5p_mfc_inst_type - The type of an MFC instance.
103 */
104enum s5p_mfc_inst_type {
105 MFCINST_INVALID,
106 MFCINST_DECODER,
107 MFCINST_ENCODER,
108};
109
110/**
111 * enum s5p_mfc_inst_state - The state of an MFC instance.
112 */
113enum s5p_mfc_inst_state {
114 MFCINST_FREE = 0,
115 MFCINST_INIT = 100,
116 MFCINST_GOT_INST,
117 MFCINST_HEAD_PARSED,
118 MFCINST_BUFS_SET,
119 MFCINST_RUNNING,
120 MFCINST_FINISHING,
121 MFCINST_FINISHED,
122 MFCINST_RETURN_INST,
123 MFCINST_ERROR,
124 MFCINST_ABORT,
125 MFCINST_RES_CHANGE_INIT,
126 MFCINST_RES_CHANGE_FLUSH,
127 MFCINST_RES_CHANGE_END,
128};
129
130/**
131 * enum s5p_mfc_queue_state - The state of buffer queue.
132 */
133enum s5p_mfc_queue_state {
134 QUEUE_FREE,
135 QUEUE_BUFS_REQUESTED,
136 QUEUE_BUFS_QUERIED,
137 QUEUE_BUFS_MMAPED,
138};
139
140/**
141 * enum s5p_mfc_decode_arg - type of frame decoding
142 */
143enum s5p_mfc_decode_arg {
144 MFC_DEC_FRAME,
145 MFC_DEC_LAST_FRAME,
146 MFC_DEC_RES_CHANGE,
147};
148
149struct s5p_mfc_ctx;
150
151/**
152 * struct s5p_mfc_buf - MFC buffer
153 */
154struct s5p_mfc_buf {
155 struct list_head list;
156 struct vb2_buffer *b;
157 union {
158 struct {
159 size_t luma;
160 size_t chroma;
161 } raw;
162 size_t stream;
163 } cookie;
164 int used;
165};
166
167/**
168 * struct s5p_mfc_pm - power management data structure
169 */
170struct s5p_mfc_pm {
171 struct clk *clock;
172 struct clk *clock_gate;
173 atomic_t power;
174 struct device *device;
175};
176
177/**
178 * struct s5p_mfc_dev - The struct containing driver internal parameters.
179 *
180 * @v4l2_dev: v4l2_device
181 * @vfd_dec: video device for decoding
182 * @vfd_enc: video device for encoding
183 * @plat_dev: platform device
184 * @mem_dev_l: child device of the left memory bank (0)
185 * @mem_dev_r: child device of the right memory bank (1)
186 * @regs_base: base address of the MFC hw registers
187 * @irq: irq resource
188 * @mfc_mem: MFC registers memory resource
189 * @dec_ctrl_handler: control framework handler for decoding
190 * @enc_ctrl_handler: control framework handler for encoding
191 * @pm: power management control
192 * @num_inst: couter of active MFC instances
193 * @irqlock: lock for operations on videobuf2 queues
194 * @condlock: lock for changing/checking if a context is ready to be
195 * processed
196 * @mfc_mutex: lock for video_device
197 * @int_cond: variable used by the waitqueue
198 * @int_type: type of last interrupt
199 * @int_err: error number for last interrupt
200 * @queue: waitqueue for waiting for completion of device commands
201 * @fw_size: size of firmware
202 * @bank1: address of the beggining of bank 1 memory
203 * @bank2: address of the beggining of bank 2 memory
204 * @hw_lock: used for hardware locking
205 * @ctx: array of driver contexts
206 * @curr_ctx: number of the currently running context
207 * @ctx_work_bits: used to mark which contexts are waiting for hardware
208 * @watchdog_cnt: counter for the watchdog
209 * @watchdog_workqueue: workqueue for the watchdog
210 * @watchdog_work: worker for the watchdog
211 * @alloc_ctx: videobuf2 allocator contexts for two memory banks
212 * @enter_suspend: flag set when entering suspend
213 *
214 */
215struct s5p_mfc_dev {
216 struct v4l2_device v4l2_dev;
217 struct video_device *vfd_dec;
218 struct video_device *vfd_enc;
219 struct platform_device *plat_dev;
220 struct device *mem_dev_l;
221 struct device *mem_dev_r;
222 void __iomem *regs_base;
223 int irq;
224 struct resource *mfc_mem;
225 struct v4l2_ctrl_handler dec_ctrl_handler;
226 struct v4l2_ctrl_handler enc_ctrl_handler;
227 struct s5p_mfc_pm pm;
228 int num_inst;
229 spinlock_t irqlock; /* lock when operating on videobuf2 queues */
230 spinlock_t condlock; /* lock when changing/checking if a context is
231 ready to be processed */
232 struct mutex mfc_mutex; /* video_device lock */
233 int int_cond;
234 int int_type;
235 unsigned int int_err;
236 wait_queue_head_t queue;
237 size_t fw_size;
238 size_t bank1;
239 size_t bank2;
240 unsigned long hw_lock;
241 struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
242 int curr_ctx;
243 unsigned long ctx_work_bits;
244 atomic_t watchdog_cnt;
245 struct timer_list watchdog_timer;
246 struct workqueue_struct *watchdog_workqueue;
247 struct work_struct watchdog_work;
248 void *alloc_ctx[2];
249 unsigned long enter_suspend;
250};
251
252/**
253 * struct s5p_mfc_h264_enc_params - encoding parameters for h264
254 */
255struct s5p_mfc_h264_enc_params {
256 enum v4l2_mpeg_video_h264_profile profile;
257 enum v4l2_mpeg_video_h264_loop_filter_mode loop_filter_mode;
258 s8 loop_filter_alpha;
259 s8 loop_filter_beta;
260 enum v4l2_mpeg_video_h264_entropy_mode entropy_mode;
261 u8 max_ref_pic;
262 u8 num_ref_pic_4p;
263 int _8x8_transform;
264 int rc_mb;
265 int rc_mb_dark;
266 int rc_mb_smooth;
267 int rc_mb_static;
268 int rc_mb_activity;
269 int vui_sar;
270 u8 vui_sar_idc;
271 u16 vui_ext_sar_width;
272 u16 vui_ext_sar_height;
273 int open_gop;
274 u16 open_gop_size;
275 u8 rc_frame_qp;
276 u8 rc_min_qp;
277 u8 rc_max_qp;
278 u8 rc_p_frame_qp;
279 u8 rc_b_frame_qp;
280 enum v4l2_mpeg_video_h264_level level_v4l2;
281 int level;
282 u16 cpb_size;
283};
284
285/**
286 * struct s5p_mfc_mpeg4_enc_params - encoding parameters for h263 and mpeg4
287 */
288struct s5p_mfc_mpeg4_enc_params {
289 /* MPEG4 Only */
290 enum v4l2_mpeg_video_mpeg4_profile profile;
291 int quarter_pixel;
292 /* Common for MPEG4, H263 */
293 u16 vop_time_res;
294 u16 vop_frm_delta;
295 u8 rc_frame_qp;
296 u8 rc_min_qp;
297 u8 rc_max_qp;
298 u8 rc_p_frame_qp;
299 u8 rc_b_frame_qp;
300 enum v4l2_mpeg_video_mpeg4_level level_v4l2;
301 int level;
302};
303
304/**
305 * struct s5p_mfc_enc_params - general encoding parameters
306 */
307struct s5p_mfc_enc_params {
308 u16 width;
309 u16 height;
310
311 u16 gop_size;
312 enum v4l2_mpeg_video_multi_slice_mode slice_mode;
313 u16 slice_mb;
314 u32 slice_bit;
315 u16 intra_refresh_mb;
316 int pad;
317 u8 pad_luma;
318 u8 pad_cb;
319 u8 pad_cr;
320 int rc_frame;
321 u32 rc_bitrate;
322 u16 rc_reaction_coeff;
323 u16 vbv_size;
324
325 enum v4l2_mpeg_video_header_mode seq_hdr_mode;
326 enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
327 int fixed_target_bit;
328
329 u8 num_b_frame;
330 u32 rc_framerate_num;
331 u32 rc_framerate_denom;
332 int interlace;
333
334 union {
335 struct s5p_mfc_h264_enc_params h264;
336 struct s5p_mfc_mpeg4_enc_params mpeg4;
337 } codec;
338
339};
340
341/**
342 * struct s5p_mfc_codec_ops - codec ops, used by encoding
343 */
344struct s5p_mfc_codec_ops {
345 /* initialization routines */
346 int (*pre_seq_start) (struct s5p_mfc_ctx *ctx);
347 int (*post_seq_start) (struct s5p_mfc_ctx *ctx);
348 /* execution routines */
349 int (*pre_frame_start) (struct s5p_mfc_ctx *ctx);
350 int (*post_frame_start) (struct s5p_mfc_ctx *ctx);
351};
352
353#define call_cop(c, op, args...) \
354 (((c)->c_ops->op) ? \
355 ((c)->c_ops->op(args)) : 0)
356
357/**
358 * struct s5p_mfc_ctx - This struct contains the instance context
359 *
360 * @dev: pointer to the s5p_mfc_dev of the device
361 * @fh: struct v4l2_fh
362 * @num: number of the context that this structure describes
363 * @int_cond: variable used by the waitqueue
364 * @int_type: type of the last interrupt
365 * @int_err: error number received from MFC hw in the interrupt
366 * @queue: waitqueue that can be used to wait for this context to
367 * finish
368 * @src_fmt: source pixelformat information
369 * @dst_fmt: destination pixelformat information
370 * @vq_src: vb2 queue for source buffers
371 * @vq_dst: vb2 queue for destination buffers
372 * @src_queue: driver internal queue for source buffers
373 * @dst_queue: driver internal queue for destination buffers
374 * @src_queue_cnt: number of buffers queued on the source internal queue
375 * @dst_queue_cnt: number of buffers queued on the dest internal queue
376 * @type: type of the instance - decoder or encoder
377 * @state: state of the context
378 * @inst_no: number of hw instance associated with the context
379 * @img_width: width of the image that is decoded or encoded
380 * @img_height: height of the image that is decoded or encoded
381 * @buf_width: width of the buffer for processed image
382 * @buf_height: height of the buffer for processed image
383 * @luma_size: size of a luma plane
384 * @chroma_size: size of a chroma plane
385 * @mv_size: size of a motion vectors buffer
386 * @consumed_stream: number of bytes that have been used so far from the
387 * decoding buffer
388 * @dpb_flush_flag: flag used to indicate that a DPB buffers are being
389 * flushed
390 * @bank1_buf: handle to memory allocated for temporary buffers from
391 * memory bank 1
392 * @bank1_phys: address of the temporary buffers from memory bank 1
393 * @bank1_size: size of the memory allocated for temporary buffers from
394 * memory bank 1
395 * @bank2_buf: handle to memory allocated for temporary buffers from
396 * memory bank 2
397 * @bank2_phys: address of the temporary buffers from memory bank 2
398 * @bank2_size: size of the memory allocated for temporary buffers from
399 * memory bank 2
400 * @capture_state: state of the capture buffers queue
401 * @output_state: state of the output buffers queue
402 * @src_bufs: information on allocated source buffers
403 * @dst_bufs: information on allocated destination buffers
404 * @sequence: counter for the sequence number for v4l2
405 * @dec_dst_flag: flags for buffers queued in the hardware
406 * @dec_src_buf_size: size of the buffer for source buffers in decoding
407 * @codec_mode: number of codec mode used by MFC hw
408 * @slice_interface: slice interface flag
409 * @loop_filter_mpeg4: loop filter for MPEG4 flag
410 * @display_delay: value of the display delay for H264
411 * @display_delay_enable: display delay for H264 enable flag
412 * @after_packed_pb: flag used to track buffer when stream is in
413 * Packed PB format
414 * @dpb_count: count of the DPB buffers required by MFC hw
415 * @total_dpb_count: count of DPB buffers with additional buffers
416 * requested by the application
417 * @ctx_buf: handle to the memory associated with this context
418 * @ctx_phys: address of the memory associated with this context
419 * @ctx_size: size of the memory associated with this context
420 * @desc_buf: description buffer for decoding handle
421 * @desc_phys: description buffer for decoding address
422 * @shm_alloc: handle for the shared memory buffer
423 * @shm: virtual address for the shared memory buffer
424 * @shm_ofs: address offset for shared memory
425 * @enc_params: encoding parameters for MFC
426 * @enc_dst_buf_size: size of the buffers for encoder output
427 * @frame_type: used to force the type of the next encoded frame
428 * @ref_queue: list of the reference buffers for encoding
429 * @ref_queue_cnt: number of the buffers in the reference list
430 * @c_ops: ops for encoding
431 * @ctrls: array of controls, used when adding controls to the
432 * v4l2 control framework
433 * @ctrl_handler: handler for v4l2 framework
434 */
435struct s5p_mfc_ctx {
436 struct s5p_mfc_dev *dev;
437 struct v4l2_fh fh;
438
439 int num;
440
441 int int_cond;
442 int int_type;
443 unsigned int int_err;
444 wait_queue_head_t queue;
445
446 struct s5p_mfc_fmt *src_fmt;
447 struct s5p_mfc_fmt *dst_fmt;
448
449 struct vb2_queue vq_src;
450 struct vb2_queue vq_dst;
451
452 struct list_head src_queue;
453 struct list_head dst_queue;
454
455 unsigned int src_queue_cnt;
456 unsigned int dst_queue_cnt;
457
458 enum s5p_mfc_inst_type type;
459 enum s5p_mfc_inst_state state;
460 int inst_no;
461
462 /* Image parameters */
463 int img_width;
464 int img_height;
465 int buf_width;
466 int buf_height;
467
468 int luma_size;
469 int chroma_size;
470 int mv_size;
471
472 unsigned long consumed_stream;
473
474 unsigned int dpb_flush_flag;
475
476 /* Buffers */
477 void *bank1_buf;
478 size_t bank1_phys;
479 size_t bank1_size;
480
481 void *bank2_buf;
482 size_t bank2_phys;
483 size_t bank2_size;
484
485 enum s5p_mfc_queue_state capture_state;
486 enum s5p_mfc_queue_state output_state;
487
488 struct s5p_mfc_buf src_bufs[MFC_MAX_BUFFERS];
489 int src_bufs_cnt;
490 struct s5p_mfc_buf dst_bufs[MFC_MAX_BUFFERS];
491 int dst_bufs_cnt;
492
493 unsigned int sequence;
494 unsigned long dec_dst_flag;
495 size_t dec_src_buf_size;
496
497 /* Control values */
498 int codec_mode;
499 int slice_interface;
500 int loop_filter_mpeg4;
501 int display_delay;
502 int display_delay_enable;
503 int after_packed_pb;
504
505 int dpb_count;
506 int total_dpb_count;
507
508 /* Buffers */
509 void *ctx_buf;
510 size_t ctx_phys;
511 size_t ctx_ofs;
512 size_t ctx_size;
513
514 void *desc_buf;
515 size_t desc_phys;
516
517
518 void *shm_alloc;
519 void *shm;
520 size_t shm_ofs;
521
522 struct s5p_mfc_enc_params enc_params;
523
524 size_t enc_dst_buf_size;
525
526 enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
527
528 struct list_head ref_queue;
529 unsigned int ref_queue_cnt;
530
531 struct s5p_mfc_codec_ops *c_ops;
532
533 struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
534 struct v4l2_ctrl_handler ctrl_handler;
535};
536
537/*
538 * struct s5p_mfc_fmt - structure used to store information about pixelformats
539 * used by the MFC
540 */
541struct s5p_mfc_fmt {
542 char *name;
543 u32 fourcc;
544 u32 codec_mode;
545 enum s5p_mfc_fmt_type type;
546 u32 num_planes;
547};
548
549/**
550 * struct mfc_control - structure used to store information about MFC controls
551 * it is used to initialize the control framework.
552 */
553struct mfc_control {
554 __u32 id;
555 enum v4l2_ctrl_type type;
556 __u8 name[32]; /* Whatever */
557 __s32 minimum; /* Note signedness */
558 __s32 maximum;
559 __s32 step;
560 __u32 menu_skip_mask;
561 __s32 default_value;
562 __u32 flags;
563 __u32 reserved[2];
564 __u8 is_volatile;
565};
566
567
568#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
569#define ctrl_to_ctx(__ctrl) \
570 container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
571
572#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
new file mode 100644
index 000000000000..5f4da80051bb
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
@@ -0,0 +1,343 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/firmware.h>
16#include <linux/jiffies.h>
17#include <linux/sched.h>
18#include "regs-mfc.h"
19#include "s5p_mfc_cmd.h"
20#include "s5p_mfc_common.h"
21#include "s5p_mfc_debug.h"
22#include "s5p_mfc_intr.h"
23#include "s5p_mfc_pm.h"
24
25static void *s5p_mfc_bitproc_buf;
26static size_t s5p_mfc_bitproc_phys;
27static unsigned char *s5p_mfc_bitproc_virt;
28
29/* Allocate and load firmware */
30int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
31{
32 struct firmware *fw_blob;
33 size_t bank2_base_phys;
34 void *b_base;
35 int err;
36
37 /* Firmare has to be present as a separate file or compiled
38 * into kernel. */
39 mfc_debug_enter();
40 err = request_firmware((const struct firmware **)&fw_blob,
41 "s5pc110-mfc.fw", dev->v4l2_dev.dev);
42 if (err != 0) {
43 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
44 return -EINVAL;
45 }
46 dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
47 if (s5p_mfc_bitproc_buf) {
48 mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
49 release_firmware(fw_blob);
50 return -ENOMEM;
51 }
52 s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
53 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
54 if (IS_ERR(s5p_mfc_bitproc_buf)) {
55 s5p_mfc_bitproc_buf = 0;
56 mfc_err("Allocating bitprocessor buffer failed\n");
57 release_firmware(fw_blob);
58 return -ENOMEM;
59 }
60 s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
61 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
62 if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
63 mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
64 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
65 s5p_mfc_bitproc_phys = 0;
66 s5p_mfc_bitproc_buf = 0;
67 release_firmware(fw_blob);
68 return -EIO;
69 }
70 s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
71 if (!s5p_mfc_bitproc_virt) {
72 mfc_err("Bitprocessor memory remap failed\n");
73 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
74 s5p_mfc_bitproc_phys = 0;
75 s5p_mfc_bitproc_buf = 0;
76 release_firmware(fw_blob);
77 return -EIO;
78 }
79 dev->bank1 = s5p_mfc_bitproc_phys;
80 b_base = vb2_dma_contig_memops.alloc(
81 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
82 if (IS_ERR(b_base)) {
83 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
84 s5p_mfc_bitproc_phys = 0;
85 s5p_mfc_bitproc_buf = 0;
86 mfc_err("Allocating bank2 base failed\n");
87 release_firmware(fw_blob);
88 return -ENOMEM;
89 }
90 bank2_base_phys = s5p_mfc_mem_cookie(
91 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
92 vb2_dma_contig_memops.put(b_base);
93 if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
94 mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
95 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
96 s5p_mfc_bitproc_phys = 0;
97 s5p_mfc_bitproc_buf = 0;
98 release_firmware(fw_blob);
99 return -EIO;
100 }
101 dev->bank2 = bank2_base_phys;
102 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
103 wmb();
104 release_firmware(fw_blob);
105 mfc_debug_leave();
106 return 0;
107}
108
109/* Reload firmware to MFC */
110int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
111{
112 struct firmware *fw_blob;
113 int err;
114
115 /* Firmare has to be present as a separate file or compiled
116 * into kernel. */
117 mfc_debug_enter();
118 err = request_firmware((const struct firmware **)&fw_blob,
119 "s5pc110-mfc.fw", dev->v4l2_dev.dev);
120 if (err != 0) {
121 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
122 return -EINVAL;
123 }
124 if (fw_blob->size > dev->fw_size) {
125 mfc_err("MFC firmware is too big to be loaded\n");
126 release_firmware(fw_blob);
127 return -ENOMEM;
128 }
129 if (s5p_mfc_bitproc_buf == 0 || s5p_mfc_bitproc_phys == 0) {
130 mfc_err("MFC firmware is not allocated or was not mapped correctly\n");
131 release_firmware(fw_blob);
132 return -EINVAL;
133 }
134 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
135 wmb();
136 release_firmware(fw_blob);
137 mfc_debug_leave();
138 return 0;
139}
140
141/* Release firmware memory */
142int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
143{
144 /* Before calling this function one has to make sure
145 * that MFC is no longer processing */
146 if (!s5p_mfc_bitproc_buf)
147 return -EINVAL;
148 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
149 s5p_mfc_bitproc_virt = 0;
150 s5p_mfc_bitproc_phys = 0;
151 s5p_mfc_bitproc_buf = 0;
152 return 0;
153}
154
155/* Reset the device */
156int s5p_mfc_reset(struct s5p_mfc_dev *dev)
157{
158 unsigned int mc_status;
159 unsigned long timeout;
160
161 mfc_debug_enter();
162 /* Stop procedure */
163 /* reset RISC */
164 mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
165 /* All reset except for MC */
166 mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
167 mdelay(10);
168
169 timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
170 /* Check MC status */
171 do {
172 if (time_after(jiffies, timeout)) {
173 mfc_err("Timeout while resetting MFC\n");
174 return -EIO;
175 }
176
177 mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
178
179 } while (mc_status & 0x3);
180
181 mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
182 mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
183 mfc_debug_leave();
184 return 0;
185}
186
187static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
188{
189 mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
190 mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
191 mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
192}
193
194static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
195{
196 mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
197 mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
198 mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
199 mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
200}
201
202/* Initialize hardware */
203int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
204{
205 unsigned int ver;
206 int ret;
207
208 mfc_debug_enter();
209 if (!s5p_mfc_bitproc_buf)
210 return -EINVAL;
211
212 /* 0. MFC reset */
213 mfc_debug(2, "MFC reset..\n");
214 s5p_mfc_clock_on();
215 ret = s5p_mfc_reset(dev);
216 if (ret) {
217 mfc_err("Failed to reset MFC - timeout\n");
218 return ret;
219 }
220 mfc_debug(2, "Done MFC reset..\n");
221 /* 1. Set DRAM base Addr */
222 s5p_mfc_init_memctrl(dev);
223 /* 2. Initialize registers of channel I/F */
224 s5p_mfc_clear_cmds(dev);
225 /* 3. Release reset signal to the RISC */
226 s5p_mfc_clean_dev_int_flags(dev);
227 mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
228 mfc_debug(2, "Will now wait for completion of firmware transfer\n");
229 if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
230 mfc_err("Failed to load firmware\n");
231 s5p_mfc_reset(dev);
232 s5p_mfc_clock_off();
233 return -EIO;
234 }
235 s5p_mfc_clean_dev_int_flags(dev);
236 /* 4. Initialize firmware */
237 ret = s5p_mfc_sys_init_cmd(dev);
238 if (ret) {
239 mfc_err("Failed to send command to MFC - timeout\n");
240 s5p_mfc_reset(dev);
241 s5p_mfc_clock_off();
242 return ret;
243 }
244 mfc_debug(2, "Ok, now will write a command to init the system\n");
245 if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
246 mfc_err("Failed to load firmware\n");
247 s5p_mfc_reset(dev);
248 s5p_mfc_clock_off();
249 return -EIO;
250 }
251 dev->int_cond = 0;
252 if (dev->int_err != 0 || dev->int_type !=
253 S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
254 /* Failure. */
255 mfc_err("Failed to init firmware - error: %d int: %d\n",
256 dev->int_err, dev->int_type);
257 s5p_mfc_reset(dev);
258 s5p_mfc_clock_off();
259 return -EIO;
260 }
261 ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
262 mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
263 (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
264 s5p_mfc_clock_off();
265 mfc_debug_leave();
266 return 0;
267}
268
269
270int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
271{
272 int ret;
273
274 mfc_debug_enter();
275 s5p_mfc_clock_on();
276 s5p_mfc_clean_dev_int_flags(dev);
277 ret = s5p_mfc_sleep_cmd(dev);
278 if (ret) {
279 mfc_err("Failed to send command to MFC - timeout\n");
280 return ret;
281 }
282 if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
283 mfc_err("Failed to sleep\n");
284 return -EIO;
285 }
286 s5p_mfc_clock_off();
287 dev->int_cond = 0;
288 if (dev->int_err != 0 || dev->int_type !=
289 S5P_FIMV_R2H_CMD_SLEEP_RET) {
290 /* Failure. */
291 mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
292 dev->int_type);
293 return -EIO;
294 }
295 mfc_debug_leave();
296 return ret;
297}
298
299int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
300{
301 int ret;
302
303 mfc_debug_enter();
304 /* 0. MFC reset */
305 mfc_debug(2, "MFC reset..\n");
306 s5p_mfc_clock_on();
307 ret = s5p_mfc_reset(dev);
308 if (ret) {
309 mfc_err("Failed to reset MFC - timeout\n");
310 return ret;
311 }
312 mfc_debug(2, "Done MFC reset..\n");
313 /* 1. Set DRAM base Addr */
314 s5p_mfc_init_memctrl(dev);
315 /* 2. Initialize registers of channel I/F */
316 s5p_mfc_clear_cmds(dev);
317 s5p_mfc_clean_dev_int_flags(dev);
318 /* 3. Initialize firmware */
319 ret = s5p_mfc_wakeup_cmd(dev);
320 if (ret) {
321 mfc_err("Failed to send command to MFC - timeout\n");
322 return ret;
323 }
324 /* 4. Release reset signal to the RISC */
325 mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
326 mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
327 if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
328 mfc_err("Failed to load firmware\n");
329 return -EIO;
330 }
331 s5p_mfc_clock_off();
332 dev->int_cond = 0;
333 if (dev->int_err != 0 || dev->int_type !=
334 S5P_FIMV_R2H_CMD_WAKEUP_RET) {
335 /* Failure. */
336 mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
337 dev->int_type);
338 return -EIO;
339 }
340 mfc_debug_leave();
341 return 0;
342}
343
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
new file mode 100644
index 000000000000..61dc23b7ee5a
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
@@ -0,0 +1,29 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_CTRL_H
14#define S5P_MFC_CTRL_H
15
16#include "s5p_mfc_common.h"
17
18int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
19int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
20int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
21
22int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
23
24int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
25int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
26
27int s5p_mfc_reset(struct s5p_mfc_dev *dev);
28
29#endif /* S5P_MFC_CTRL_H */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_debug.h b/drivers/media/video/s5p-mfc/s5p_mfc_debug.h
new file mode 100644
index 000000000000..ecb8616a492a
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_debug.h
@@ -0,0 +1,48 @@
1/*
2 * drivers/media/video/samsung/mfc5/s5p_mfc_debug.h
3 *
4 * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
5 * This file contains debug macros
6 *
7 * Kamil Debski, Copyright (c) 2011 Samsung Electronics
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#ifndef S5P_MFC_DEBUG_H_
16#define S5P_MFC_DEBUG_H_
17
18#define DEBUG
19
20#ifdef DEBUG
21extern int debug;
22
23#define mfc_debug(level, fmt, args...) \
24 do { \
25 if (debug >= level) \
26 printk(KERN_DEBUG "%s:%d: " fmt, \
27 __func__, __LINE__, ##args); \
28 } while (0)
29#else
30#define mfc_debug(level, fmt, args...)
31#endif
32
33#define mfc_debug_enter() mfc_debug(5, "enter")
34#define mfc_debug_leave() mfc_debug(5, "leave")
35
36#define mfc_err(fmt, args...) \
37 do { \
38 printk(KERN_ERR "%s:%d: " fmt, \
39 __func__, __LINE__, ##args); \
40 } while (0)
41
42#define mfc_info(fmt, args...) \
43 do { \
44 printk(KERN_INFO "%s:%d: " fmt, \
45 __func__, __LINE__, ##args); \
46 } while (0)
47
48#endif /* S5P_MFC_DEBUG_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
new file mode 100644
index 000000000000..b2c5052a9c41
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -0,0 +1,1036 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 * Kamil Debski, <k.debski@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/clk.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/version.h>
22#include <linux/videodev2.h>
23#include <linux/workqueue.h>
24#include <media/v4l2-ctrls.h>
25#include <media/videobuf2-core.h>
26#include "regs-mfc.h"
27#include "s5p_mfc_common.h"
28#include "s5p_mfc_debug.h"
29#include "s5p_mfc_dec.h"
30#include "s5p_mfc_intr.h"
31#include "s5p_mfc_opr.h"
32#include "s5p_mfc_pm.h"
33#include "s5p_mfc_shm.h"
34
35static struct s5p_mfc_fmt formats[] = {
36 {
37 .name = "4:2:0 2 Planes 64x32 Tiles",
38 .fourcc = V4L2_PIX_FMT_NV12MT,
39 .codec_mode = S5P_FIMV_CODEC_NONE,
40 .type = MFC_FMT_RAW,
41 .num_planes = 2,
42 },
43 {
44 .name = "4:2:0 2 Planes",
45 .fourcc = V4L2_PIX_FMT_NV12M,
46 .codec_mode = S5P_FIMV_CODEC_NONE,
47 .type = MFC_FMT_RAW,
48 .num_planes = 2,
49 },
50 {
51 .name = "H264 Encoded Stream",
52 .fourcc = V4L2_PIX_FMT_H264,
53 .codec_mode = S5P_FIMV_CODEC_H264_DEC,
54 .type = MFC_FMT_DEC,
55 .num_planes = 1,
56 },
57 {
58 .name = "H263 Encoded Stream",
59 .fourcc = V4L2_PIX_FMT_H263,
60 .codec_mode = S5P_FIMV_CODEC_H263_DEC,
61 .type = MFC_FMT_DEC,
62 .num_planes = 1,
63 },
64 {
65 .name = "MPEG1 Encoded Stream",
66 .fourcc = V4L2_PIX_FMT_MPEG1,
67 .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
68 .type = MFC_FMT_DEC,
69 .num_planes = 1,
70 },
71 {
72 .name = "MPEG2 Encoded Stream",
73 .fourcc = V4L2_PIX_FMT_MPEG2,
74 .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
75 .type = MFC_FMT_DEC,
76 .num_planes = 1,
77 },
78 {
79 .name = "MPEG4 Encoded Stream",
80 .fourcc = V4L2_PIX_FMT_MPEG4,
81 .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
82 .type = MFC_FMT_DEC,
83 .num_planes = 1,
84 },
85 {
86 .name = "XviD Encoded Stream",
87 .fourcc = V4L2_PIX_FMT_XVID,
88 .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
89 .type = MFC_FMT_DEC,
90 .num_planes = 1,
91 },
92 {
93 .name = "VC1 Encoded Stream",
94 .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
95 .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
96 .type = MFC_FMT_DEC,
97 .num_planes = 1,
98 },
99 {
100 .name = "VC1 RCV Encoded Stream",
101 .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
102 .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
103 .type = MFC_FMT_DEC,
104 .num_planes = 1,
105 },
106};
107
108#define NUM_FORMATS ARRAY_SIZE(formats)
109
110/* Find selected format description */
111static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
112{
113 unsigned int i;
114
115 for (i = 0; i < NUM_FORMATS; i++) {
116 if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
117 formats[i].type == t)
118 return &formats[i];
119 }
120 return NULL;
121}
122
123static struct mfc_control controls[] = {
124 {
125 .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "H264 Display Delay",
128 .minimum = 0,
129 .maximum = 16383,
130 .step = 1,
131 .default_value = 0,
132 },
133 {
134 .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,
135 .type = V4L2_CTRL_TYPE_BOOLEAN,
136 .name = "H264 Display Delay Enable",
137 .minimum = 0,
138 .maximum = 1,
139 .step = 1,
140 .default_value = 0,
141 },
142 {
143 .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,
144 .type = V4L2_CTRL_TYPE_BOOLEAN,
145 .name = "Mpeg4 Loop Filter Enable",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149 .default_value = 0,
150 },
151 {
152 .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,
153 .type = V4L2_CTRL_TYPE_BOOLEAN,
154 .name = "Slice Interface Enable",
155 .minimum = 0,
156 .maximum = 1,
157 .step = 1,
158 .default_value = 0,
159 },
160 {
161 .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
162 .type = V4L2_CTRL_TYPE_INTEGER,
163 .name = "Minimum number of cap bufs",
164 .minimum = 1,
165 .maximum = 32,
166 .step = 1,
167 .default_value = 1,
168 .is_volatile = 1,
169 },
170};
171
172#define NUM_CTRLS ARRAY_SIZE(controls)
173
174/* Check whether a context should be run on hardware */
175static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
176{
177 /* Context is to parse header */
178 if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)
179 return 1;
180 /* Context is to decode a frame */
181 if (ctx->src_queue_cnt >= 1 &&
182 ctx->state == MFCINST_RUNNING &&
183 ctx->dst_queue_cnt >= ctx->dpb_count)
184 return 1;
185 /* Context is to return last frame */
186 if (ctx->state == MFCINST_FINISHING &&
187 ctx->dst_queue_cnt >= ctx->dpb_count)
188 return 1;
189 /* Context is to set buffers */
190 if (ctx->src_queue_cnt >= 1 &&
191 ctx->state == MFCINST_HEAD_PARSED &&
192 ctx->capture_state == QUEUE_BUFS_MMAPED)
193 return 1;
194 /* Resolution change */
195 if ((ctx->state == MFCINST_RES_CHANGE_INIT ||
196 ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
197 ctx->dst_queue_cnt >= ctx->dpb_count)
198 return 1;
199 if (ctx->state == MFCINST_RES_CHANGE_END &&
200 ctx->src_queue_cnt >= 1)
201 return 1;
202 mfc_debug(2, "ctx is not ready\n");
203 return 0;
204}
205
206static struct s5p_mfc_codec_ops decoder_codec_ops = {
207 .pre_seq_start = NULL,
208 .post_seq_start = NULL,
209 .pre_frame_start = NULL,
210 .post_frame_start = NULL,
211};
212
213/* Query capabilities of the device */
214static int vidioc_querycap(struct file *file, void *priv,
215 struct v4l2_capability *cap)
216{
217 struct s5p_mfc_dev *dev = video_drvdata(file);
218
219 strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
220 strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
221 cap->bus_info[0] = 0;
222 cap->version = KERNEL_VERSION(1, 0, 0);
223 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
224 | V4L2_CAP_STREAMING;
225 return 0;
226}
227
228/* Enumerate format */
229static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out)
230{
231 struct s5p_mfc_fmt *fmt;
232 int i, j = 0;
233
234 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
235 if (mplane && formats[i].num_planes == 1)
236 continue;
237 else if (!mplane && formats[i].num_planes > 1)
238 continue;
239 if (out && formats[i].type != MFC_FMT_DEC)
240 continue;
241 else if (!out && formats[i].type != MFC_FMT_RAW)
242 continue;
243
244 if (j == f->index)
245 break;
246 ++j;
247 }
248 if (i == ARRAY_SIZE(formats))
249 return -EINVAL;
250 fmt = &formats[i];
251 strlcpy(f->description, fmt->name, sizeof(f->description));
252 f->pixelformat = fmt->fourcc;
253 return 0;
254}
255
256static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
257 struct v4l2_fmtdesc *f)
258{
259 return vidioc_enum_fmt(f, false, false);
260}
261
262static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
263 struct v4l2_fmtdesc *f)
264{
265 return vidioc_enum_fmt(f, true, false);
266}
267
268static int vidioc_enum_fmt_vid_out(struct file *file, void *prov,
269 struct v4l2_fmtdesc *f)
270{
271 return vidioc_enum_fmt(f, false, true);
272}
273
274static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
275 struct v4l2_fmtdesc *f)
276{
277 return vidioc_enum_fmt(f, true, true);
278}
279
280/* Get format */
281static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
282{
283 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
284 struct v4l2_pix_format_mplane *pix_mp;
285
286 mfc_debug_enter();
287 pix_mp = &f->fmt.pix_mp;
288 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
289 (ctx->state == MFCINST_GOT_INST || ctx->state ==
290 MFCINST_RES_CHANGE_END)) {
291 /* If the MFC is parsing the header,
292 * so wait until it is finished */
293 s5p_mfc_clean_ctx_int_flags(ctx);
294 s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
295 0);
296 }
297 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
298 ctx->state >= MFCINST_HEAD_PARSED &&
299 ctx->state < MFCINST_ABORT) {
300 /* This is run on CAPTURE (decode output) */
301 /* Width and height are set to the dimensions
302 of the movie, the buffer is bigger and
303 further processing stages should crop to this
304 rectangle. */
305 pix_mp->width = ctx->buf_width;
306 pix_mp->height = ctx->buf_height;
307 pix_mp->field = V4L2_FIELD_NONE;
308 pix_mp->num_planes = 2;
309 /* Set pixelformat to the format in which MFC
310 outputs the decoded frame */
311 pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT;
312 pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
313 pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
314 pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
315 pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
316 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
317 /* This is run on OUTPUT
318 The buffer contains compressed image
319 so width and height have no meaning */
320 pix_mp->width = 0;
321 pix_mp->height = 0;
322 pix_mp->field = V4L2_FIELD_NONE;
323 pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;
324 pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;
325 pix_mp->pixelformat = ctx->src_fmt->fourcc;
326 pix_mp->num_planes = ctx->src_fmt->num_planes;
327 } else {
328 mfc_err("Format could not be read\n");
329 mfc_debug(2, "%s-- with error\n", __func__);
330 return -EINVAL;
331 }
332 mfc_debug_leave();
333 return 0;
334}
335
336/* Try format */
337static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
338{
339 struct s5p_mfc_fmt *fmt;
340
341 if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
342 mfc_err("This node supports decoding only\n");
343 return -EINVAL;
344 }
345 fmt = find_format(f, MFC_FMT_DEC);
346 if (!fmt) {
347 mfc_err("Unsupported format\n");
348 return -EINVAL;
349 }
350 if (fmt->type != MFC_FMT_DEC) {
351 mfc_err("\n");
352 return -EINVAL;
353 }
354 return 0;
355}
356
357/* Set format */
358static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
359{
360 struct s5p_mfc_dev *dev = video_drvdata(file);
361 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
362 int ret = 0;
363 struct s5p_mfc_fmt *fmt;
364 struct v4l2_pix_format_mplane *pix_mp;
365
366 mfc_debug_enter();
367 ret = vidioc_try_fmt(file, priv, f);
368 pix_mp = &f->fmt.pix_mp;
369 if (ret)
370 return ret;
371 if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
372 v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
373 ret = -EBUSY;
374 goto out;
375 }
376 fmt = find_format(f, MFC_FMT_DEC);
377 if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
378 mfc_err("Unknown codec\n");
379 ret = -EINVAL;
380 goto out;
381 }
382 if (fmt->type != MFC_FMT_DEC) {
383 mfc_err("Wrong format selected, you should choose "
384 "format for decoding\n");
385 ret = -EINVAL;
386 goto out;
387 }
388 ctx->src_fmt = fmt;
389 ctx->codec_mode = fmt->codec_mode;
390 mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
391 pix_mp->height = 0;
392 pix_mp->width = 0;
393 if (pix_mp->plane_fmt[0].sizeimage)
394 ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
395 else
396 pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
397 DEF_CPB_SIZE;
398 pix_mp->plane_fmt[0].bytesperline = 0;
399 ctx->state = MFCINST_INIT;
400out:
401 mfc_debug_leave();
402 return ret;
403}
404
405/* Reqeust buffers */
406static int vidioc_reqbufs(struct file *file, void *priv,
407 struct v4l2_requestbuffers *reqbufs)
408{
409 struct s5p_mfc_dev *dev = video_drvdata(file);
410 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
411 int ret = 0;
412 unsigned long flags;
413
414 if (reqbufs->memory != V4L2_MEMORY_MMAP) {
415 mfc_err("Only V4L2_MEMORY_MAP is supported\n");
416 return -EINVAL;
417 }
418 if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
419 /* Can only request buffers after an instance has been opened.*/
420 if (ctx->state == MFCINST_INIT) {
421 ctx->src_bufs_cnt = 0;
422 if (reqbufs->count == 0) {
423 mfc_debug(2, "Freeing buffers\n");
424 s5p_mfc_clock_on();
425 ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
426 s5p_mfc_clock_off();
427 return ret;
428 }
429 /* Decoding */
430 if (ctx->output_state != QUEUE_FREE) {
431 mfc_err("Bufs have already been requested\n");
432 return -EINVAL;
433 }
434 s5p_mfc_clock_on();
435 ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
436 s5p_mfc_clock_off();
437 if (ret) {
438 mfc_err("vb2_reqbufs on output failed\n");
439 return ret;
440 }
441 mfc_debug(2, "vb2_reqbufs: %d\n", ret);
442 ctx->output_state = QUEUE_BUFS_REQUESTED;
443 }
444 } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
445 ctx->dst_bufs_cnt = 0;
446 if (reqbufs->count == 0) {
447 mfc_debug(2, "Freeing buffers\n");
448 s5p_mfc_clock_on();
449 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
450 s5p_mfc_clock_off();
451 return ret;
452 }
453 if (ctx->capture_state != QUEUE_FREE) {
454 mfc_err("Bufs have already been requested\n");
455 return -EINVAL;
456 }
457 ctx->capture_state = QUEUE_BUFS_REQUESTED;
458 s5p_mfc_clock_on();
459 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
460 s5p_mfc_clock_off();
461 if (ret) {
462 mfc_err("vb2_reqbufs on capture failed\n");
463 return ret;
464 }
465 if (reqbufs->count < ctx->dpb_count) {
466 mfc_err("Not enough buffers allocated\n");
467 reqbufs->count = 0;
468 s5p_mfc_clock_on();
469 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
470 s5p_mfc_clock_off();
471 return -ENOMEM;
472 }
473 ctx->total_dpb_count = reqbufs->count;
474 ret = s5p_mfc_alloc_codec_buffers(ctx);
475 if (ret) {
476 mfc_err("Failed to allocate decoding buffers\n");
477 reqbufs->count = 0;
478 s5p_mfc_clock_on();
479 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
480 s5p_mfc_clock_off();
481 return -ENOMEM;
482 }
483 if (ctx->dst_bufs_cnt == ctx->total_dpb_count) {
484 ctx->capture_state = QUEUE_BUFS_MMAPED;
485 } else {
486 mfc_err("Not all buffers passed to buf_init\n");
487 reqbufs->count = 0;
488 s5p_mfc_clock_on();
489 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
490 s5p_mfc_release_codec_buffers(ctx);
491 s5p_mfc_clock_off();
492 return -ENOMEM;
493 }
494 if (s5p_mfc_ctx_ready(ctx)) {
495 spin_lock_irqsave(&dev->condlock, flags);
496 set_bit(ctx->num, &dev->ctx_work_bits);
497 spin_unlock_irqrestore(&dev->condlock, flags);
498 }
499 s5p_mfc_try_run(dev);
500 s5p_mfc_wait_for_done_ctx(ctx,
501 S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
502 }
503 return ret;
504}
505
506/* Query buffer */
507static int vidioc_querybuf(struct file *file, void *priv,
508 struct v4l2_buffer *buf)
509{
510 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
511 int ret;
512 int i;
513
514 if (buf->memory != V4L2_MEMORY_MMAP) {
515 mfc_err("Only mmaped buffers can be used\n");
516 return -EINVAL;
517 }
518 mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
519 if (ctx->state == MFCINST_INIT &&
520 buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
521 ret = vb2_querybuf(&ctx->vq_src, buf);
522 } else if (ctx->state == MFCINST_RUNNING &&
523 buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
524 ret = vb2_querybuf(&ctx->vq_dst, buf);
525 for (i = 0; i < buf->length; i++)
526 buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
527 } else {
528 mfc_err("vidioc_querybuf called in an inappropriate state\n");
529 ret = -EINVAL;
530 }
531 mfc_debug_leave();
532 return ret;
533}
534
535/* Queue a buffer */
536static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
537{
538 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
539
540 if (ctx->state == MFCINST_ERROR) {
541 mfc_err("Call on QBUF after unrecoverable error\n");
542 return -EIO;
543 }
544 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
545 return vb2_qbuf(&ctx->vq_src, buf);
546 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
547 return vb2_qbuf(&ctx->vq_dst, buf);
548 return -EINVAL;
549}
550
551/* Dequeue a buffer */
552static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
553{
554 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
555
556 if (ctx->state == MFCINST_ERROR) {
557 mfc_err("Call on DQBUF after unrecoverable error\n");
558 return -EIO;
559 }
560 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
561 return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
562 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
563 return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
564 return -EINVAL;
565}
566
567/* Stream on */
568static int vidioc_streamon(struct file *file, void *priv,
569 enum v4l2_buf_type type)
570{
571 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
572 struct s5p_mfc_dev *dev = ctx->dev;
573 unsigned long flags;
574 int ret = -EINVAL;
575
576 mfc_debug_enter();
577 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
578
579 if (ctx->state == MFCINST_INIT) {
580 ctx->dst_bufs_cnt = 0;
581 ctx->src_bufs_cnt = 0;
582 ctx->capture_state = QUEUE_FREE;
583 ctx->output_state = QUEUE_FREE;
584 s5p_mfc_alloc_instance_buffer(ctx);
585 s5p_mfc_alloc_dec_temp_buffers(ctx);
586 spin_lock_irqsave(&dev->condlock, flags);
587 set_bit(ctx->num, &dev->ctx_work_bits);
588 spin_unlock_irqrestore(&dev->condlock, flags);
589 s5p_mfc_clean_ctx_int_flags(ctx);
590 s5p_mfc_try_run(dev);
591
592 if (s5p_mfc_wait_for_done_ctx(ctx,
593 S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
594 /* Error or timeout */
595 mfc_err("Error getting instance from hardware\n");
596 s5p_mfc_release_instance_buffer(ctx);
597 s5p_mfc_release_dec_desc_buffer(ctx);
598 return -EIO;
599 }
600 mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
601 }
602 ret = vb2_streamon(&ctx->vq_src, type);
603 }
604 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
605 ret = vb2_streamon(&ctx->vq_dst, type);
606 mfc_debug_leave();
607 return ret;
608}
609
610/* Stream off, which equals to a pause */
611static int vidioc_streamoff(struct file *file, void *priv,
612 enum v4l2_buf_type type)
613{
614 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
615
616 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
617 return vb2_streamoff(&ctx->vq_src, type);
618 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
619 return vb2_streamoff(&ctx->vq_dst, type);
620 return -EINVAL;
621}
622
623/* Set controls - v4l2 control framework */
624static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
625{
626 struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
627
628 switch (ctrl->id) {
629 case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
630 ctx->loop_filter_mpeg4 = ctrl->val;
631 break;
632 case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:
633 ctx->display_delay_enable = ctrl->val;
634 break;
635 case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
636 ctx->display_delay = ctrl->val;
637 break;
638 case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
639 ctx->slice_interface = ctrl->val;
640 break;
641 default:
642 mfc_err("Invalid control 0x%08x\n", ctrl->id);
643 return -EINVAL;
644 }
645 return 0;
646}
647
648static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
649{
650 struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
651 struct s5p_mfc_dev *dev = ctx->dev;
652
653 switch (ctrl->id) {
654 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
655 if (ctx->state >= MFCINST_HEAD_PARSED &&
656 ctx->state < MFCINST_ABORT) {
657 ctrl->val = ctx->dpb_count;
658 break;
659 } else if (ctx->state != MFCINST_INIT) {
660 v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
661 return -EINVAL;
662 }
663 /* Should wait for the header to be parsed */
664 s5p_mfc_clean_ctx_int_flags(ctx);
665 s5p_mfc_wait_for_done_ctx(ctx,
666 S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
667 if (ctx->state >= MFCINST_HEAD_PARSED &&
668 ctx->state < MFCINST_ABORT) {
669 ctrl->val = ctx->dpb_count;
670 } else {
671 v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
672 return -EINVAL;
673 }
674 break;
675 }
676 return 0;
677}
678
679
680static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {
681 .s_ctrl = s5p_mfc_dec_s_ctrl,
682 .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,
683};
684
685/* Get cropping information */
686static int vidioc_g_crop(struct file *file, void *priv,
687 struct v4l2_crop *cr)
688{
689 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
690 u32 left, right, top, bottom;
691
692 if (ctx->state != MFCINST_HEAD_PARSED &&
693 ctx->state != MFCINST_RUNNING && ctx->state != MFCINST_FINISHING
694 && ctx->state != MFCINST_FINISHED) {
695 mfc_err("Cannont set crop\n");
696 return -EINVAL;
697 }
698 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
699 left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
700 right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
701 left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
702 top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
703 bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
704 top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
705 cr->c.left = left;
706 cr->c.top = top;
707 cr->c.width = ctx->img_width - left - right;
708 cr->c.height = ctx->img_height - top - bottom;
709 mfc_debug(2, "Cropping info [h264]: l=%d t=%d "
710 "w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", left, top,
711 cr->c.width, cr->c.height, right, bottom,
712 ctx->buf_width, ctx->buf_height);
713 } else {
714 cr->c.left = 0;
715 cr->c.top = 0;
716 cr->c.width = ctx->img_width;
717 cr->c.height = ctx->img_height;
718 mfc_debug(2, "Cropping info: w=%d h=%d fw=%d "
719 "fh=%d\n", cr->c.width, cr->c.height, ctx->buf_width,
720 ctx->buf_height);
721 }
722 return 0;
723}
724
725/* v4l2_ioctl_ops */
726static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
727 .vidioc_querycap = vidioc_querycap,
728 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
729 .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
730 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
731 .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
732 .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
733 .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
734 .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
735 .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
736 .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
737 .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
738 .vidioc_reqbufs = vidioc_reqbufs,
739 .vidioc_querybuf = vidioc_querybuf,
740 .vidioc_qbuf = vidioc_qbuf,
741 .vidioc_dqbuf = vidioc_dqbuf,
742 .vidioc_streamon = vidioc_streamon,
743 .vidioc_streamoff = vidioc_streamoff,
744 .vidioc_g_crop = vidioc_g_crop,
745};
746
747static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count,
748 unsigned int *plane_count, unsigned long psize[],
749 void *allocators[])
750{
751 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
752
753 /* Video output for decoding (source)
754 * this can be set after getting an instance */
755 if (ctx->state == MFCINST_INIT &&
756 vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
757 /* A single plane is required for input */
758 *plane_count = 1;
759 if (*buf_count < 1)
760 *buf_count = 1;
761 if (*buf_count > MFC_MAX_BUFFERS)
762 *buf_count = MFC_MAX_BUFFERS;
763 /* Video capture for decoding (destination)
764 * this can be set after the header was parsed */
765 } else if (ctx->state == MFCINST_HEAD_PARSED &&
766 vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
767 /* Output plane count is 2 - one for Y and one for CbCr */
768 *plane_count = 2;
769 /* Setup buffer count */
770 if (*buf_count < ctx->dpb_count)
771 *buf_count = ctx->dpb_count;
772 if (*buf_count > ctx->dpb_count + MFC_MAX_EXTRA_DPB)
773 *buf_count = ctx->dpb_count + MFC_MAX_EXTRA_DPB;
774 if (*buf_count > MFC_MAX_BUFFERS)
775 *buf_count = MFC_MAX_BUFFERS;
776 } else {
777 mfc_err("State seems invalid. State = %d, vq->type = %d\n",
778 ctx->state, vq->type);
779 return -EINVAL;
780 }
781 mfc_debug(2, "Buffer count=%d, plane count=%d\n",
782 *buf_count, *plane_count);
783 if (ctx->state == MFCINST_HEAD_PARSED &&
784 vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
785 psize[0] = ctx->luma_size;
786 psize[1] = ctx->chroma_size;
787 allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
788 allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
789 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
790 ctx->state == MFCINST_INIT) {
791 psize[0] = ctx->dec_src_buf_size;
792 allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
793 } else {
794 mfc_err("This video node is dedicated to decoding. Decoding not initalised\n");
795 return -EINVAL;
796 }
797 return 0;
798}
799
800static void s5p_mfc_unlock(struct vb2_queue *q)
801{
802 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
803 struct s5p_mfc_dev *dev = ctx->dev;
804
805 mutex_unlock(&dev->mfc_mutex);
806}
807
808static void s5p_mfc_lock(struct vb2_queue *q)
809{
810 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
811 struct s5p_mfc_dev *dev = ctx->dev;
812
813 mutex_lock(&dev->mfc_mutex);
814}
815
816static int s5p_mfc_buf_init(struct vb2_buffer *vb)
817{
818 struct vb2_queue *vq = vb->vb2_queue;
819 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
820 unsigned int i;
821
822 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
823 if (ctx->capture_state == QUEUE_BUFS_MMAPED)
824 return 0;
825 for (i = 0; i <= ctx->src_fmt->num_planes ; i++) {
826 if (IS_ERR_OR_NULL(ERR_PTR(
827 vb2_dma_contig_plane_paddr(vb, i)))) {
828 mfc_err("Plane mem not allocated\n");
829 return -EINVAL;
830 }
831 }
832 if (vb2_plane_size(vb, 0) < ctx->luma_size ||
833 vb2_plane_size(vb, 1) < ctx->chroma_size) {
834 mfc_err("Plane buffer (CAPTURE) is too small\n");
835 return -EINVAL;
836 }
837 i = vb->v4l2_buf.index;
838 ctx->dst_bufs[i].b = vb;
839 ctx->dst_bufs[i].cookie.raw.luma =
840 vb2_dma_contig_plane_paddr(vb, 0);
841 ctx->dst_bufs[i].cookie.raw.chroma =
842 vb2_dma_contig_plane_paddr(vb, 1);
843 ctx->dst_bufs_cnt++;
844 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
845 if (IS_ERR_OR_NULL(ERR_PTR(
846 vb2_dma_contig_plane_paddr(vb, 0)))) {
847 mfc_err("Plane memory not allocated\n");
848 return -EINVAL;
849 }
850 if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {
851 mfc_err("Plane buffer (OUTPUT) is too small\n");
852 return -EINVAL;
853 }
854
855 i = vb->v4l2_buf.index;
856 ctx->src_bufs[i].b = vb;
857 ctx->src_bufs[i].cookie.stream =
858 vb2_dma_contig_plane_paddr(vb, 0);
859 ctx->src_bufs_cnt++;
860 } else {
861 mfc_err("s5p_mfc_buf_init: unknown queue type\n");
862 return -EINVAL;
863 }
864 return 0;
865}
866
867static int s5p_mfc_start_streaming(struct vb2_queue *q)
868{
869 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
870 struct s5p_mfc_dev *dev = ctx->dev;
871 unsigned long flags;
872
873 v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
874 if (ctx->state == MFCINST_FINISHING ||
875 ctx->state == MFCINST_FINISHED)
876 ctx->state = MFCINST_RUNNING;
877 /* If context is ready then dev = work->data;schedule it to run */
878 if (s5p_mfc_ctx_ready(ctx)) {
879 spin_lock_irqsave(&dev->condlock, flags);
880 set_bit(ctx->num, &dev->ctx_work_bits);
881 spin_unlock_irqrestore(&dev->condlock, flags);
882 }
883 s5p_mfc_try_run(dev);
884 return 0;
885}
886
887static int s5p_mfc_stop_streaming(struct vb2_queue *q)
888{
889 unsigned long flags;
890 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
891 struct s5p_mfc_dev *dev = ctx->dev;
892 int aborted = 0;
893
894 if ((ctx->state == MFCINST_FINISHING ||
895 ctx->state == MFCINST_RUNNING) &&
896 dev->curr_ctx == ctx->num && dev->hw_lock) {
897 ctx->state = MFCINST_ABORT;
898 s5p_mfc_wait_for_done_ctx(ctx,
899 S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
900 aborted = 1;
901 }
902 spin_lock_irqsave(&dev->irqlock, flags);
903 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
904 s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
905 INIT_LIST_HEAD(&ctx->dst_queue);
906 ctx->dst_queue_cnt = 0;
907 ctx->dpb_flush_flag = 1;
908 ctx->dec_dst_flag = 0;
909 }
910 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
911 s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
912 INIT_LIST_HEAD(&ctx->src_queue);
913 ctx->src_queue_cnt = 0;
914 }
915 if (aborted)
916 ctx->state = MFCINST_RUNNING;
917 spin_unlock_irqrestore(&dev->irqlock, flags);
918 return 0;
919}
920
921
922static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
923{
924 struct vb2_queue *vq = vb->vb2_queue;
925 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
926 struct s5p_mfc_dev *dev = ctx->dev;
927 unsigned long flags;
928 struct s5p_mfc_buf *mfc_buf;
929
930 if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
931 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
932 mfc_buf->used = 0;
933 spin_lock_irqsave(&dev->irqlock, flags);
934 list_add_tail(&mfc_buf->list, &ctx->src_queue);
935 ctx->src_queue_cnt++;
936 spin_unlock_irqrestore(&dev->irqlock, flags);
937 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
938 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
939 mfc_buf->used = 0;
940 /* Mark destination as available for use by MFC */
941 spin_lock_irqsave(&dev->irqlock, flags);
942 set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
943 list_add_tail(&mfc_buf->list, &ctx->dst_queue);
944 ctx->dst_queue_cnt++;
945 spin_unlock_irqrestore(&dev->irqlock, flags);
946 } else {
947 mfc_err("Unsupported buffer type (%d)\n", vq->type);
948 }
949 if (s5p_mfc_ctx_ready(ctx)) {
950 spin_lock_irqsave(&dev->condlock, flags);
951 set_bit(ctx->num, &dev->ctx_work_bits);
952 spin_unlock_irqrestore(&dev->condlock, flags);
953 }
954 s5p_mfc_try_run(dev);
955}
956
957static struct vb2_ops s5p_mfc_dec_qops = {
958 .queue_setup = s5p_mfc_queue_setup,
959 .wait_prepare = s5p_mfc_unlock,
960 .wait_finish = s5p_mfc_lock,
961 .buf_init = s5p_mfc_buf_init,
962 .start_streaming = s5p_mfc_start_streaming,
963 .stop_streaming = s5p_mfc_stop_streaming,
964 .buf_queue = s5p_mfc_buf_queue,
965};
966
967struct s5p_mfc_codec_ops *get_dec_codec_ops(void)
968{
969 return &decoder_codec_ops;
970}
971
972struct vb2_ops *get_dec_queue_ops(void)
973{
974 return &s5p_mfc_dec_qops;
975}
976
977const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)
978{
979 return &s5p_mfc_dec_ioctl_ops;
980}
981
982#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \
983 && V4L2_CTRL_DRIVER_PRIV(x))
984
985int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
986{
987 struct v4l2_ctrl_config cfg;
988 int i;
989
990 v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
991 if (ctx->ctrl_handler.error) {
992 mfc_err("v4l2_ctrl_handler_init failed\n");
993 return ctx->ctrl_handler.error;
994 }
995
996 for (i = 0; i < NUM_CTRLS; i++) {
997 if (IS_MFC51_PRIV(controls[i].id)) {
998 cfg.ops = &s5p_mfc_dec_ctrl_ops;
999 cfg.id = controls[i].id;
1000 cfg.min = controls[i].minimum;
1001 cfg.max = controls[i].maximum;
1002 cfg.def = controls[i].default_value;
1003 cfg.name = controls[i].name;
1004 cfg.type = controls[i].type;
1005
1006 cfg.step = controls[i].step;
1007 cfg.menu_skip_mask = 0;
1008
1009 ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
1010 &cfg, NULL);
1011 } else {
1012 ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,
1013 &s5p_mfc_dec_ctrl_ops,
1014 controls[i].id, controls[i].minimum,
1015 controls[i].maximum, controls[i].step,
1016 controls[i].default_value);
1017 }
1018 if (ctx->ctrl_handler.error) {
1019 mfc_err("Adding control (%d) failed\n", i);
1020 return ctx->ctrl_handler.error;
1021 }
1022 if (controls[i].is_volatile && ctx->ctrls[i])
1023 ctx->ctrls[i]->is_volatile = 1;
1024 }
1025 return 0;
1026}
1027
1028void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
1029{
1030 int i;
1031
1032 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1033 for (i = 0; i < NUM_CTRLS; i++)
1034 ctx->ctrls[i] = NULL;
1035}
1036
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
new file mode 100644
index 000000000000..fb8b215db0e7
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
@@ -0,0 +1,23 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_DEC_H_
14#define S5P_MFC_DEC_H_
15
16struct s5p_mfc_codec_ops *get_dec_codec_ops(void);
17struct vb2_ops *get_dec_queue_ops(void);
18const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
19struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
20int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
21void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
22
23#endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
new file mode 100644
index 000000000000..fee094a14f4c
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -0,0 +1,1829 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
3 *
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * Jeongtae Park <jtp.park@samsung.com>
8 * Kamil Debski <k.debski@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 as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 */
15
16#include <linux/clk.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/sched.h>
22#include <linux/version.h>
23#include <linux/videodev2.h>
24#include <linux/workqueue.h>
25#include <media/v4l2-ctrls.h>
26#include <media/videobuf2-core.h>
27#include "regs-mfc.h"
28#include "s5p_mfc_common.h"
29#include "s5p_mfc_debug.h"
30#include "s5p_mfc_enc.h"
31#include "s5p_mfc_intr.h"
32#include "s5p_mfc_opr.h"
33
34static struct s5p_mfc_fmt formats[] = {
35 {
36 .name = "4:2:0 2 Planes 64x32 Tiles",
37 .fourcc = V4L2_PIX_FMT_NV12MT,
38 .codec_mode = S5P_FIMV_CODEC_NONE,
39 .type = MFC_FMT_RAW,
40 .num_planes = 2,
41 },
42 {
43 .name = "4:2:0 2 Planes",
44 .fourcc = V4L2_PIX_FMT_NV12M,
45 .codec_mode = S5P_FIMV_CODEC_NONE,
46 .type = MFC_FMT_RAW,
47 .num_planes = 2,
48 },
49 {
50 .name = "H264 Encoded Stream",
51 .fourcc = V4L2_PIX_FMT_H264,
52 .codec_mode = S5P_FIMV_CODEC_H264_ENC,
53 .type = MFC_FMT_ENC,
54 .num_planes = 1,
55 },
56 {
57 .name = "MPEG4 Encoded Stream",
58 .fourcc = V4L2_PIX_FMT_MPEG4,
59 .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
60 .type = MFC_FMT_ENC,
61 .num_planes = 1,
62 },
63 {
64 .name = "H264 Encoded Stream",
65 .fourcc = V4L2_PIX_FMT_H263,
66 .codec_mode = S5P_FIMV_CODEC_H263_ENC,
67 .type = MFC_FMT_ENC,
68 .num_planes = 1,
69 },
70};
71
72#define NUM_FORMATS ARRAY_SIZE(formats)
73static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
74{
75 unsigned int i;
76
77 for (i = 0; i < NUM_FORMATS; i++) {
78 if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
79 formats[i].type == t)
80 return &formats[i];
81 }
82 return NULL;
83}
84
85static struct mfc_control controls[] = {
86 {
87 .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .minimum = 0,
90 .maximum = (1 << 16) - 1,
91 .step = 1,
92 .default_value = 0,
93 },
94 {
95 .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
96 .type = V4L2_CTRL_TYPE_MENU,
97 .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
98 .maximum = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES,
99 .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
100 .menu_skip_mask = 0,
101 },
102 {
103 .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .minimum = 1,
106 .maximum = (1 << 16) - 1,
107 .step = 1,
108 .default_value = 1,
109 },
110 {
111 .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
112 .type = V4L2_CTRL_TYPE_INTEGER,
113 .minimum = 1900,
114 .maximum = (1 << 30) - 1,
115 .step = 1,
116 .default_value = 1900,
117 },
118 {
119 .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .minimum = 0,
122 .maximum = (1 << 16) - 1,
123 .step = 1,
124 .default_value = 0,
125 },
126 {
127 .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING,
128 .type = V4L2_CTRL_TYPE_BOOLEAN,
129 .name = "Padding Control Enable",
130 .minimum = 0,
131 .maximum = 1,
132 .step = 1,
133 .default_value = 0,
134 },
135 {
136 .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV,
137 .type = V4L2_CTRL_TYPE_INTEGER,
138 .name = "Padding Color YUV Value",
139 .minimum = 0,
140 .maximum = (1 << 25) - 1,
141 .step = 1,
142 .default_value = 0,
143 },
144 {
145 .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
146 .type = V4L2_CTRL_TYPE_BOOLEAN,
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
150 .default_value = 0,
151 },
152 {
153 .id = V4L2_CID_MPEG_VIDEO_BITRATE,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .minimum = 1,
156 .maximum = (1 << 30) - 1,
157 .step = 1,
158 .default_value = 1,
159 },
160 {
161 .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF,
162 .type = V4L2_CTRL_TYPE_INTEGER,
163 .name = "Rate Control Reaction Coeff.",
164 .minimum = 1,
165 .maximum = (1 << 16) - 1,
166 .step = 1,
167 .default_value = 1,
168 },
169 {
170 .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Force frame type",
173 .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
174 .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
175 .default_value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
176 .menu_skip_mask = 0,
177 },
178 {
179 .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .minimum = 0,
182 .maximum = (1 << 16) - 1,
183 .step = 1,
184 .default_value = 0,
185 },
186 {
187 .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE,
188 .type = V4L2_CTRL_TYPE_INTEGER,
189 .minimum = 0,
190 .maximum = (1 << 16) - 1,
191 .step = 1,
192 .default_value = 0,
193 },
194 {
195 .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
196 .type = V4L2_CTRL_TYPE_MENU,
197 .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
198 .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
199 .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
200 .menu_skip_mask = 0,
201 },
202 {
203 .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
204 .type = V4L2_CTRL_TYPE_MENU,
205 .name = "Frame Skip Enable",
206 .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
207 .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
208 .menu_skip_mask = 0,
209 .default_value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
210 },
211 {
212 .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT,
213 .type = V4L2_CTRL_TYPE_BOOLEAN,
214 .name = "Fixed Target Bit Enable",
215 .minimum = 0,
216 .maximum = 1,
217 .default_value = 0,
218 .menu_skip_mask = 0,
219 },
220 {
221 .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
222 .type = V4L2_CTRL_TYPE_INTEGER,
223 .minimum = 0,
224 .maximum = 2,
225 .step = 1,
226 .default_value = 0,
227 },
228 {
229 .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
230 .type = V4L2_CTRL_TYPE_MENU,
231 .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
232 .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
233 .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
234 .menu_skip_mask = ~(
235 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
236 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
237 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
238 ),
239 },
240 {
241 .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
242 .type = V4L2_CTRL_TYPE_MENU,
243 .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
244 .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
245 .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
246 .menu_skip_mask = ~(
247 (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
248 (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
249 (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
250 (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_1)
251 ),
252 },
253 {
254 .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
255 .type = V4L2_CTRL_TYPE_MENU,
256 .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
257 .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
258 .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
259 .menu_skip_mask = 0,
260 },
261 {
262 .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
263 .type = V4L2_CTRL_TYPE_MENU,
264 .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
265 .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
266 .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
267 .menu_skip_mask = 0,
268 },
269 {
270 .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
271 .type = V4L2_CTRL_TYPE_INTEGER,
272 .minimum = -6,
273 .maximum = 6,
274 .step = 1,
275 .default_value = 0,
276 },
277 {
278 .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
279 .type = V4L2_CTRL_TYPE_INTEGER,
280 .minimum = -6,
281 .maximum = 6,
282 .step = 1,
283 .default_value = 0,
284 },
285 {
286 .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
287 .type = V4L2_CTRL_TYPE_MENU,
288 .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
289 .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
290 .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
291 .menu_skip_mask = 0,
292 },
293 {
294 .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
295 .type = V4L2_CTRL_TYPE_INTEGER,
296 .name = "The Number of Ref. Pic for P",
297 .minimum = 1,
298 .maximum = 2,
299 .step = 1,
300 .default_value = 1,
301 },
302 {
303 .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
304 .type = V4L2_CTRL_TYPE_BOOLEAN,
305 .minimum = 0,
306 .maximum = 1,
307 .step = 1,
308 .default_value = 0,
309 },
310 {
311 .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
312 .type = V4L2_CTRL_TYPE_BOOLEAN,
313 .minimum = 0,
314 .maximum = 1,
315 .step = 1,
316 .default_value = 0,
317 },
318 {
319 .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
320 .type = V4L2_CTRL_TYPE_INTEGER,
321 .minimum = 0,
322 .maximum = 51,
323 .step = 1,
324 .default_value = 1,
325 },
326 {
327 .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
328 .type = V4L2_CTRL_TYPE_INTEGER,
329 .minimum = 0,
330 .maximum = 51,
331 .step = 1,
332 .default_value = 1,
333 },
334 {
335 .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
336 .type = V4L2_CTRL_TYPE_INTEGER,
337 .minimum = 0,
338 .maximum = 51,
339 .step = 1,
340 .default_value = 1,
341 },
342 {
343 .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
344 .type = V4L2_CTRL_TYPE_INTEGER,
345 .minimum = 0,
346 .maximum = 51,
347 .step = 1,
348 .default_value = 1,
349 },
350 {
351 .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
352 .type = V4L2_CTRL_TYPE_INTEGER,
353 .minimum = 0,
354 .maximum = 51,
355 .step = 1,
356 .default_value = 1,
357 },
358 {
359 .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
360 .type = V4L2_CTRL_TYPE_INTEGER,
361 .name = "H263 I-Frame QP value",
362 .minimum = 1,
363 .maximum = 31,
364 .step = 1,
365 .default_value = 1,
366 },
367 {
368 .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
369 .type = V4L2_CTRL_TYPE_INTEGER,
370 .name = "H263 Minimum QP value",
371 .minimum = 1,
372 .maximum = 31,
373 .step = 1,
374 .default_value = 1,
375 },
376 {
377 .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
378 .type = V4L2_CTRL_TYPE_INTEGER,
379 .name = "H263 Maximum QP value",
380 .minimum = 1,
381 .maximum = 31,
382 .step = 1,
383 .default_value = 1,
384 },
385 {
386 .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
387 .type = V4L2_CTRL_TYPE_INTEGER,
388 .name = "H263 P frame QP value",
389 .minimum = 1,
390 .maximum = 31,
391 .step = 1,
392 .default_value = 1,
393 },
394 {
395 .id = V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP,
396 .type = V4L2_CTRL_TYPE_INTEGER,
397 .name = "H263 B frame QP value",
398 .minimum = 1,
399 .maximum = 31,
400 .step = 1,
401 .default_value = 1,
402 },
403 {
404 .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
405 .type = V4L2_CTRL_TYPE_INTEGER,
406 .name = "MPEG4 I-Frame QP value",
407 .minimum = 1,
408 .maximum = 31,
409 .step = 1,
410 .default_value = 1,
411 },
412 {
413 .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
414 .type = V4L2_CTRL_TYPE_INTEGER,
415 .name = "MPEG4 Minimum QP value",
416 .minimum = 1,
417 .maximum = 31,
418 .step = 1,
419 .default_value = 1,
420 },
421 {
422 .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
423 .type = V4L2_CTRL_TYPE_INTEGER,
424 .name = "MPEG4 Maximum QP value",
425 .minimum = 0,
426 .maximum = 51,
427 .step = 1,
428 .default_value = 1,
429 },
430 {
431 .id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP,
432 .type = V4L2_CTRL_TYPE_INTEGER,
433 .name = "MPEG4 P frame QP value",
434 .minimum = 1,
435 .maximum = 31,
436 .step = 1,
437 .default_value = 1,
438 },
439 {
440 .id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP,
441 .type = V4L2_CTRL_TYPE_INTEGER,
442 .name = "MPEG4 B frame QP value",
443 .minimum = 1,
444 .maximum = 31,
445 .step = 1,
446 .default_value = 1,
447 },
448 {
449 .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
450 .type = V4L2_CTRL_TYPE_BOOLEAN,
451 .name = "H264 Dark Reg Adaptive RC",
452 .minimum = 0,
453 .maximum = 1,
454 .step = 1,
455 .default_value = 0,
456 },
457 {
458 .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH,
459 .type = V4L2_CTRL_TYPE_BOOLEAN,
460 .name = "H264 Smooth Reg Adaptive RC",
461 .minimum = 0,
462 .maximum = 1,
463 .step = 1,
464 .default_value = 0,
465 },
466 {
467 .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC,
468 .type = V4L2_CTRL_TYPE_BOOLEAN,
469 .name = "H264 Static Reg Adaptive RC",
470 .minimum = 0,
471 .maximum = 1,
472 .step = 1,
473 .default_value = 0,
474 },
475 {
476 .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY,
477 .type = V4L2_CTRL_TYPE_BOOLEAN,
478 .name = "H264 Activity Reg Adaptive RC",
479 .minimum = 0,
480 .maximum = 1,
481 .step = 1,
482 .default_value = 0,
483 },
484 {
485 .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
486 .type = V4L2_CTRL_TYPE_BOOLEAN,
487 .minimum = 0,
488 .maximum = 1,
489 .step = 1,
490 .default_value = 0,
491 },
492 {
493 .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
494 .type = V4L2_CTRL_TYPE_MENU,
495 .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
496 .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
497 .default_value = 0,
498 .menu_skip_mask = 0,
499 },
500 {
501 .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
502 .type = V4L2_CTRL_TYPE_INTEGER,
503 .minimum = 0,
504 .maximum = (1 << 16) - 1,
505 .step = 1,
506 .default_value = 0,
507 },
508 {
509 .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
510 .type = V4L2_CTRL_TYPE_INTEGER,
511 .minimum = 0,
512 .maximum = (1 << 16) - 1,
513 .step = 1,
514 .default_value = 0,
515 },
516 {
517 .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
518 .type = V4L2_CTRL_TYPE_BOOLEAN,
519 .minimum = 0,
520 .maximum = 1,
521 .step = 1,
522 .default_value = 1,
523 },
524 {
525 .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
526 .type = V4L2_CTRL_TYPE_INTEGER,
527 .minimum = 0,
528 .maximum = (1 << 16) - 1,
529 .step = 1,
530 .default_value = 0,
531 },
532 {
533 .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
534 .type = V4L2_CTRL_TYPE_MENU,
535 .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
536 .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
537 .default_value = 0,
538 .menu_skip_mask = 0,
539 },
540 {
541 .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
542 .type = V4L2_CTRL_TYPE_BOOLEAN,
543 .minimum = 0,
544 .maximum = 1,
545 .step = 1,
546 .default_value = 0,
547 },
548};
549
550#define NUM_CTRLS ARRAY_SIZE(controls)
551static const char * const *mfc51_get_menu(u32 id)
552{
553 static const char * const mfc51_video_frame_skip[] = {
554 "Disabled",
555 "Level Limit",
556 "VBV/CPB Limit",
557 NULL,
558 };
559 static const char * const mfc51_video_force_frame[] = {
560 "Disabled",
561 "I Frame",
562 "Not Coded",
563 NULL,
564 };
565 switch (id) {
566 case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
567 return mfc51_video_frame_skip;
568 case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
569 return mfc51_video_force_frame;
570 }
571 return NULL;
572}
573
574static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
575{
576 mfc_debug(2, "src=%d, dst=%d, state=%d\n",
577 ctx->src_queue_cnt, ctx->dst_queue_cnt, ctx->state);
578 /* context is ready to make header */
579 if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
580 return 1;
581 /* context is ready to encode a frame */
582 if (ctx->state == MFCINST_RUNNING &&
583 ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
584 return 1;
585 /* context is ready to encode remain frames */
586 if (ctx->state == MFCINST_FINISHING &&
587 ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
588 return 1;
589 mfc_debug(2, "ctx is not ready\n");
590 return 0;
591}
592
593static void cleanup_ref_queue(struct s5p_mfc_ctx *ctx)
594{
595 struct s5p_mfc_buf *mb_entry;
596 unsigned long mb_y_addr, mb_c_addr;
597
598 /* move buffers in ref queue to src queue */
599 while (!list_empty(&ctx->ref_queue)) {
600 mb_entry = list_entry((&ctx->ref_queue)->next,
601 struct s5p_mfc_buf, list);
602 mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
603 mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
604 list_del(&mb_entry->list);
605 ctx->ref_queue_cnt--;
606 list_add_tail(&mb_entry->list, &ctx->src_queue);
607 ctx->src_queue_cnt++;
608 }
609 mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
610 ctx->src_queue_cnt, ctx->ref_queue_cnt);
611 INIT_LIST_HEAD(&ctx->ref_queue);
612 ctx->ref_queue_cnt = 0;
613}
614
615static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
616{
617 struct s5p_mfc_dev *dev = ctx->dev;
618 struct s5p_mfc_buf *dst_mb;
619 unsigned long dst_addr;
620 unsigned int dst_size;
621 unsigned long flags;
622
623 spin_lock_irqsave(&dev->irqlock, flags);
624 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
625 dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
626 dst_size = vb2_plane_size(dst_mb->b, 0);
627 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
628 spin_unlock_irqrestore(&dev->irqlock, flags);
629 return 0;
630}
631
632static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
633{
634 struct s5p_mfc_dev *dev = ctx->dev;
635 struct s5p_mfc_enc_params *p = &ctx->enc_params;
636 struct s5p_mfc_buf *dst_mb;
637 unsigned long flags;
638
639 if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) {
640 spin_lock_irqsave(&dev->irqlock, flags);
641 dst_mb = list_entry(ctx->dst_queue.next,
642 struct s5p_mfc_buf, list);
643 list_del(&dst_mb->list);
644 ctx->dst_queue_cnt--;
645 vb2_set_plane_payload(dst_mb->b, 0,
646 s5p_mfc_get_enc_strm_size());
647 vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
648 spin_unlock_irqrestore(&dev->irqlock, flags);
649 }
650 ctx->state = MFCINST_RUNNING;
651 if (s5p_mfc_ctx_ready(ctx)) {
652 spin_lock_irqsave(&dev->condlock, flags);
653 set_bit(ctx->num, &dev->ctx_work_bits);
654 spin_unlock_irqrestore(&dev->condlock, flags);
655 }
656 s5p_mfc_try_run(dev);
657 return 0;
658}
659
660static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
661{
662 struct s5p_mfc_dev *dev = ctx->dev;
663 struct s5p_mfc_buf *dst_mb;
664 struct s5p_mfc_buf *src_mb;
665 unsigned long flags;
666 unsigned long src_y_addr, src_c_addr, dst_addr;
667 unsigned int dst_size;
668
669 spin_lock_irqsave(&dev->irqlock, flags);
670 src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
671 src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
672 src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
673 s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
674 spin_unlock_irqrestore(&dev->irqlock, flags);
675
676 spin_lock_irqsave(&dev->irqlock, flags);
677 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
678 dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
679 dst_size = vb2_plane_size(dst_mb->b, 0);
680 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
681 spin_unlock_irqrestore(&dev->irqlock, flags);
682
683 return 0;
684}
685
686static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
687{
688 struct s5p_mfc_dev *dev = ctx->dev;
689 struct s5p_mfc_buf *mb_entry;
690 unsigned long enc_y_addr, enc_c_addr;
691 unsigned long mb_y_addr, mb_c_addr;
692 int slice_type;
693 unsigned int strm_size;
694 unsigned long flags;
695
696 slice_type = s5p_mfc_get_enc_slice_type();
697 strm_size = s5p_mfc_get_enc_strm_size();
698 mfc_debug(2, "Encoded slice type: %d", slice_type);
699 mfc_debug(2, "Encoded stream size: %d", strm_size);
700 mfc_debug(2, "Display order: %d",
701 mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
702 spin_lock_irqsave(&dev->irqlock, flags);
703 if (slice_type >= 0) {
704 s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
705 list_for_each_entry(mb_entry, &ctx->src_queue, list) {
706 mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
707 mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
708 if ((enc_y_addr == mb_y_addr) &&
709 (enc_c_addr == mb_c_addr)) {
710 list_del(&mb_entry->list);
711 ctx->src_queue_cnt--;
712 vb2_buffer_done(mb_entry->b,
713 VB2_BUF_STATE_DONE);
714 break;
715 }
716 }
717 list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
718 mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
719 mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
720 if ((enc_y_addr == mb_y_addr) &&
721 (enc_c_addr == mb_c_addr)) {
722 list_del(&mb_entry->list);
723 ctx->ref_queue_cnt--;
724 vb2_buffer_done(mb_entry->b,
725 VB2_BUF_STATE_DONE);
726 break;
727 }
728 }
729 }
730 if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
731 mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
732 list);
733 if (mb_entry->used) {
734 list_del(&mb_entry->list);
735 ctx->src_queue_cnt--;
736 list_add_tail(&mb_entry->list, &ctx->ref_queue);
737 ctx->ref_queue_cnt++;
738 }
739 mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
740 ctx->src_queue_cnt, ctx->ref_queue_cnt);
741 }
742 if (strm_size > 0) {
743 /* at least one more dest. buffers exist always */
744 mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
745 list);
746 list_del(&mb_entry->list);
747 ctx->dst_queue_cnt--;
748 switch (slice_type) {
749 case S5P_FIMV_ENC_SI_SLICE_TYPE_I:
750 mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
751 break;
752 case S5P_FIMV_ENC_SI_SLICE_TYPE_P:
753 mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
754 break;
755 case S5P_FIMV_ENC_SI_SLICE_TYPE_B:
756 mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME;
757 break;
758 }
759 vb2_set_plane_payload(mb_entry->b, 0, strm_size);
760 vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
761 }
762 spin_unlock_irqrestore(&dev->irqlock, flags);
763 if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) {
764 spin_lock(&dev->condlock);
765 clear_bit(ctx->num, &dev->ctx_work_bits);
766 spin_unlock(&dev->condlock);
767 }
768 return 0;
769}
770
771static struct s5p_mfc_codec_ops encoder_codec_ops = {
772 .pre_seq_start = enc_pre_seq_start,
773 .post_seq_start = enc_post_seq_start,
774 .pre_frame_start = enc_pre_frame_start,
775 .post_frame_start = enc_post_frame_start,
776};
777
778/* Query capabilities of the device */
779static int vidioc_querycap(struct file *file, void *priv,
780 struct v4l2_capability *cap)
781{
782 struct s5p_mfc_dev *dev = video_drvdata(file);
783
784 strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
785 strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
786 cap->bus_info[0] = 0;
787 cap->version = KERNEL_VERSION(1, 0, 0);
788 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
789 | V4L2_CAP_VIDEO_OUTPUT
790 | V4L2_CAP_STREAMING;
791 return 0;
792}
793
794static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out)
795{
796 struct s5p_mfc_fmt *fmt;
797 int i, j = 0;
798
799 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
800 if (mplane && formats[i].num_planes == 1)
801 continue;
802 else if (!mplane && formats[i].num_planes > 1)
803 continue;
804 if (out && formats[i].type != MFC_FMT_RAW)
805 continue;
806 else if (!out && formats[i].type != MFC_FMT_ENC)
807 continue;
808 if (j == f->index) {
809 fmt = &formats[i];
810 strlcpy(f->description, fmt->name,
811 sizeof(f->description));
812 f->pixelformat = fmt->fourcc;
813 return 0;
814 }
815 ++j;
816 }
817 return -EINVAL;
818}
819
820static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
821 struct v4l2_fmtdesc *f)
822{
823 return vidioc_enum_fmt(f, false, false);
824}
825
826static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
827 struct v4l2_fmtdesc *f)
828{
829 return vidioc_enum_fmt(f, true, false);
830}
831
832static int vidioc_enum_fmt_vid_out(struct file *file, void *prov,
833 struct v4l2_fmtdesc *f)
834{
835 return vidioc_enum_fmt(f, false, true);
836}
837
838static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
839 struct v4l2_fmtdesc *f)
840{
841 return vidioc_enum_fmt(f, true, true);
842}
843
844static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
845{
846 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
847 struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
848
849 mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state);
850 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
851 /* This is run on output (encoder dest) */
852 pix_fmt_mp->width = 0;
853 pix_fmt_mp->height = 0;
854 pix_fmt_mp->field = V4L2_FIELD_NONE;
855 pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
856 pix_fmt_mp->num_planes = ctx->dst_fmt->num_planes;
857
858 pix_fmt_mp->plane_fmt[0].bytesperline = ctx->enc_dst_buf_size;
859 pix_fmt_mp->plane_fmt[0].sizeimage = ctx->enc_dst_buf_size;
860 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
861 /* This is run on capture (encoder src) */
862 pix_fmt_mp->width = ctx->img_width;
863 pix_fmt_mp->height = ctx->img_height;
864
865 pix_fmt_mp->field = V4L2_FIELD_NONE;
866 pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
867 pix_fmt_mp->num_planes = ctx->src_fmt->num_planes;
868
869 pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
870 pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
871 pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
872 pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
873 } else {
874 mfc_err("invalid buf type\n");
875 return -EINVAL;
876 }
877 return 0;
878}
879
880static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
881{
882 struct s5p_mfc_fmt *fmt;
883 struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
884
885 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
886 fmt = find_format(f, MFC_FMT_ENC);
887 if (!fmt) {
888 mfc_err("failed to try output format\n");
889 return -EINVAL;
890 }
891
892 if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
893 mfc_err("must be set encoding output size\n");
894 return -EINVAL;
895 }
896
897 pix_fmt_mp->plane_fmt[0].bytesperline =
898 pix_fmt_mp->plane_fmt[0].sizeimage;
899 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
900 fmt = find_format(f, MFC_FMT_RAW);
901 if (!fmt) {
902 mfc_err("failed to try output format\n");
903 return -EINVAL;
904 }
905
906 if (fmt->num_planes != pix_fmt_mp->num_planes) {
907 mfc_err("failed to try output format\n");
908 return -EINVAL;
909 }
910 } else {
911 mfc_err("invalid buf type\n");
912 return -EINVAL;
913 }
914 return 0;
915}
916
917static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
918{
919 struct s5p_mfc_dev *dev = video_drvdata(file);
920 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
921 struct s5p_mfc_fmt *fmt;
922 struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
923 unsigned long flags;
924 int ret = 0;
925
926 ret = vidioc_try_fmt(file, priv, f);
927 if (ret)
928 return ret;
929 if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
930 v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
931 ret = -EBUSY;
932 goto out;
933 }
934 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
935 fmt = find_format(f, MFC_FMT_ENC);
936 if (!fmt) {
937 mfc_err("failed to set capture format\n");
938 return -EINVAL;
939 }
940 ctx->state = MFCINST_INIT;
941 ctx->dst_fmt = fmt;
942 ctx->codec_mode = ctx->dst_fmt->codec_mode;
943 ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
944 pix_fmt_mp->plane_fmt[0].bytesperline = 0;
945 ctx->dst_bufs_cnt = 0;
946 ctx->capture_state = QUEUE_FREE;
947 s5p_mfc_alloc_instance_buffer(ctx);
948 spin_lock_irqsave(&dev->condlock, flags);
949 set_bit(ctx->num, &dev->ctx_work_bits);
950 spin_unlock_irqrestore(&dev->condlock, flags);
951 s5p_mfc_clean_ctx_int_flags(ctx);
952 s5p_mfc_try_run(dev);
953 if (s5p_mfc_wait_for_done_ctx(ctx, \
954 S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
955 /* Error or timeout */
956 mfc_err("Error getting instance from hardware\n");
957 s5p_mfc_release_instance_buffer(ctx);
958 ret = -EIO;
959 goto out;
960 }
961 mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
962 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
963 fmt = find_format(f, MFC_FMT_RAW);
964 if (!fmt) {
965 mfc_err("failed to set output format\n");
966 return -EINVAL;
967 }
968 if (fmt->num_planes != pix_fmt_mp->num_planes) {
969 mfc_err("failed to set output format\n");
970 ret = -EINVAL;
971 goto out;
972 }
973 ctx->src_fmt = fmt;
974 ctx->img_width = pix_fmt_mp->width;
975 ctx->img_height = pix_fmt_mp->height;
976 mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode);
977 mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
978 pix_fmt_mp->width, pix_fmt_mp->height,
979 ctx->img_width, ctx->img_height);
980 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
981 ctx->buf_width = ALIGN(ctx->img_width,
982 S5P_FIMV_NV12M_HALIGN);
983 ctx->luma_size = ALIGN(ctx->img_width,
984 S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
985 S5P_FIMV_NV12M_LVALIGN);
986 ctx->chroma_size = ALIGN(ctx->img_width,
987 S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
988 >> 1), S5P_FIMV_NV12M_CVALIGN);
989
990 ctx->luma_size = ALIGN(ctx->luma_size,
991 S5P_FIMV_NV12M_SALIGN);
992 ctx->chroma_size = ALIGN(ctx->chroma_size,
993 S5P_FIMV_NV12M_SALIGN);
994
995 pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
996 pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
997 pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
998 pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
999
1000 } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
1001 ctx->buf_width = ALIGN(ctx->img_width,
1002 S5P_FIMV_NV12MT_HALIGN);
1003 ctx->luma_size = ALIGN(ctx->img_width,
1004 S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
1005 S5P_FIMV_NV12MT_VALIGN);
1006 ctx->chroma_size = ALIGN(ctx->img_width,
1007 S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
1008 >> 1), S5P_FIMV_NV12MT_VALIGN);
1009 ctx->luma_size = ALIGN(ctx->luma_size,
1010 S5P_FIMV_NV12MT_SALIGN);
1011 ctx->chroma_size = ALIGN(ctx->chroma_size,
1012 S5P_FIMV_NV12MT_SALIGN);
1013
1014 pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
1015 pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
1016 pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
1017 pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
1018 }
1019 ctx->src_bufs_cnt = 0;
1020 ctx->output_state = QUEUE_FREE;
1021 } else {
1022 mfc_err("invalid buf type\n");
1023 return -EINVAL;
1024 }
1025out:
1026 mfc_debug_leave();
1027 return ret;
1028}
1029
1030static int vidioc_reqbufs(struct file *file, void *priv,
1031 struct v4l2_requestbuffers *reqbufs)
1032{
1033 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1034 int ret = 0;
1035
1036 /* if memory is not mmp or userptr return error */
1037 if ((reqbufs->memory != V4L2_MEMORY_MMAP) &&
1038 (reqbufs->memory != V4L2_MEMORY_USERPTR))
1039 return -EINVAL;
1040 if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1041 if (ctx->capture_state != QUEUE_FREE) {
1042 mfc_err("invalid capture state: %d\n",
1043 ctx->capture_state);
1044 return -EINVAL;
1045 }
1046 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
1047 if (ret != 0) {
1048 mfc_err("error in vb2_reqbufs() for E(D)\n");
1049 return ret;
1050 }
1051 ctx->capture_state = QUEUE_BUFS_REQUESTED;
1052 ret = s5p_mfc_alloc_codec_buffers(ctx);
1053 if (ret) {
1054 mfc_err("Failed to allocate encoding buffers\n");
1055 reqbufs->count = 0;
1056 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
1057 return -ENOMEM;
1058 }
1059 } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1060 if (ctx->output_state != QUEUE_FREE) {
1061 mfc_err("invalid output state: %d\n",
1062 ctx->output_state);
1063 return -EINVAL;
1064 }
1065 ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
1066 if (ret != 0) {
1067 mfc_err("error in vb2_reqbufs() for E(S)\n");
1068 return ret;
1069 }
1070 ctx->output_state = QUEUE_BUFS_REQUESTED;
1071 } else {
1072 mfc_err("invalid buf type\n");
1073 return -EINVAL;
1074 }
1075 return ret;
1076}
1077
1078static int vidioc_querybuf(struct file *file, void *priv,
1079 struct v4l2_buffer *buf)
1080{
1081 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1082 int ret = 0;
1083
1084 /* if memory is not mmp or userptr return error */
1085 if ((buf->memory != V4L2_MEMORY_MMAP) &&
1086 (buf->memory != V4L2_MEMORY_USERPTR))
1087 return -EINVAL;
1088 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1089 if (ctx->state != MFCINST_GOT_INST) {
1090 mfc_err("invalid context state: %d\n", ctx->state);
1091 return -EINVAL;
1092 }
1093 ret = vb2_querybuf(&ctx->vq_dst, buf);
1094 if (ret != 0) {
1095 mfc_err("error in vb2_querybuf() for E(D)\n");
1096 return ret;
1097 }
1098 buf->m.planes[0].m.mem_offset += DST_QUEUE_OFF_BASE;
1099 } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1100 ret = vb2_querybuf(&ctx->vq_src, buf);
1101 if (ret != 0) {
1102 mfc_err("error in vb2_querybuf() for E(S)\n");
1103 return ret;
1104 }
1105 } else {
1106 mfc_err("invalid buf type\n");
1107 return -EINVAL;
1108 }
1109 return ret;
1110}
1111
1112/* Queue a buffer */
1113static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1114{
1115 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1116
1117 if (ctx->state == MFCINST_ERROR) {
1118 mfc_err("Call on QBUF after unrecoverable error\n");
1119 return -EIO;
1120 }
1121 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1122 return vb2_qbuf(&ctx->vq_src, buf);
1123 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1124 return vb2_qbuf(&ctx->vq_dst, buf);
1125 return -EINVAL;
1126}
1127
1128/* Dequeue a buffer */
1129static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1130{
1131 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1132
1133 if (ctx->state == MFCINST_ERROR) {
1134 mfc_err("Call on DQBUF after unrecoverable error\n");
1135 return -EIO;
1136 }
1137 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1138 return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
1139 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1140 return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
1141 return -EINVAL;
1142}
1143
1144/* Stream on */
1145static int vidioc_streamon(struct file *file, void *priv,
1146 enum v4l2_buf_type type)
1147{
1148 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1149
1150 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1151 return vb2_streamon(&ctx->vq_src, type);
1152 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1153 return vb2_streamon(&ctx->vq_dst, type);
1154 return -EINVAL;
1155}
1156
1157/* Stream off, which equals to a pause */
1158static int vidioc_streamoff(struct file *file, void *priv,
1159 enum v4l2_buf_type type)
1160{
1161 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1162
1163 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1164 return vb2_streamoff(&ctx->vq_src, type);
1165 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1166 return vb2_streamoff(&ctx->vq_dst, type);
1167 return -EINVAL;
1168}
1169
1170static inline int h264_level(enum v4l2_mpeg_video_h264_level lvl)
1171{
1172 static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_4_0 + 1] = {
1173 /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0 */ 10,
1174 /* V4L2_MPEG_VIDEO_H264_LEVEL_1B */ 9,
1175 /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1 */ 11,
1176 /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2 */ 12,
1177 /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3 */ 13,
1178 /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0 */ 20,
1179 /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1 */ 21,
1180 /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2 */ 22,
1181 /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0 */ 30,
1182 /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1 */ 31,
1183 /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2 */ 32,
1184 /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0 */ 40,
1185 };
1186 return t[lvl];
1187}
1188
1189static inline int mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
1190{
1191 static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 + 1] = {
1192 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 */ 0,
1193 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B */ 9,
1194 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 */ 1,
1195 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 */ 2,
1196 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 */ 3,
1197 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B */ 7,
1198 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 */ 4,
1199 /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 */ 5,
1200 };
1201 return t[lvl];
1202}
1203
1204static inline int vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
1205{
1206 static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
1207 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED */ 0,
1208 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1 */ 1,
1209 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11 */ 2,
1210 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11 */ 3,
1211 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11 */ 4,
1212 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33 */ 5,
1213 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11 */ 6,
1214 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11 */ 7,
1215 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11 */ 8,
1216 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33 */ 9,
1217 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11 */ 10,
1218 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11 */ 11,
1219 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33 */ 12,
1220 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99 */ 13,
1221 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3 */ 14,
1222 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2 */ 15,
1223 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 */ 16,
1224 /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED */ 255,
1225 };
1226 return t[sar];
1227}
1228
1229static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
1230{
1231 struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
1232 struct s5p_mfc_dev *dev = ctx->dev;
1233 struct s5p_mfc_enc_params *p = &ctx->enc_params;
1234 int ret = 0;
1235
1236 switch (ctrl->id) {
1237 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1238 p->gop_size = ctrl->val;
1239 break;
1240 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
1241 p->slice_mode = ctrl->val;
1242 break;
1243 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
1244 p->slice_mb = ctrl->val;
1245 break;
1246 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
1247 p->slice_bit = ctrl->val * 8;
1248 break;
1249 case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
1250 p->intra_refresh_mb = ctrl->val;
1251 break;
1252 case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
1253 p->pad = ctrl->val;
1254 break;
1255 case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
1256 p->pad_luma = (ctrl->val >> 16) & 0xff;
1257 p->pad_cb = (ctrl->val >> 8) & 0xff;
1258 p->pad_cr = (ctrl->val >> 0) & 0xff;
1259 break;
1260 case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
1261 p->rc_frame = ctrl->val;
1262 break;
1263 case V4L2_CID_MPEG_VIDEO_BITRATE:
1264 p->rc_bitrate = ctrl->val;
1265 break;
1266 case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
1267 p->rc_reaction_coeff = ctrl->val;
1268 break;
1269 case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
1270 ctx->force_frame_type = ctrl->val;
1271 break;
1272 case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
1273 p->vbv_size = ctrl->val;
1274 break;
1275 case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
1276 p->codec.h264.cpb_size = ctrl->val;
1277 break;
1278 case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
1279 p->seq_hdr_mode = ctrl->val;
1280 break;
1281 case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
1282 p->frame_skip_mode = ctrl->val;
1283 break;
1284 case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
1285 p->fixed_target_bit = ctrl->val;
1286 break;
1287 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
1288 p->num_b_frame = ctrl->val;
1289 break;
1290 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
1291 switch (ctrl->val) {
1292 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
1293 p->codec.h264.profile =
1294 S5P_FIMV_ENC_PROFILE_H264_MAIN;
1295 break;
1296 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
1297 p->codec.h264.profile =
1298 S5P_FIMV_ENC_PROFILE_H264_HIGH;
1299 break;
1300 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
1301 p->codec.h264.profile =
1302 S5P_FIMV_ENC_PROFILE_H264_BASELINE;
1303 break;
1304 default:
1305 ret = -EINVAL;
1306 }
1307 break;
1308 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
1309 p->codec.h264.level_v4l2 = ctrl->val;
1310 p->codec.h264.level = h264_level(ctrl->val);
1311 if (p->codec.h264.level < 0) {
1312 mfc_err("Level number is wrong\n");
1313 ret = p->codec.h264.level;
1314 }
1315 break;
1316 case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
1317 p->codec.mpeg4.level_v4l2 = ctrl->val;
1318 p->codec.mpeg4.level = mpeg4_level(ctrl->val);
1319 if (p->codec.mpeg4.level < 0) {
1320 mfc_err("Level number is wrong\n");
1321 ret = p->codec.mpeg4.level;
1322 }
1323 break;
1324 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
1325 p->codec.h264.loop_filter_mode = ctrl->val;
1326 break;
1327 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
1328 p->codec.h264.loop_filter_alpha = ctrl->val;
1329 break;
1330 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
1331 p->codec.h264.loop_filter_beta = ctrl->val;
1332 break;
1333 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
1334 p->codec.h264.entropy_mode = ctrl->val;
1335 break;
1336 case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
1337 p->codec.h264.num_ref_pic_4p = ctrl->val;
1338 break;
1339 case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
1340 p->codec.h264._8x8_transform = ctrl->val;
1341 break;
1342 case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
1343 p->codec.h264.rc_mb = ctrl->val;
1344 break;
1345 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
1346 p->codec.h264.rc_frame_qp = ctrl->val;
1347 break;
1348 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1349 p->codec.h264.rc_min_qp = ctrl->val;
1350 break;
1351 case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
1352 p->codec.h264.rc_max_qp = ctrl->val;
1353 break;
1354 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
1355 p->codec.h264.rc_p_frame_qp = ctrl->val;
1356 break;
1357 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
1358 p->codec.h264.rc_b_frame_qp = ctrl->val;
1359 break;
1360 case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
1361 case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
1362 p->codec.mpeg4.rc_frame_qp = ctrl->val;
1363 break;
1364 case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
1365 case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
1366 p->codec.mpeg4.rc_min_qp = ctrl->val;
1367 break;
1368 case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
1369 case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
1370 p->codec.mpeg4.rc_max_qp = ctrl->val;
1371 break;
1372 case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
1373 case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
1374 p->codec.mpeg4.rc_p_frame_qp = ctrl->val;
1375 break;
1376 case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
1377 case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
1378 p->codec.mpeg4.rc_b_frame_qp = ctrl->val;
1379 break;
1380 case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
1381 p->codec.h264.rc_mb_dark = ctrl->val;
1382 break;
1383 case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
1384 p->codec.h264.rc_mb_smooth = ctrl->val;
1385 break;
1386 case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
1387 p->codec.h264.rc_mb_static = ctrl->val;
1388 break;
1389 case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
1390 p->codec.h264.rc_mb_activity = ctrl->val;
1391 break;
1392 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
1393 p->codec.h264.vui_sar = ctrl->val;
1394 break;
1395 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
1396 p->codec.h264.vui_sar_idc = vui_sar_idc(ctrl->val);
1397 break;
1398 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
1399 p->codec.h264.vui_ext_sar_width = ctrl->val;
1400 break;
1401 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
1402 p->codec.h264.vui_ext_sar_height = ctrl->val;
1403 break;
1404 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
1405 p->codec.h264.open_gop = !ctrl->val;
1406 break;
1407 case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
1408 p->codec.h264.open_gop_size = ctrl->val;
1409 break;
1410 case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
1411 switch (ctrl->val) {
1412 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
1413 p->codec.mpeg4.profile =
1414 S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE;
1415 break;
1416 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
1417 p->codec.mpeg4.profile =
1418 S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE;
1419 break;
1420 default:
1421 ret = -EINVAL;
1422 }
1423 break;
1424 case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
1425 p->codec.mpeg4.quarter_pixel = ctrl->val;
1426 break;
1427 default:
1428 v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n",
1429 ctrl->id, ctrl->val);
1430 ret = -EINVAL;
1431 }
1432 return ret;
1433}
1434
1435static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
1436 .s_ctrl = s5p_mfc_enc_s_ctrl,
1437};
1438
1439int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a)
1440{
1441 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1442
1443 if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1444 ctx->enc_params.rc_framerate_num =
1445 a->parm.output.timeperframe.denominator;
1446 ctx->enc_params.rc_framerate_denom =
1447 a->parm.output.timeperframe.numerator;
1448 } else {
1449 mfc_err("Setting FPS is only possible for the output queue\n");
1450 return -EINVAL;
1451 }
1452 return 0;
1453}
1454
1455int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a)
1456{
1457 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1458
1459 if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1460 a->parm.output.timeperframe.denominator =
1461 ctx->enc_params.rc_framerate_num;
1462 a->parm.output.timeperframe.numerator =
1463 ctx->enc_params.rc_framerate_denom;
1464 } else {
1465 mfc_err("Setting FPS is only possible for the output queue\n");
1466 return -EINVAL;
1467 }
1468 return 0;
1469}
1470
1471static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
1472 .vidioc_querycap = vidioc_querycap,
1473 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1474 .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
1475 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
1476 .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
1477 .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
1478 .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
1479 .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
1480 .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
1481 .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
1482 .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
1483 .vidioc_reqbufs = vidioc_reqbufs,
1484 .vidioc_querybuf = vidioc_querybuf,
1485 .vidioc_qbuf = vidioc_qbuf,
1486 .vidioc_dqbuf = vidioc_dqbuf,
1487 .vidioc_streamon = vidioc_streamon,
1488 .vidioc_streamoff = vidioc_streamoff,
1489 .vidioc_s_parm = vidioc_s_parm,
1490 .vidioc_g_parm = vidioc_g_parm,
1491};
1492
1493static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
1494{
1495 int i;
1496
1497 if (!fmt)
1498 return -EINVAL;
1499 if (fmt->num_planes != vb->num_planes) {
1500 mfc_err("invalid plane number for the format\n");
1501 return -EINVAL;
1502 }
1503 for (i = 0; i < fmt->num_planes; i++) {
1504 if (!vb2_dma_contig_plane_paddr(vb, i)) {
1505 mfc_err("failed to get plane cookie\n");
1506 return -EINVAL;
1507 }
1508 mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx",
1509 vb->v4l2_buf.index, i,
1510 vb2_dma_contig_plane_paddr(vb, i));
1511 }
1512 return 0;
1513}
1514
1515static int s5p_mfc_queue_setup(struct vb2_queue *vq,
1516 unsigned int *buf_count, unsigned int *plane_count,
1517 unsigned long psize[], void *allocators[])
1518{
1519 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
1520
1521 if (ctx->state != MFCINST_GOT_INST) {
1522 mfc_err("inavlid state: %d\n", ctx->state);
1523 return -EINVAL;
1524 }
1525 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1526 if (ctx->dst_fmt)
1527 *plane_count = ctx->dst_fmt->num_planes;
1528 else
1529 *plane_count = MFC_ENC_CAP_PLANE_COUNT;
1530 if (*buf_count < 1)
1531 *buf_count = 1;
1532 if (*buf_count > MFC_MAX_BUFFERS)
1533 *buf_count = MFC_MAX_BUFFERS;
1534 psize[0] = ctx->enc_dst_buf_size;
1535 allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
1536 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1537 if (ctx->src_fmt)
1538 *plane_count = ctx->src_fmt->num_planes;
1539 else
1540 *plane_count = MFC_ENC_OUT_PLANE_COUNT;
1541
1542 if (*buf_count < 1)
1543 *buf_count = 1;
1544 if (*buf_count > MFC_MAX_BUFFERS)
1545 *buf_count = MFC_MAX_BUFFERS;
1546 psize[0] = ctx->luma_size;
1547 psize[1] = ctx->chroma_size;
1548 allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
1549 allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
1550 } else {
1551 mfc_err("inavlid queue type: %d\n", vq->type);
1552 return -EINVAL;
1553 }
1554 return 0;
1555}
1556
1557static void s5p_mfc_unlock(struct vb2_queue *q)
1558{
1559 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
1560 struct s5p_mfc_dev *dev = ctx->dev;
1561
1562 mutex_unlock(&dev->mfc_mutex);
1563}
1564
1565static void s5p_mfc_lock(struct vb2_queue *q)
1566{
1567 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
1568 struct s5p_mfc_dev *dev = ctx->dev;
1569
1570 mutex_lock(&dev->mfc_mutex);
1571}
1572
1573static int s5p_mfc_buf_init(struct vb2_buffer *vb)
1574{
1575 struct vb2_queue *vq = vb->vb2_queue;
1576 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
1577 unsigned int i;
1578 int ret;
1579
1580 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1581 ret = check_vb_with_fmt(ctx->dst_fmt, vb);
1582 if (ret < 0)
1583 return ret;
1584 i = vb->v4l2_buf.index;
1585 ctx->dst_bufs[i].b = vb;
1586 ctx->dst_bufs[i].cookie.stream =
1587 vb2_dma_contig_plane_paddr(vb, 0);
1588 ctx->dst_bufs_cnt++;
1589 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1590 ret = check_vb_with_fmt(ctx->src_fmt, vb);
1591 if (ret < 0)
1592 return ret;
1593 i = vb->v4l2_buf.index;
1594 ctx->src_bufs[i].b = vb;
1595 ctx->src_bufs[i].cookie.raw.luma =
1596 vb2_dma_contig_plane_paddr(vb, 0);
1597 ctx->src_bufs[i].cookie.raw.chroma =
1598 vb2_dma_contig_plane_paddr(vb, 1);
1599 ctx->src_bufs_cnt++;
1600 } else {
1601 mfc_err("inavlid queue type: %d\n", vq->type);
1602 return -EINVAL;
1603 }
1604 return 0;
1605}
1606
1607static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
1608{
1609 struct vb2_queue *vq = vb->vb2_queue;
1610 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
1611 int ret;
1612
1613 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1614 ret = check_vb_with_fmt(ctx->dst_fmt, vb);
1615 if (ret < 0)
1616 return ret;
1617 mfc_debug(2, "plane size: %ld, dst size: %d\n",
1618 vb2_plane_size(vb, 0), ctx->enc_dst_buf_size);
1619 if (vb2_plane_size(vb, 0) < ctx->enc_dst_buf_size) {
1620 mfc_err("plane size is too small for capture\n");
1621 return -EINVAL;
1622 }
1623 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1624 ret = check_vb_with_fmt(ctx->src_fmt, vb);
1625 if (ret < 0)
1626 return ret;
1627 mfc_debug(2, "plane size: %ld, luma size: %d\n",
1628 vb2_plane_size(vb, 0), ctx->luma_size);
1629 mfc_debug(2, "plane size: %ld, chroma size: %d\n",
1630 vb2_plane_size(vb, 1), ctx->chroma_size);
1631 if (vb2_plane_size(vb, 0) < ctx->luma_size ||
1632 vb2_plane_size(vb, 1) < ctx->chroma_size) {
1633 mfc_err("plane size is too small for output\n");
1634 return -EINVAL;
1635 }
1636 } else {
1637 mfc_err("inavlid queue type: %d\n", vq->type);
1638 return -EINVAL;
1639 }
1640 return 0;
1641}
1642
1643static int s5p_mfc_start_streaming(struct vb2_queue *q)
1644{
1645 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
1646 struct s5p_mfc_dev *dev = ctx->dev;
1647 unsigned long flags;
1648
1649 v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1650 /* If context is ready then dev = work->data;schedule it to run */
1651 if (s5p_mfc_ctx_ready(ctx)) {
1652 spin_lock_irqsave(&dev->condlock, flags);
1653 set_bit(ctx->num, &dev->ctx_work_bits);
1654 spin_unlock_irqrestore(&dev->condlock, flags);
1655 }
1656 s5p_mfc_try_run(dev);
1657 return 0;
1658}
1659
1660static int s5p_mfc_stop_streaming(struct vb2_queue *q)
1661{
1662 unsigned long flags;
1663 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
1664 struct s5p_mfc_dev *dev = ctx->dev;
1665
1666 if ((ctx->state == MFCINST_FINISHING ||
1667 ctx->state == MFCINST_RUNNING) &&
1668 dev->curr_ctx == ctx->num && dev->hw_lock) {
1669 ctx->state = MFCINST_ABORT;
1670 s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
1671 0);
1672 }
1673 ctx->state = MFCINST_FINISHED;
1674 spin_lock_irqsave(&dev->irqlock, flags);
1675 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1676 s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
1677 INIT_LIST_HEAD(&ctx->dst_queue);
1678 ctx->dst_queue_cnt = 0;
1679 }
1680 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1681 cleanup_ref_queue(ctx);
1682 s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
1683 INIT_LIST_HEAD(&ctx->src_queue);
1684 ctx->src_queue_cnt = 0;
1685 }
1686 spin_unlock_irqrestore(&dev->irqlock, flags);
1687 return 0;
1688}
1689
1690static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
1691{
1692 struct vb2_queue *vq = vb->vb2_queue;
1693 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
1694 struct s5p_mfc_dev *dev = ctx->dev;
1695 unsigned long flags;
1696 struct s5p_mfc_buf *mfc_buf;
1697
1698 if (ctx->state == MFCINST_ERROR) {
1699 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
1700 cleanup_ref_queue(ctx);
1701 return;
1702 }
1703 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1704 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
1705 mfc_buf->used = 0;
1706 /* Mark destination as available for use by MFC */
1707 spin_lock_irqsave(&dev->irqlock, flags);
1708 list_add_tail(&mfc_buf->list, &ctx->dst_queue);
1709 ctx->dst_queue_cnt++;
1710 spin_unlock_irqrestore(&dev->irqlock, flags);
1711 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1712 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
1713 mfc_buf->used = 0;
1714 spin_lock_irqsave(&dev->irqlock, flags);
1715 if (vb->v4l2_planes[0].bytesused == 0) {
1716 mfc_debug(1, "change state to FINISHING\n");
1717 ctx->state = MFCINST_FINISHING;
1718 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
1719 cleanup_ref_queue(ctx);
1720 } else {
1721 list_add_tail(&mfc_buf->list, &ctx->src_queue);
1722 ctx->src_queue_cnt++;
1723 }
1724 spin_unlock_irqrestore(&dev->irqlock, flags);
1725 } else {
1726 mfc_err("unsupported buffer type (%d)\n", vq->type);
1727 }
1728 if (s5p_mfc_ctx_ready(ctx)) {
1729 spin_lock_irqsave(&dev->condlock, flags);
1730 set_bit(ctx->num, &dev->ctx_work_bits);
1731 spin_unlock_irqrestore(&dev->condlock, flags);
1732 }
1733 s5p_mfc_try_run(dev);
1734}
1735
1736static struct vb2_ops s5p_mfc_enc_qops = {
1737 .queue_setup = s5p_mfc_queue_setup,
1738 .wait_prepare = s5p_mfc_unlock,
1739 .wait_finish = s5p_mfc_lock,
1740 .buf_init = s5p_mfc_buf_init,
1741 .buf_prepare = s5p_mfc_buf_prepare,
1742 .start_streaming = s5p_mfc_start_streaming,
1743 .stop_streaming = s5p_mfc_stop_streaming,
1744 .buf_queue = s5p_mfc_buf_queue,
1745};
1746
1747struct s5p_mfc_codec_ops *get_enc_codec_ops(void)
1748{
1749 return &encoder_codec_ops;
1750}
1751
1752struct vb2_ops *get_enc_queue_ops(void)
1753{
1754 return &s5p_mfc_enc_qops;
1755}
1756
1757const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void)
1758{
1759 return &s5p_mfc_enc_ioctl_ops;
1760}
1761
1762#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \
1763 && V4L2_CTRL_DRIVER_PRIV(x))
1764
1765int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
1766{
1767 struct v4l2_ctrl_config cfg;
1768 int i;
1769
1770 v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
1771 if (ctx->ctrl_handler.error) {
1772 mfc_err("v4l2_ctrl_handler_init failed\n");
1773 return ctx->ctrl_handler.error;
1774 }
1775 for (i = 0; i < NUM_CTRLS; i++) {
1776 if (IS_MFC51_PRIV(controls[i].id)) {
1777 cfg.ops = &s5p_mfc_enc_ctrl_ops;
1778 cfg.id = controls[i].id;
1779 cfg.min = controls[i].minimum;
1780 cfg.max = controls[i].maximum;
1781 cfg.def = controls[i].default_value;
1782 cfg.name = controls[i].name;
1783 cfg.type = controls[i].type;
1784 cfg.flags = 0;
1785
1786 if (cfg.type == V4L2_CTRL_TYPE_MENU) {
1787 cfg.step = 0;
1788 cfg.menu_skip_mask = cfg.menu_skip_mask;
1789 cfg.qmenu = mfc51_get_menu(cfg.id);
1790 } else {
1791 cfg.step = controls[i].step;
1792 cfg.menu_skip_mask = 0;
1793 }
1794 ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
1795 &cfg, NULL);
1796 } else {
1797 if (controls[i].type == V4L2_CTRL_TYPE_MENU) {
1798 ctx->ctrls[i] = v4l2_ctrl_new_std_menu(
1799 &ctx->ctrl_handler,
1800 &s5p_mfc_enc_ctrl_ops, controls[i].id,
1801 controls[i].maximum, 0,
1802 controls[i].default_value);
1803 } else {
1804 ctx->ctrls[i] = v4l2_ctrl_new_std(
1805 &ctx->ctrl_handler,
1806 &s5p_mfc_enc_ctrl_ops, controls[i].id,
1807 controls[i].minimum,
1808 controls[i].maximum, controls[i].step,
1809 controls[i].default_value);
1810 }
1811 }
1812 if (ctx->ctrl_handler.error) {
1813 mfc_err("Adding control (%d) failed\n", i);
1814 return ctx->ctrl_handler.error;
1815 }
1816 if (controls[i].is_volatile && ctx->ctrls[i])
1817 ctx->ctrls[i]->is_volatile = 1;
1818 }
1819 return 0;
1820}
1821
1822void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
1823{
1824 int i;
1825
1826 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1827 for (i = 0; i < NUM_CTRLS; i++)
1828 ctx->ctrls[i] = NULL;
1829}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
new file mode 100644
index 000000000000..405bdd3ee083
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
@@ -0,0 +1,23 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_ENC_H_
14#define S5P_MFC_ENC_H_
15
16struct s5p_mfc_codec_ops *get_enc_codec_ops(void);
17struct vb2_ops *get_enc_queue_ops(void);
18const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
19struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
20int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
21void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
22
23#endif /* S5P_MFC_ENC_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
new file mode 100644
index 000000000000..8f2f8bf4da7f
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
@@ -0,0 +1,92 @@
1/*
2 * drivers/media/video/samsung/mfc5/s5p_mfc_intr.c
3 *
4 * C file for Samsung MFC (Multi Function Codec - FIMV) driver
5 * This file contains functions used to wait for command completion.
6 *
7 * Kamil Debski, Copyright (C) 2011 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#include <linux/delay.h>
16#include <linux/errno.h>
17#include <linux/io.h>
18#include <linux/sched.h>
19#include <linux/wait.h>
20#include "regs-mfc.h"
21#include "s5p_mfc_common.h"
22#include "s5p_mfc_debug.h"
23#include "s5p_mfc_intr.h"
24
25int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
26{
27 int ret;
28
29 ret = wait_event_interruptible_timeout(dev->queue,
30 (dev->int_cond && (dev->int_type == command
31 || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
32 msecs_to_jiffies(MFC_INT_TIMEOUT));
33 if (ret == 0) {
34 mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
35 dev->int_type, command);
36 return 1;
37 } else if (ret == -ERESTARTSYS) {
38 mfc_err("Interrupted by a signal\n");
39 return 1;
40 }
41 mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
42 dev->int_type, command);
43 if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
44 return 1;
45 return 0;
46}
47
48void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
49{
50 dev->int_cond = 0;
51 dev->int_type = 0;
52 dev->int_err = 0;
53}
54
55int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
56 int command, int interrupt)
57{
58 int ret;
59
60 if (interrupt) {
61 ret = wait_event_interruptible_timeout(ctx->queue,
62 (ctx->int_cond && (ctx->int_type == command
63 || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
64 msecs_to_jiffies(MFC_INT_TIMEOUT));
65 } else {
66 ret = wait_event_timeout(ctx->queue,
67 (ctx->int_cond && (ctx->int_type == command
68 || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
69 msecs_to_jiffies(MFC_INT_TIMEOUT));
70 }
71 if (ret == 0) {
72 mfc_err("Interrupt (ctx->int_type:%d, command:%d) timed out\n",
73 ctx->int_type, command);
74 return 1;
75 } else if (ret == -ERESTARTSYS) {
76 mfc_err("Interrupted by a signal\n");
77 return 1;
78 }
79 mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
80 ctx->int_type, command);
81 if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
82 return 1;
83 return 0;
84}
85
86void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
87{
88 ctx->int_cond = 0;
89 ctx->int_type = 0;
90 ctx->int_err = 0;
91}
92
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.h b/drivers/media/video/s5p-mfc/s5p_mfc_intr.h
new file mode 100644
index 000000000000..122d7732f745
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.h
@@ -0,0 +1,26 @@
1/*
2 * drivers/media/video/samsung/mfc5/s5p_mfc_intr.h
3 *
4 * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
5 * It contains waiting functions declarations.
6 *
7 * Kamil Debski, Copyright (C) 2011 Samsung Electronics
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#ifndef S5P_MFC_INTR_H_
16#define S5P_MFC_INTR_H_
17
18#include "s5p_mfc_common.h"
19
20int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
21 int command, int interrupt);
22int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
23void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx);
24void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev);
25
26#endif /* S5P_MFC_INTR_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
new file mode 100644
index 000000000000..7b239168c199
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
@@ -0,0 +1,1397 @@
1/*
2 * drivers/media/video/samsung/mfc5/s5p_mfc_opr.c
3 *
4 * Samsung MFC (Multi Function Codec - FIMV) driver
5 * This file contains hw related functions.
6 *
7 * Kamil Debski, Copyright (c) 2011 Samsung Electronics
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#include "regs-mfc.h"
16#include "s5p_mfc_cmd.h"
17#include "s5p_mfc_common.h"
18#include "s5p_mfc_ctrl.h"
19#include "s5p_mfc_debug.h"
20#include "s5p_mfc_intr.h"
21#include "s5p_mfc_opr.h"
22#include "s5p_mfc_pm.h"
23#include "s5p_mfc_shm.h"
24#include <asm/cacheflush.h>
25#include <linux/delay.h>
26#include <linux/dma-mapping.h>
27#include <linux/err.h>
28#include <linux/firmware.h>
29#include <linux/io.h>
30#include <linux/jiffies.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33
34#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
35#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
36
37/* Allocate temporary buffers for decoding */
38int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
39{
40 void *desc_virt;
41 struct s5p_mfc_dev *dev = ctx->dev;
42
43 ctx->desc_buf = vb2_dma_contig_memops.alloc(
44 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
45 if (IS_ERR_VALUE((int)ctx->desc_buf)) {
46 ctx->desc_buf = 0;
47 mfc_err("Allocating DESC buffer failed\n");
48 return -ENOMEM;
49 }
50 ctx->desc_phys = s5p_mfc_mem_cookie(
51 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
52 BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
53 desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
54 if (desc_virt == NULL) {
55 vb2_dma_contig_memops.put(ctx->desc_buf);
56 ctx->desc_phys = 0;
57 ctx->desc_buf = 0;
58 mfc_err("Remapping DESC buffer failed\n");
59 return -ENOMEM;
60 }
61 memset(desc_virt, 0, DESC_BUF_SIZE);
62 wmb();
63 return 0;
64}
65
66/* Release temporary buffers for decoding */
67void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
68{
69 if (ctx->desc_phys) {
70 vb2_dma_contig_memops.put(ctx->desc_buf);
71 ctx->desc_phys = 0;
72 ctx->desc_buf = 0;
73 }
74}
75
76/* Allocate codec buffers */
77int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
78{
79 struct s5p_mfc_dev *dev = ctx->dev;
80 unsigned int enc_ref_y_size = 0;
81 unsigned int enc_ref_c_size = 0;
82 unsigned int guard_width, guard_height;
83
84 if (ctx->type == MFCINST_DECODER) {
85 mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
86 ctx->luma_size, ctx->chroma_size, ctx->mv_size);
87 mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
88 } else if (ctx->type == MFCINST_ENCODER) {
89 enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
90 * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
91 enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
92
93 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
94 enc_ref_c_size = ALIGN(ctx->img_width,
95 S5P_FIMV_NV12MT_HALIGN)
96 * ALIGN(ctx->img_height >> 1,
97 S5P_FIMV_NV12MT_VALIGN);
98 enc_ref_c_size = ALIGN(enc_ref_c_size,
99 S5P_FIMV_NV12MT_SALIGN);
100 } else {
101 guard_width = ALIGN(ctx->img_width + 16,
102 S5P_FIMV_NV12MT_HALIGN);
103 guard_height = ALIGN((ctx->img_height >> 1) + 4,
104 S5P_FIMV_NV12MT_VALIGN);
105 enc_ref_c_size = ALIGN(guard_width * guard_height,
106 S5P_FIMV_NV12MT_SALIGN);
107 }
108 mfc_debug(2, "recon luma size: %d chroma size: %d\n",
109 enc_ref_y_size, enc_ref_c_size);
110 } else {
111 return -EINVAL;
112 }
113 /* Codecs have different memory requirements */
114 switch (ctx->codec_mode) {
115 case S5P_FIMV_CODEC_H264_DEC:
116 ctx->bank1_size =
117 ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
118 S5P_FIMV_DEC_VERT_NB_MV_SIZE,
119 S5P_FIMV_DEC_BUF_ALIGN);
120 ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
121 break;
122 case S5P_FIMV_CODEC_MPEG4_DEC:
123 ctx->bank1_size =
124 ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
125 S5P_FIMV_DEC_UPNB_MV_SIZE +
126 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
127 S5P_FIMV_DEC_STX_PARSER_SIZE +
128 S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
129 S5P_FIMV_DEC_BUF_ALIGN);
130 ctx->bank2_size = 0;
131 break;
132 case S5P_FIMV_CODEC_VC1RCV_DEC:
133 case S5P_FIMV_CODEC_VC1_DEC:
134 ctx->bank1_size =
135 ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
136 S5P_FIMV_DEC_UPNB_MV_SIZE +
137 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
138 S5P_FIMV_DEC_NB_DCAC_SIZE +
139 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
140 S5P_FIMV_DEC_BUF_ALIGN);
141 ctx->bank2_size = 0;
142 break;
143 case S5P_FIMV_CODEC_MPEG2_DEC:
144 ctx->bank1_size = 0;
145 ctx->bank2_size = 0;
146 break;
147 case S5P_FIMV_CODEC_H263_DEC:
148 ctx->bank1_size =
149 ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
150 S5P_FIMV_DEC_UPNB_MV_SIZE +
151 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
152 S5P_FIMV_DEC_NB_DCAC_SIZE,
153 S5P_FIMV_DEC_BUF_ALIGN);
154 ctx->bank2_size = 0;
155 break;
156 case S5P_FIMV_CODEC_H264_ENC:
157 ctx->bank1_size = (enc_ref_y_size * 2) +
158 S5P_FIMV_ENC_UPMV_SIZE +
159 S5P_FIMV_ENC_COLFLG_SIZE +
160 S5P_FIMV_ENC_INTRAMD_SIZE +
161 S5P_FIMV_ENC_NBORINFO_SIZE;
162 ctx->bank2_size = (enc_ref_y_size * 2) +
163 (enc_ref_c_size * 4) +
164 S5P_FIMV_ENC_INTRAPRED_SIZE;
165 break;
166 case S5P_FIMV_CODEC_MPEG4_ENC:
167 ctx->bank1_size = (enc_ref_y_size * 2) +
168 S5P_FIMV_ENC_UPMV_SIZE +
169 S5P_FIMV_ENC_COLFLG_SIZE +
170 S5P_FIMV_ENC_ACDCCOEF_SIZE;
171 ctx->bank2_size = (enc_ref_y_size * 2) +
172 (enc_ref_c_size * 4);
173 break;
174 case S5P_FIMV_CODEC_H263_ENC:
175 ctx->bank1_size = (enc_ref_y_size * 2) +
176 S5P_FIMV_ENC_UPMV_SIZE +
177 S5P_FIMV_ENC_ACDCCOEF_SIZE;
178 ctx->bank2_size = (enc_ref_y_size * 2) +
179 (enc_ref_c_size * 4);
180 break;
181 default:
182 break;
183 }
184 /* Allocate only if memory from bank 1 is necessary */
185 if (ctx->bank1_size > 0) {
186 ctx->bank1_buf = vb2_dma_contig_memops.alloc(
187 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
188 if (IS_ERR(ctx->bank1_buf)) {
189 ctx->bank1_buf = 0;
190 printk(KERN_ERR
191 "Buf alloc for decoding failed (port A)\n");
192 return -ENOMEM;
193 }
194 ctx->bank1_phys = s5p_mfc_mem_cookie(
195 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
196 BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
197 }
198 /* Allocate only if memory from bank 2 is necessary */
199 if (ctx->bank2_size > 0) {
200 ctx->bank2_buf = vb2_dma_contig_memops.alloc(
201 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
202 if (IS_ERR(ctx->bank2_buf)) {
203 ctx->bank2_buf = 0;
204 mfc_err("Buf alloc for decoding failed (port B)\n");
205 return -ENOMEM;
206 }
207 ctx->bank2_phys = s5p_mfc_mem_cookie(
208 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
209 BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
210 }
211 return 0;
212}
213
214/* Release buffers allocated for codec */
215void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
216{
217 if (ctx->bank1_buf) {
218 vb2_dma_contig_memops.put(ctx->bank1_buf);
219 ctx->bank1_buf = 0;
220 ctx->bank1_phys = 0;
221 ctx->bank1_size = 0;
222 }
223 if (ctx->bank2_buf) {
224 vb2_dma_contig_memops.put(ctx->bank2_buf);
225 ctx->bank2_buf = 0;
226 ctx->bank2_phys = 0;
227 ctx->bank2_size = 0;
228 }
229}
230
231/* Allocate memory for instance data buffer */
232int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
233{
234 void *context_virt;
235 struct s5p_mfc_dev *dev = ctx->dev;
236
237 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
238 ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
239 ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
240 else
241 ctx->ctx_size = MFC_CTX_BUF_SIZE;
242 ctx->ctx_buf = vb2_dma_contig_memops.alloc(
243 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
244 if (IS_ERR(ctx->ctx_buf)) {
245 mfc_err("Allocating context buffer failed\n");
246 ctx->ctx_phys = 0;
247 ctx->ctx_buf = 0;
248 return -ENOMEM;
249 }
250 ctx->ctx_phys = s5p_mfc_mem_cookie(
251 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
252 BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
253 ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
254 context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
255 if (context_virt == NULL) {
256 mfc_err("Remapping instance buffer failed\n");
257 vb2_dma_contig_memops.put(ctx->ctx_buf);
258 ctx->ctx_phys = 0;
259 ctx->ctx_buf = 0;
260 return -ENOMEM;
261 }
262 /* Zero content of the allocated memory */
263 memset(context_virt, 0, ctx->ctx_size);
264 wmb();
265 if (s5p_mfc_init_shm(ctx) < 0) {
266 vb2_dma_contig_memops.put(ctx->ctx_buf);
267 ctx->ctx_phys = 0;
268 ctx->ctx_buf = 0;
269 return -ENOMEM;
270 }
271 return 0;
272}
273
274/* Release instance buffer */
275void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
276{
277 if (ctx->ctx_buf) {
278 vb2_dma_contig_memops.put(ctx->ctx_buf);
279 ctx->ctx_phys = 0;
280 ctx->ctx_buf = 0;
281 }
282 if (ctx->shm_alloc) {
283 vb2_dma_contig_memops.put(ctx->shm_alloc);
284 ctx->shm_alloc = 0;
285 ctx->shm = 0;
286 }
287}
288
289/* Set registers for decoding temporary buffers */
290void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
291{
292 struct s5p_mfc_dev *dev = ctx->dev;
293
294 mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
295 mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
296}
297
298/* Set registers for shared buffer */
299void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
300{
301 struct s5p_mfc_dev *dev = ctx->dev;
302 mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
303}
304
305/* Set registers for decoding stream buffer */
306int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
307 unsigned int start_num_byte, unsigned int buf_size)
308{
309 struct s5p_mfc_dev *dev = ctx->dev;
310
311 mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
312 mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
313 mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
314 s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
315 return 0;
316}
317
318/* Set decoding frame buffer */
319int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
320{
321 unsigned int frame_size, i;
322 unsigned int frame_size_ch, frame_size_mv;
323 struct s5p_mfc_dev *dev = ctx->dev;
324 unsigned int dpb;
325 size_t buf_addr1, buf_addr2;
326 int buf_size1, buf_size2;
327
328 buf_addr1 = ctx->bank1_phys;
329 buf_size1 = ctx->bank1_size;
330 buf_addr2 = ctx->bank2_phys;
331 buf_size2 = ctx->bank2_size;
332 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
333 ~S5P_FIMV_DPB_COUNT_MASK;
334 mfc_write(dev, ctx->total_dpb_count | dpb,
335 S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
336 s5p_mfc_set_shared_buffer(ctx);
337 switch (ctx->codec_mode) {
338 case S5P_FIMV_CODEC_H264_DEC:
339 mfc_write(dev, OFFSETA(buf_addr1),
340 S5P_FIMV_H264_VERT_NB_MV_ADR);
341 buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
342 buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
343 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
344 buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
345 buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
346 break;
347 case S5P_FIMV_CODEC_MPEG4_DEC:
348 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
349 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
350 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
351 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
352 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
353 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
354 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
355 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
356 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
357 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
358 buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
359 buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
360 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
361 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
362 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
363 break;
364 case S5P_FIMV_CODEC_H263_DEC:
365 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
366 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
367 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
368 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
369 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
370 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
371 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
372 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
373 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
374 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
375 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
376 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
377 break;
378 case S5P_FIMV_CODEC_VC1_DEC:
379 case S5P_FIMV_CODEC_VC1RCV_DEC:
380 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
381 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
382 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
383 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
384 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
385 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
386 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
387 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
388 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
389 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
390 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
391 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
392 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
393 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
394 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
395 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
396 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
397 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
398 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
399 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
400 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
401 break;
402 case S5P_FIMV_CODEC_MPEG2_DEC:
403 break;
404 default:
405 mfc_err("Unknown codec for decoding (%x)\n",
406 ctx->codec_mode);
407 return -EINVAL;
408 break;
409 }
410 frame_size = ctx->luma_size;
411 frame_size_ch = ctx->chroma_size;
412 frame_size_mv = ctx->mv_size;
413 mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
414 frame_size_mv);
415 for (i = 0; i < ctx->total_dpb_count; i++) {
416 /* Bank2 */
417 mfc_debug(2, "Luma %d: %x\n", i,
418 ctx->dst_bufs[i].cookie.raw.luma);
419 mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
420 S5P_FIMV_DEC_LUMA_ADR + i * 4);
421 mfc_debug(2, "\tChroma %d: %x\n", i,
422 ctx->dst_bufs[i].cookie.raw.chroma);
423 mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
424 S5P_FIMV_DEC_CHROMA_ADR + i * 4);
425 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
426 mfc_debug(2, "\tBuf2: %x, size: %d\n",
427 buf_addr2, buf_size2);
428 mfc_write(dev, OFFSETB(buf_addr2),
429 S5P_FIMV_H264_MV_ADR + i * 4);
430 buf_addr2 += frame_size_mv;
431 buf_size2 -= frame_size_mv;
432 }
433 }
434 mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
435 mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
436 buf_size1, buf_size2, ctx->total_dpb_count);
437 if (buf_size1 < 0 || buf_size2 < 0) {
438 mfc_debug(2, "Not enough memory has been allocated\n");
439 return -ENOMEM;
440 }
441 s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
442 s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
443 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
444 s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
445 mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
446 << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
447 S5P_FIMV_SI_CH0_INST_ID);
448 return 0;
449}
450
451/* Set registers for encoding stream buffer */
452int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
453 unsigned long addr, unsigned int size)
454{
455 struct s5p_mfc_dev *dev = ctx->dev;
456
457 mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
458 mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
459 return 0;
460}
461
462void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
463 unsigned long y_addr, unsigned long c_addr)
464{
465 struct s5p_mfc_dev *dev = ctx->dev;
466
467 mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
468 mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
469}
470
471void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
472 unsigned long *y_addr, unsigned long *c_addr)
473{
474 struct s5p_mfc_dev *dev = ctx->dev;
475
476 *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
477 << MFC_OFFSET_SHIFT);
478 *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
479 << MFC_OFFSET_SHIFT);
480}
481
482/* Set encoding ref & codec buffer */
483int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
484{
485 struct s5p_mfc_dev *dev = ctx->dev;
486 size_t buf_addr1, buf_addr2;
487 size_t buf_size1, buf_size2;
488 unsigned int enc_ref_y_size, enc_ref_c_size;
489 unsigned int guard_width, guard_height;
490 int i;
491
492 buf_addr1 = ctx->bank1_phys;
493 buf_size1 = ctx->bank1_size;
494 buf_addr2 = ctx->bank2_phys;
495 buf_size2 = ctx->bank2_size;
496 enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
497 * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
498 enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
499 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
500 enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
501 * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
502 enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
503 } else {
504 guard_width = ALIGN(ctx->img_width + 16,
505 S5P_FIMV_NV12MT_HALIGN);
506 guard_height = ALIGN((ctx->img_height >> 1) + 4,
507 S5P_FIMV_NV12MT_VALIGN);
508 enc_ref_c_size = ALIGN(guard_width * guard_height,
509 S5P_FIMV_NV12MT_SALIGN);
510 }
511 mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
512 switch (ctx->codec_mode) {
513 case S5P_FIMV_CODEC_H264_ENC:
514 for (i = 0; i < 2; i++) {
515 mfc_write(dev, OFFSETA(buf_addr1),
516 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
517 buf_addr1 += enc_ref_y_size;
518 buf_size1 -= enc_ref_y_size;
519
520 mfc_write(dev, OFFSETB(buf_addr2),
521 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
522 buf_addr2 += enc_ref_y_size;
523 buf_size2 -= enc_ref_y_size;
524 }
525 for (i = 0; i < 4; i++) {
526 mfc_write(dev, OFFSETB(buf_addr2),
527 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
528 buf_addr2 += enc_ref_c_size;
529 buf_size2 -= enc_ref_c_size;
530 }
531 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
532 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
533 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
534 mfc_write(dev, OFFSETA(buf_addr1),
535 S5P_FIMV_H264_COZERO_FLAG_ADR);
536 buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
537 buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
538 mfc_write(dev, OFFSETA(buf_addr1),
539 S5P_FIMV_H264_UP_INTRA_MD_ADR);
540 buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
541 buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
542 mfc_write(dev, OFFSETB(buf_addr2),
543 S5P_FIMV_H264_UP_INTRA_PRED_ADR);
544 buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
545 buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
546 mfc_write(dev, OFFSETA(buf_addr1),
547 S5P_FIMV_H264_NBOR_INFO_ADR);
548 buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
549 buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
550 mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
551 buf_size1, buf_size2);
552 break;
553 case S5P_FIMV_CODEC_MPEG4_ENC:
554 for (i = 0; i < 2; i++) {
555 mfc_write(dev, OFFSETA(buf_addr1),
556 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
557 buf_addr1 += enc_ref_y_size;
558 buf_size1 -= enc_ref_y_size;
559 mfc_write(dev, OFFSETB(buf_addr2),
560 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
561 buf_addr2 += enc_ref_y_size;
562 buf_size2 -= enc_ref_y_size;
563 }
564 for (i = 0; i < 4; i++) {
565 mfc_write(dev, OFFSETB(buf_addr2),
566 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
567 buf_addr2 += enc_ref_c_size;
568 buf_size2 -= enc_ref_c_size;
569 }
570 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
571 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
572 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
573 mfc_write(dev, OFFSETA(buf_addr1),
574 S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
575 buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
576 buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
577 mfc_write(dev, OFFSETA(buf_addr1),
578 S5P_FIMV_MPEG4_ACDC_COEF_ADR);
579 buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
580 buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
581 mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
582 buf_size1, buf_size2);
583 break;
584 case S5P_FIMV_CODEC_H263_ENC:
585 for (i = 0; i < 2; i++) {
586 mfc_write(dev, OFFSETA(buf_addr1),
587 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
588 buf_addr1 += enc_ref_y_size;
589 buf_size1 -= enc_ref_y_size;
590 mfc_write(dev, OFFSETB(buf_addr2),
591 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
592 buf_addr2 += enc_ref_y_size;
593 buf_size2 -= enc_ref_y_size;
594 }
595 for (i = 0; i < 4; i++) {
596 mfc_write(dev, OFFSETB(buf_addr2),
597 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
598 buf_addr2 += enc_ref_c_size;
599 buf_size2 -= enc_ref_c_size;
600 }
601 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
602 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
603 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
604 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
605 buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
606 buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
607 mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
608 buf_size1, buf_size2);
609 break;
610 default:
611 mfc_err("Unknown codec set for encoding: %d\n",
612 ctx->codec_mode);
613 return -EINVAL;
614 }
615 return 0;
616}
617
618static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
619{
620 struct s5p_mfc_dev *dev = ctx->dev;
621 struct s5p_mfc_enc_params *p = &ctx->enc_params;
622 unsigned int reg;
623 unsigned int shm;
624
625 /* width */
626 mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
627 /* height */
628 mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
629 /* pictype : enable, IDR period */
630 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
631 reg |= (1 << 18);
632 reg &= ~(0xFFFF);
633 reg |= p->gop_size;
634 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
635 mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
636 /* multi-slice control */
637 /* multi-slice MB number or bit size */
638 mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
639 if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
640 mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
641 } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
642 mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
643 } else {
644 mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
645 mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
646 }
647 /* cyclic intra refresh */
648 mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
649 /* memory structure cur. frame */
650 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
651 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
652 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
653 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
654 /* padding control & value */
655 reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
656 if (p->pad) {
657 /** enable */
658 reg |= (1 << 31);
659 /** cr value */
660 reg &= ~(0xFF << 16);
661 reg |= (p->pad_cr << 16);
662 /** cb value */
663 reg &= ~(0xFF << 8);
664 reg |= (p->pad_cb << 8);
665 /** y value */
666 reg &= ~(0xFF);
667 reg |= (p->pad_luma);
668 } else {
669 /** disable & all value clear */
670 reg = 0;
671 }
672 mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
673 /* rate control config. */
674 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
675 /** frame-level rate control */
676 reg &= ~(0x1 << 9);
677 reg |= (p->rc_frame << 9);
678 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
679 /* bit rate */
680 if (p->rc_frame)
681 mfc_write(dev, p->rc_bitrate,
682 S5P_FIMV_ENC_RC_BIT_RATE);
683 else
684 mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
685 /* reaction coefficient */
686 if (p->rc_frame)
687 mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
688 shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
689 /* seq header ctrl */
690 shm &= ~(0x1 << 3);
691 shm |= (p->seq_hdr_mode << 3);
692 /* frame skip mode */
693 shm &= ~(0x3 << 1);
694 shm |= (p->frame_skip_mode << 1);
695 s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
696 /* fixed target bit */
697 s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
698 return 0;
699}
700
701static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
702{
703 struct s5p_mfc_dev *dev = ctx->dev;
704 struct s5p_mfc_enc_params *p = &ctx->enc_params;
705 struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
706 unsigned int reg;
707 unsigned int shm;
708
709 s5p_mfc_set_enc_params(ctx);
710 /* pictype : number of B */
711 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
712 /* num_b_frame - 0 ~ 2 */
713 reg &= ~(0x3 << 16);
714 reg |= (p->num_b_frame << 16);
715 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
716 /* profile & level */
717 reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
718 /* level */
719 reg &= ~(0xFF << 8);
720 reg |= (p_264->level << 8);
721 /* profile - 0 ~ 2 */
722 reg &= ~(0x3F);
723 reg |= p_264->profile;
724 mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
725 /* interlace */
726 mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
727 /* height */
728 if (p->interlace)
729 mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
730 /* loopfilter ctrl */
731 mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
732 /* loopfilter alpha offset */
733 if (p_264->loop_filter_alpha < 0) {
734 reg = 0x10;
735 reg |= (0xFF - p_264->loop_filter_alpha) + 1;
736 } else {
737 reg = 0x00;
738 reg |= (p_264->loop_filter_alpha & 0xF);
739 }
740 mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
741 /* loopfilter beta offset */
742 if (p_264->loop_filter_beta < 0) {
743 reg = 0x10;
744 reg |= (0xFF - p_264->loop_filter_beta) + 1;
745 } else {
746 reg = 0x00;
747 reg |= (p_264->loop_filter_beta & 0xF);
748 }
749 mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
750 /* entropy coding mode */
751 if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
752 mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
753 else
754 mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
755 /* number of ref. picture */
756 reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
757 /* num of ref. pictures of P */
758 reg &= ~(0x3 << 5);
759 reg |= (p_264->num_ref_pic_4p << 5);
760 /* max number of ref. pictures */
761 reg &= ~(0x1F);
762 reg |= p_264->max_ref_pic;
763 mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
764 /* 8x8 transform enable */
765 mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
766 /* rate control config. */
767 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
768 /* macroblock level rate control */
769 reg &= ~(0x1 << 8);
770 reg |= (p_264->rc_mb << 8);
771 /* frame QP */
772 reg &= ~(0x3F);
773 reg |= p_264->rc_frame_qp;
774 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
775 /* frame rate */
776 if (p->rc_frame && p->rc_framerate_denom)
777 mfc_write(dev, p->rc_framerate_num * 1000
778 / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
779 else
780 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
781 /* max & min value of QP */
782 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
783 /* max QP */
784 reg &= ~(0x3F << 8);
785 reg |= (p_264->rc_max_qp << 8);
786 /* min QP */
787 reg &= ~(0x3F);
788 reg |= p_264->rc_min_qp;
789 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
790 /* macroblock adaptive scaling features */
791 if (p_264->rc_mb) {
792 reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
793 /* dark region */
794 reg &= ~(0x1 << 3);
795 reg |= (p_264->rc_mb_dark << 3);
796 /* smooth region */
797 reg &= ~(0x1 << 2);
798 reg |= (p_264->rc_mb_smooth << 2);
799 /* static region */
800 reg &= ~(0x1 << 1);
801 reg |= (p_264->rc_mb_static << 1);
802 /* high activity region */
803 reg &= ~(0x1);
804 reg |= p_264->rc_mb_activity;
805 mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
806 }
807 if (!p->rc_frame &&
808 !p_264->rc_mb) {
809 shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
810 shm &= ~(0xFFF);
811 shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
812 shm |= (p_264->rc_p_frame_qp & 0x3F);
813 s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
814 }
815 /* extended encoder ctrl */
816 shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
817 /* AR VUI control */
818 shm &= ~(0x1 << 15);
819 shm |= (p_264->vui_sar << 1);
820 s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
821 if (p_264->vui_sar) {
822 /* aspect ration IDC */
823 shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
824 shm &= ~(0xFF);
825 shm |= p_264->vui_sar_idc;
826 s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
827 if (p_264->vui_sar_idc == 0xFF) {
828 /* sample AR info */
829 shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
830 shm &= ~(0xFFFFFFFF);
831 shm |= p_264->vui_ext_sar_width << 16;
832 shm |= p_264->vui_ext_sar_height;
833 s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
834 }
835 }
836 /* intra picture period for H.264 */
837 shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
838 /* control */
839 shm &= ~(0x1 << 16);
840 shm |= (p_264->open_gop << 16);
841 /* value */
842 if (p_264->open_gop) {
843 shm &= ~(0xFFFF);
844 shm |= p_264->open_gop_size;
845 }
846 s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
847 /* extended encoder ctrl */
848 shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
849 /* vbv buffer size */
850 if (p->frame_skip_mode ==
851 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
852 shm &= ~(0xFFFF << 16);
853 shm |= (p_264->cpb_size << 16);
854 }
855 s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
856 return 0;
857}
858
859static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
860{
861 struct s5p_mfc_dev *dev = ctx->dev;
862 struct s5p_mfc_enc_params *p = &ctx->enc_params;
863 struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
864 unsigned int reg;
865 unsigned int shm;
866 unsigned int framerate;
867
868 s5p_mfc_set_enc_params(ctx);
869 /* pictype : number of B */
870 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
871 /* num_b_frame - 0 ~ 2 */
872 reg &= ~(0x3 << 16);
873 reg |= (p->num_b_frame << 16);
874 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
875 /* profile & level */
876 reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
877 /* level */
878 reg &= ~(0xFF << 8);
879 reg |= (p_mpeg4->level << 8);
880 /* profile - 0 ~ 2 */
881 reg &= ~(0x3F);
882 reg |= p_mpeg4->profile;
883 mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
884 /* quarter_pixel */
885 mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
886 /* qp */
887 if (!p->rc_frame) {
888 shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
889 shm &= ~(0xFFF);
890 shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
891 shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
892 s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
893 }
894 /* frame rate */
895 if (p->rc_frame) {
896 if (p->rc_framerate_denom > 0) {
897 framerate = p->rc_framerate_num * 1000 /
898 p->rc_framerate_denom;
899 mfc_write(dev, framerate,
900 S5P_FIMV_ENC_RC_FRAME_RATE);
901 shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
902 shm &= ~(0xFFFFFFFF);
903 shm |= (1 << 31);
904 shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
905 shm |= (p->rc_framerate_denom & 0xFFFF);
906 s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
907 }
908 } else {
909 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
910 }
911 /* rate control config. */
912 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
913 /* frame QP */
914 reg &= ~(0x3F);
915 reg |= p_mpeg4->rc_frame_qp;
916 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
917 /* max & min value of QP */
918 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
919 /* max QP */
920 reg &= ~(0x3F << 8);
921 reg |= (p_mpeg4->rc_max_qp << 8);
922 /* min QP */
923 reg &= ~(0x3F);
924 reg |= p_mpeg4->rc_min_qp;
925 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
926 /* extended encoder ctrl */
927 shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
928 /* vbv buffer size */
929 if (p->frame_skip_mode ==
930 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
931 shm &= ~(0xFFFF << 16);
932 shm |= (p->vbv_size << 16);
933 }
934 s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
935 return 0;
936}
937
938static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
939{
940 struct s5p_mfc_dev *dev = ctx->dev;
941 struct s5p_mfc_enc_params *p = &ctx->enc_params;
942 struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
943 unsigned int reg;
944 unsigned int shm;
945
946 s5p_mfc_set_enc_params(ctx);
947 /* qp */
948 if (!p->rc_frame) {
949 shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
950 shm &= ~(0xFFF);
951 shm |= (p_h263->rc_p_frame_qp & 0x3F);
952 s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
953 }
954 /* frame rate */
955 if (p->rc_frame && p->rc_framerate_denom)
956 mfc_write(dev, p->rc_framerate_num * 1000
957 / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
958 else
959 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
960 /* rate control config. */
961 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
962 /* frame QP */
963 reg &= ~(0x3F);
964 reg |= p_h263->rc_frame_qp;
965 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
966 /* max & min value of QP */
967 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
968 /* max QP */
969 reg &= ~(0x3F << 8);
970 reg |= (p_h263->rc_max_qp << 8);
971 /* min QP */
972 reg &= ~(0x3F);
973 reg |= p_h263->rc_min_qp;
974 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
975 /* extended encoder ctrl */
976 shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
977 /* vbv buffer size */
978 if (p->frame_skip_mode ==
979 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
980 shm &= ~(0xFFFF << 16);
981 shm |= (p->vbv_size << 16);
982 }
983 s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
984 return 0;
985}
986
987/* Initialize decoding */
988int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
989{
990 struct s5p_mfc_dev *dev = ctx->dev;
991
992 s5p_mfc_set_shared_buffer(ctx);
993 /* Setup loop filter, for decoding this is only valid for MPEG4 */
994 if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
995 mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
996 else
997 mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
998 mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
999 S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
1000 S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
1001 S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
1002 S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
1003 mfc_write(dev,
1004 ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
1005 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1006 return 0;
1007}
1008
1009static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
1010{
1011 struct s5p_mfc_dev *dev = ctx->dev;
1012 unsigned int dpb;
1013
1014 if (flush)
1015 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
1016 S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
1017 else
1018 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
1019 ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
1020 mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
1021}
1022
1023/* Decode a single frame */
1024int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
1025 enum s5p_mfc_decode_arg last_frame)
1026{
1027 struct s5p_mfc_dev *dev = ctx->dev;
1028
1029 mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
1030 s5p_mfc_set_shared_buffer(ctx);
1031 s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
1032 /* Issue different commands to instance basing on whether it
1033 * is the last frame or not. */
1034 switch (last_frame) {
1035 case MFC_DEC_FRAME:
1036 mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
1037 S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1038 break;
1039 case MFC_DEC_LAST_FRAME:
1040 mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
1041 S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1042 break;
1043 case MFC_DEC_RES_CHANGE:
1044 mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
1045 S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
1046 S5P_FIMV_SI_CH0_INST_ID);
1047 break;
1048 }
1049 mfc_debug(2, "Decoding a usual frame\n");
1050 return 0;
1051}
1052
1053int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
1054{
1055 struct s5p_mfc_dev *dev = ctx->dev;
1056
1057 if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
1058 s5p_mfc_set_enc_params_h264(ctx);
1059 else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
1060 s5p_mfc_set_enc_params_mpeg4(ctx);
1061 else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
1062 s5p_mfc_set_enc_params_h263(ctx);
1063 else {
1064 mfc_err("Unknown codec for encoding (%x)\n",
1065 ctx->codec_mode);
1066 return -EINVAL;
1067 }
1068 s5p_mfc_set_shared_buffer(ctx);
1069 mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
1070 (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1071 return 0;
1072}
1073
1074/* Encode a single frame */
1075int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
1076{
1077 struct s5p_mfc_dev *dev = ctx->dev;
1078 /* memory structure cur. frame */
1079 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
1080 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
1081 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
1082 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
1083 s5p_mfc_set_shared_buffer(ctx);
1084 mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
1085 (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1086 return 0;
1087}
1088
1089static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
1090{
1091 unsigned long flags;
1092 int new_ctx;
1093 int cnt;
1094
1095 spin_lock_irqsave(&dev->condlock, flags);
1096 new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
1097 cnt = 0;
1098 while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
1099 new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
1100 if (++cnt > MFC_NUM_CONTEXTS) {
1101 /* No contexts to run */
1102 spin_unlock_irqrestore(&dev->condlock, flags);
1103 return -EAGAIN;
1104 }
1105 }
1106 spin_unlock_irqrestore(&dev->condlock, flags);
1107 return new_ctx;
1108}
1109
1110static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
1111{
1112 struct s5p_mfc_dev *dev = ctx->dev;
1113
1114 s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
1115 dev->curr_ctx = ctx->num;
1116 s5p_mfc_clean_ctx_int_flags(ctx);
1117 s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
1118}
1119
1120static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
1121{
1122 struct s5p_mfc_dev *dev = ctx->dev;
1123 struct s5p_mfc_buf *temp_vb;
1124 unsigned long flags;
1125 unsigned int index;
1126
1127 spin_lock_irqsave(&dev->irqlock, flags);
1128 /* Frames are being decoded */
1129 if (list_empty(&ctx->src_queue)) {
1130 mfc_debug(2, "No src buffers\n");
1131 spin_unlock_irqrestore(&dev->irqlock, flags);
1132 return -EAGAIN;
1133 }
1134 /* Get the next source buffer */
1135 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1136 temp_vb->used = 1;
1137 s5p_mfc_set_dec_stream_buffer(ctx,
1138 vb2_dma_contig_plane_paddr(temp_vb->b, 0), ctx->consumed_stream,
1139 temp_vb->b->v4l2_planes[0].bytesused);
1140 spin_unlock_irqrestore(&dev->irqlock, flags);
1141 index = temp_vb->b->v4l2_buf.index;
1142 dev->curr_ctx = ctx->num;
1143 s5p_mfc_clean_ctx_int_flags(ctx);
1144 if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
1145 last_frame = MFC_DEC_LAST_FRAME;
1146 mfc_debug(2, "Setting ctx->state to FINISHING\n");
1147 ctx->state = MFCINST_FINISHING;
1148 }
1149 s5p_mfc_decode_one_frame(ctx, last_frame);
1150 return 0;
1151}
1152
1153static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
1154{
1155 struct s5p_mfc_dev *dev = ctx->dev;
1156 unsigned long flags;
1157 struct s5p_mfc_buf *dst_mb;
1158 struct s5p_mfc_buf *src_mb;
1159 unsigned long src_y_addr, src_c_addr, dst_addr;
1160 unsigned int dst_size;
1161
1162 spin_lock_irqsave(&dev->irqlock, flags);
1163 if (list_empty(&ctx->src_queue)) {
1164 mfc_debug(2, "no src buffers\n");
1165 spin_unlock_irqrestore(&dev->irqlock, flags);
1166 return -EAGAIN;
1167 }
1168 if (list_empty(&ctx->dst_queue)) {
1169 mfc_debug(2, "no dst buffers\n");
1170 spin_unlock_irqrestore(&dev->irqlock, flags);
1171 return -EAGAIN;
1172 }
1173 src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1174 src_mb->used = 1;
1175 src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
1176 src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
1177 s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
1178 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
1179 dst_mb->used = 1;
1180 dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
1181 dst_size = vb2_plane_size(dst_mb->b, 0);
1182 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
1183 spin_unlock_irqrestore(&dev->irqlock, flags);
1184 dev->curr_ctx = ctx->num;
1185 s5p_mfc_clean_ctx_int_flags(ctx);
1186 s5p_mfc_encode_one_frame(ctx);
1187 return 0;
1188}
1189
1190static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
1191{
1192 struct s5p_mfc_dev *dev = ctx->dev;
1193 unsigned long flags;
1194 struct s5p_mfc_buf *temp_vb;
1195
1196 /* Initializing decoding - parsing header */
1197 spin_lock_irqsave(&dev->irqlock, flags);
1198 mfc_debug(2, "Preparing to init decoding\n");
1199 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1200 s5p_mfc_set_dec_desc_buffer(ctx);
1201 mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
1202 s5p_mfc_set_dec_stream_buffer(ctx,
1203 vb2_dma_contig_plane_paddr(temp_vb->b, 0),
1204 0, temp_vb->b->v4l2_planes[0].bytesused);
1205 spin_unlock_irqrestore(&dev->irqlock, flags);
1206 dev->curr_ctx = ctx->num;
1207 s5p_mfc_clean_ctx_int_flags(ctx);
1208 s5p_mfc_init_decode(ctx);
1209}
1210
1211static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
1212{
1213 struct s5p_mfc_dev *dev = ctx->dev;
1214 unsigned long flags;
1215 struct s5p_mfc_buf *dst_mb;
1216 unsigned long dst_addr;
1217 unsigned int dst_size;
1218
1219 s5p_mfc_set_enc_ref_buffer(ctx);
1220 spin_lock_irqsave(&dev->irqlock, flags);
1221 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
1222 dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
1223 dst_size = vb2_plane_size(dst_mb->b, 0);
1224 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
1225 spin_unlock_irqrestore(&dev->irqlock, flags);
1226 dev->curr_ctx = ctx->num;
1227 s5p_mfc_clean_ctx_int_flags(ctx);
1228 s5p_mfc_init_encode(ctx);
1229}
1230
1231static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
1232{
1233 struct s5p_mfc_dev *dev = ctx->dev;
1234 unsigned long flags;
1235 struct s5p_mfc_buf *temp_vb;
1236 int ret;
1237
1238 /*
1239 * Header was parsed now starting processing
1240 * First set the output frame buffers
1241 */
1242 if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
1243 mfc_err("It seems that not all destionation buffers were "
1244 "mmaped\nMFC requires that all destination are mmaped "
1245 "before starting processing\n");
1246 return -EAGAIN;
1247 }
1248 spin_lock_irqsave(&dev->irqlock, flags);
1249 if (list_empty(&ctx->src_queue)) {
1250 mfc_err("Header has been deallocated in the middle of"
1251 " initialization\n");
1252 spin_unlock_irqrestore(&dev->irqlock, flags);
1253 return -EIO;
1254 }
1255 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1256 mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
1257 s5p_mfc_set_dec_stream_buffer(ctx,
1258 vb2_dma_contig_plane_paddr(temp_vb->b, 0),
1259 0, temp_vb->b->v4l2_planes[0].bytesused);
1260 spin_unlock_irqrestore(&dev->irqlock, flags);
1261 dev->curr_ctx = ctx->num;
1262 s5p_mfc_clean_ctx_int_flags(ctx);
1263 ret = s5p_mfc_set_dec_frame_buffer(ctx);
1264 if (ret) {
1265 mfc_err("Failed to alloc frame mem\n");
1266 ctx->state = MFCINST_ERROR;
1267 }
1268 return ret;
1269}
1270
1271/* Try running an operation on hardware */
1272void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
1273{
1274 struct s5p_mfc_ctx *ctx;
1275 int new_ctx;
1276 unsigned int ret = 0;
1277
1278 if (test_bit(0, &dev->enter_suspend)) {
1279 mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
1280 return;
1281 }
1282 /* Check whether hardware is not running */
1283 if (test_and_set_bit(0, &dev->hw_lock) != 0) {
1284 /* This is perfectly ok, the scheduled ctx should wait */
1285 mfc_debug(1, "Couldn't lock HW\n");
1286 return;
1287 }
1288 /* Choose the context to run */
1289 new_ctx = s5p_mfc_get_new_ctx(dev);
1290 if (new_ctx < 0) {
1291 /* No contexts to run */
1292 if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
1293 mfc_err("Failed to unlock hardware\n");
1294 return;
1295 }
1296 mfc_debug(1, "No ctx is scheduled to be run\n");
1297 return;
1298 }
1299 ctx = dev->ctx[new_ctx];
1300 /* Got context to run in ctx */
1301 /*
1302 * Last frame has already been sent to MFC.
1303 * Now obtaining frames from MFC buffer
1304 */
1305 s5p_mfc_clock_on();
1306 if (ctx->type == MFCINST_DECODER) {
1307 s5p_mfc_set_dec_desc_buffer(ctx);
1308 switch (ctx->state) {
1309 case MFCINST_FINISHING:
1310 s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
1311 break;
1312 case MFCINST_RUNNING:
1313 ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
1314 break;
1315 case MFCINST_INIT:
1316 s5p_mfc_clean_ctx_int_flags(ctx);
1317 ret = s5p_mfc_open_inst_cmd(ctx);
1318 break;
1319 case MFCINST_RETURN_INST:
1320 s5p_mfc_clean_ctx_int_flags(ctx);
1321 ret = s5p_mfc_close_inst_cmd(ctx);
1322 break;
1323 case MFCINST_GOT_INST:
1324 s5p_mfc_run_init_dec(ctx);
1325 break;
1326 case MFCINST_HEAD_PARSED:
1327 ret = s5p_mfc_run_init_dec_buffers(ctx);
1328 mfc_debug(1, "head parsed\n");
1329 break;
1330 case MFCINST_RES_CHANGE_INIT:
1331 s5p_mfc_run_res_change(ctx);
1332 break;
1333 case MFCINST_RES_CHANGE_FLUSH:
1334 s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
1335 break;
1336 case MFCINST_RES_CHANGE_END:
1337 mfc_debug(2, "Finished remaining frames after resolution change\n");
1338 ctx->capture_state = QUEUE_FREE;
1339 mfc_debug(2, "Will re-init the codec\n");
1340 s5p_mfc_run_init_dec(ctx);
1341 break;
1342 default:
1343 ret = -EAGAIN;
1344 }
1345 } else if (ctx->type == MFCINST_ENCODER) {
1346 switch (ctx->state) {
1347 case MFCINST_FINISHING:
1348 case MFCINST_RUNNING:
1349 ret = s5p_mfc_run_enc_frame(ctx);
1350 break;
1351 case MFCINST_INIT:
1352 s5p_mfc_clean_ctx_int_flags(ctx);
1353 ret = s5p_mfc_open_inst_cmd(ctx);
1354 break;
1355 case MFCINST_RETURN_INST:
1356 s5p_mfc_clean_ctx_int_flags(ctx);
1357 ret = s5p_mfc_close_inst_cmd(ctx);
1358 break;
1359 case MFCINST_GOT_INST:
1360 s5p_mfc_run_init_enc(ctx);
1361 break;
1362 default:
1363 ret = -EAGAIN;
1364 }
1365 } else {
1366 mfc_err("Invalid context type: %d\n", ctx->type);
1367 ret = -EAGAIN;
1368 }
1369
1370 if (ret) {
1371 /* Free hardware lock */
1372 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
1373 mfc_err("Failed to unlock hardware\n");
1374
1375 /* This is in deed imporant, as no operation has been
1376 * scheduled, reduce the clock count as no one will
1377 * ever do this, because no interrupt related to this try_run
1378 * will ever come from hardware. */
1379 s5p_mfc_clock_off();
1380 }
1381}
1382
1383
1384void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
1385{
1386 struct s5p_mfc_buf *b;
1387 int i;
1388
1389 while (!list_empty(lh)) {
1390 b = list_entry(lh->next, struct s5p_mfc_buf, list);
1391 for (i = 0; i < b->b->num_planes; i++)
1392 vb2_set_plane_payload(b->b, i, 0);
1393 vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
1394 list_del(&b->list);
1395 }
1396}
1397
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
new file mode 100644
index 000000000000..db83836e6a9f
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
@@ -0,0 +1,91 @@
1/*
2 * drivers/media/video/samsung/mfc5/s5p_mfc_opr.h
3 *
4 * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
5 * Contains declarations of hw related functions.
6 *
7 * Kamil Debski, Copyright (C) 2011 Samsung Electronics
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#ifndef S5P_MFC_OPR_H_
16#define S5P_MFC_OPR_H_
17
18#include "s5p_mfc_common.h"
19
20int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
21int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
22
23/* Decoding functions */
24int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
25int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
26 unsigned int start_num_byte,
27 unsigned int buf_size);
28
29/* Encoding functions */
30void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
31 unsigned long y_addr, unsigned long c_addr);
32int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
33 unsigned long addr, unsigned int size);
34void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
35 unsigned long *y_addr, unsigned long *c_addr);
36int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
37
38int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
39 enum s5p_mfc_decode_arg last_frame);
40int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
41
42/* Memory allocation */
43int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
44void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
45void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
46
47int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
48void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
49
50int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
51void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
52
53void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
54void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
55
56#define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
57 S5P_FIMV_SI_DISPLAY_Y_ADR) << \
58 MFC_OFFSET_SHIFT)
59#define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \
60 S5P_FIMV_SI_DISPLAY_Y_ADR) << \
61 MFC_OFFSET_SHIFT)
62#define s5p_mfc_get_dspl_status() readl(dev->regs_base + \
63 S5P_FIMV_SI_DISPLAY_STATUS)
64#define s5p_mfc_get_frame_type() (readl(dev->regs_base + \
65 S5P_FIMV_DECODE_FRAME_TYPE) \
66 & S5P_FIMV_DECODE_FRAME_MASK)
67#define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
68 S5P_FIMV_SI_CONSUMED_BYTES)
69#define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
70 S5P_FIMV_RISC2HOST_CMD) & \
71 S5P_FIMV_RISC2HOST_CMD_MASK)
72#define s5p_mfc_get_int_err() readl(dev->regs_base + \
73 S5P_FIMV_RISC2HOST_ARG2)
74#define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
75 S5P_FIMV_ERR_DEC_SHIFT)
76#define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
77 S5P_FIMV_ERR_DSPL_SHIFT)
78#define s5p_mfc_get_img_width() readl(dev->regs_base + \
79 S5P_FIMV_SI_HRESOL)
80#define s5p_mfc_get_img_height() readl(dev->regs_base + \
81 S5P_FIMV_SI_VRESOL)
82#define s5p_mfc_get_dpb_count() readl(dev->regs_base + \
83 S5P_FIMV_SI_BUF_NUMBER)
84#define s5p_mfc_get_inst_no() readl(dev->regs_base + \
85 S5P_FIMV_RISC2HOST_ARG1)
86#define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \
87 S5P_FIMV_ENC_SI_STRM_SIZE)
88#define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
89 S5P_FIMV_ENC_SI_SLICE_TYPE)
90
91#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
new file mode 100644
index 000000000000..f6a3035c4fb7
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
@@ -0,0 +1,117 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/clk.h>
14#include <linux/err.h>
15#include <linux/platform_device.h>
16#ifdef CONFIG_PM_RUNTIME
17#include <linux/pm_runtime.h>
18#endif
19#include "s5p_mfc_common.h"
20#include "s5p_mfc_debug.h"
21#include "s5p_mfc_pm.h"
22
23#define MFC_CLKNAME "sclk_mfc"
24#define MFC_GATE_CLK_NAME "mfc"
25
26#define CLK_DEBUG
27
28static struct s5p_mfc_pm *pm;
29static struct s5p_mfc_dev *p_dev;
30
31#ifdef CLK_DEBUG
32atomic_t clk_ref;
33#endif
34
35int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
36{
37 int ret = 0;
38
39 pm = &dev->pm;
40 p_dev = dev;
41 pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME);
42 if (IS_ERR(pm->clock_gate)) {
43 mfc_err("Failed to get clock-gating control\n");
44 ret = -ENOENT;
45 goto err_g_ip_clk;
46 }
47 pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
48 if (IS_ERR(pm->clock)) {
49 mfc_err("Failed to get MFC clock\n");
50 ret = -ENOENT;
51 goto err_g_ip_clk_2;
52 }
53 atomic_set(&pm->power, 0);
54#ifdef CONFIG_PM_RUNTIME
55 pm->device = &dev->plat_dev->dev;
56 pm_runtime_enable(pm->device);
57#endif
58#ifdef CLK_DEBUG
59 atomic_set(&clk_ref, 0);
60#endif
61 return 0;
62err_g_ip_clk_2:
63 clk_put(pm->clock_gate);
64err_g_ip_clk:
65 return ret;
66}
67
68void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
69{
70 clk_put(pm->clock_gate);
71 clk_put(pm->clock);
72#ifdef CONFIG_PM_RUNTIME
73 pm_runtime_disable(pm->device);
74#endif
75}
76
77int s5p_mfc_clock_on(void)
78{
79 int ret;
80#ifdef CLK_DEBUG
81 atomic_inc(&clk_ref);
82 mfc_debug(3, "+ %d", atomic_read(&clk_ref));
83#endif
84 ret = clk_enable(pm->clock_gate);
85 return ret;
86}
87
88void s5p_mfc_clock_off(void)
89{
90#ifdef CLK_DEBUG
91 atomic_dec(&clk_ref);
92 mfc_debug(3, "- %d", atomic_read(&clk_ref));
93#endif
94 clk_disable(pm->clock_gate);
95}
96
97int s5p_mfc_power_on(void)
98{
99#ifdef CONFIG_PM_RUNTIME
100 return pm_runtime_get_sync(pm->device);
101#else
102 atomic_set(&pm->power, 1);
103 return 0;
104#endif
105}
106
107int s5p_mfc_power_off(void)
108{
109#ifdef CONFIG_PM_RUNTIME
110 return pm_runtime_put_sync(pm->device);
111#else
112 atomic_set(&pm->power, 0);
113 return 0;
114#endif
115}
116
117
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.h b/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
new file mode 100644
index 000000000000..5107914f27e4
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
@@ -0,0 +1,24 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_PM_H_
14#define S5P_MFC_PM_H_
15
16int s5p_mfc_init_pm(struct s5p_mfc_dev *dev);
17void s5p_mfc_final_pm(struct s5p_mfc_dev *dev);
18
19int s5p_mfc_clock_on(void);
20void s5p_mfc_clock_off(void);
21int s5p_mfc_power_on(void);
22int s5p_mfc_power_off(void);
23
24#endif /* S5P_MFC_PM_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
new file mode 100644
index 000000000000..91fdbac8c37a
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
@@ -0,0 +1,47 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifdef CONFIG_ARCH_EXYNOS4
14#include <linux/dma-mapping.h>
15#endif
16#include <linux/io.h>
17#include "s5p_mfc_common.h"
18#include "s5p_mfc_debug.h"
19
20int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
21{
22 struct s5p_mfc_dev *dev = ctx->dev;
23 void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
24
25 ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
26 SHARED_BUF_SIZE);
27 if (IS_ERR(ctx->shm_alloc)) {
28 mfc_err("failed to allocate shared memory\n");
29 return PTR_ERR(ctx->shm_alloc);
30 }
31 /* shm_ofs only keeps the offset from base (port a) */
32 ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
33 - dev->bank1;
34 BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
35 ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
36 if (!ctx->shm) {
37 vb2_dma_contig_memops.put(ctx->shm_alloc);
38 ctx->shm_ofs = 0;
39 ctx->shm_alloc = NULL;
40 mfc_err("failed to virt addr of shared memory\n");
41 return -ENOMEM;
42 }
43 memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
44 wmb();
45 return 0;
46}
47
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
new file mode 100644
index 000000000000..764eac6bcc4c
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
@@ -0,0 +1,91 @@
1/*
2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
3 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef S5P_MFC_SHM_H_
14#define S5P_MFC_SHM_H_
15
16enum MFC_SHM_OFS
17{
18 EXTENEDED_DECODE_STATUS = 0x00, /* D */
19 SET_FRAME_TAG = 0x04, /* D */
20 GET_FRAME_TAG_TOP = 0x08, /* D */
21 GET_FRAME_TAG_BOT = 0x0C, /* D */
22 PIC_TIME_TOP = 0x10, /* D */
23 PIC_TIME_BOT = 0x14, /* D */
24 START_BYTE_NUM = 0x18, /* D */
25
26 CROP_INFO_H = 0x20, /* D */
27 CROP_INFO_V = 0x24, /* D */
28 EXT_ENC_CONTROL = 0x28, /* E */
29 ENC_PARAM_CHANGE = 0x2C, /* E */
30 RC_VOP_TIMING = 0x30, /* E, MPEG4 */
31 HEC_PERIOD = 0x34, /* E, MPEG4 */
32 METADATA_ENABLE = 0x38, /* C */
33 METADATA_STATUS = 0x3C, /* C */
34 METADATA_DISPLAY_INDEX = 0x40, /* C */
35 EXT_METADATA_START_ADDR = 0x44, /* C */
36 PUT_EXTRADATA = 0x48, /* C */
37 EXTRADATA_ADDR = 0x4C, /* C */
38
39 ALLOC_LUMA_DPB_SIZE = 0x64, /* D */
40 ALLOC_CHROMA_DPB_SIZE = 0x68, /* D */
41 ALLOC_MV_SIZE = 0x6C, /* D */
42 P_B_FRAME_QP = 0x70, /* E */
43 SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
44 ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
45 EXTENDED_SAR = 0x78, /* E, H.264, depned on
46 ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
47 DISP_PIC_PROFILE = 0x7C, /* D */
48 FLUSH_CMD_TYPE = 0x80, /* C */
49 FLUSH_CMD_INBUF1 = 0x84, /* C */
50 FLUSH_CMD_INBUF2 = 0x88, /* C */
51 FLUSH_CMD_OUTBUF = 0x8C, /* E */
52 NEW_RC_BIT_RATE = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
53 depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
54 NEW_RC_FRAME_RATE = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
55 depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
56 NEW_I_PERIOD = 0x98, /* E, format as I_FRM_CTRL(0xC504)
57 depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
58 H264_I_PERIOD = 0x9C, /* E, H.264, open GOP */
59 RC_CONTROL_CONFIG = 0xA0, /* E */
60 BATCH_INPUT_ADDR = 0xA4, /* E */
61 BATCH_OUTPUT_ADDR = 0xA8, /* E */
62 BATCH_OUTPUT_SIZE = 0xAC, /* E */
63 MIN_LUMA_DPB_SIZE = 0xB0, /* D */
64 DEVICE_FORMAT_ID = 0xB4, /* C */
65 H264_POC_TYPE = 0xB8, /* D */
66 MIN_CHROMA_DPB_SIZE = 0xBC, /* D */
67 DISP_PIC_FRAME_TYPE = 0xC0, /* D */
68 FREE_LUMA_DPB = 0xC4, /* D, VC1 MPEG4 */
69 ASPECT_RATIO_INFO = 0xC8, /* D, MPEG4 */
70 EXTENDED_PAR = 0xCC, /* D, MPEG4 */
71 DBG_HISTORY_INPUT0 = 0xD0, /* C */
72 DBG_HISTORY_INPUT1 = 0xD4, /* C */
73 DBG_HISTORY_OUTPUT = 0xD8, /* C */
74 HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
75};
76
77int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
78
79#define s5p_mfc_write_shm(ctx, x, ofs) \
80 do { \
81 writel(x, (ctx->shm + ofs)); \
82 wmb(); \
83 } while (0)
84
85static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
86{
87 rmb();
88 return readl(ctx->shm + ofs);
89}
90
91#endif /* S5P_MFC_SHM_H_ */